From f40e33203245891b3b000e1b35b417e6fd546876 Mon Sep 17 00:00:00 2001 From: core Date: Tue, 8 Jul 2025 20:12:01 -0400 Subject: [PATCH] chore(part): part fix #1 --- crates/unified/src/attachment.rs | 7 +- crates/unified/src/client/key_input.rs | 50 ++- crates/unified/src/client/mod.rs | 25 +- crates/unified/src/client/net.rs | 1 - crates/unified/src/client/particles/mod.rs | 4 +- crates/unified/src/client/parts.rs | 36 +- .../src/client/planet/incoming_planets.rs | 21 +- .../unified/src/client/planet/indicators.rs | 69 +++- crates/unified/src/client/planet/mod.rs | 2 +- crates/unified/src/client/starfield.rs | 53 ++- crates/unified/src/client/zoom.rs | 50 ++- crates/unified/src/config/mod.rs | 2 +- crates/unified/src/config/part.rs | 6 +- crates/unified/src/config/planet.rs | 3 +- crates/unified/src/config/world.rs | 4 +- crates/unified/src/ecs.rs | 11 +- crates/unified/src/lib.rs | 8 +- crates/unified/src/main.rs | 7 +- crates/unified/src/particle_editor/ecs.rs | 13 +- crates/unified/src/particle_editor/hooks.rs | 9 +- crates/unified/src/particle_editor/mod.rs | 387 +++++++++++------- crates/unified/src/particle_editor/spawn.rs | 57 ++- crates/unified/src/particles.rs | 40 +- crates/unified/src/server/earth_parts.rs | 34 +- crates/unified/src/server/gravity.rs | 2 - crates/unified/src/server/mod.rs | 10 +- crates/unified/src/server/part.rs | 138 +------ crates/unified/src/server/player.rs | 36 +- crates/unified/src/server_plugins.rs | 18 +- crates/unified/src/shared_plugins.rs | 7 +- 30 files changed, 614 insertions(+), 496 deletions(-) diff --git a/crates/unified/src/attachment.rs b/crates/unified/src/attachment.rs index ad67e85085d4da75f2e272559511efa4729f58c6..fe3656be8e6986cd35cb79ea48052048560a25ce 100644 --- a/crates/unified/src/attachment.rs +++ b/crates/unified/src/attachment.rs @@ -1,8 +1,8 @@ -use std::ops::Deref; use bevy::asset::processor::ErasedProcessor; use bevy::ecs::entity::MapEntities; use bevy::prelude::*; use serde::{Deserialize, Serialize}; +use std::ops::Deref; #[derive(Component, Serialize, Deserialize)] /// The primary component for a ship structure @@ -16,12 +16,11 @@ pub struct Parts(#[entities] Vec); #[relationship(relationship_target = Parts)] pub struct PartInShip(#[entities] Entity); - #[derive(Component, Serialize, Deserialize)] #[require(Transform)] pub struct Joint { pub id: JointId, - pub transform: Transform + pub transform: Transform, } #[derive(Component, Serialize, Deserialize)] pub struct Peer(#[entities] Entity); @@ -48,4 +47,4 @@ impl JointId { } #[derive(Serialize, Deserialize, Component)] -pub struct JointSnapFor(#[entities] pub Entity); \ No newline at end of file +pub struct JointSnapFor(#[entities] pub Entity); diff --git a/crates/unified/src/client/key_input.rs b/crates/unified/src/client/key_input.rs index a7baf84a5dff24e5f0027aa1690fbd64c61b1a15..0a0e91771417efbcdad8774081559b15d177b823 100644 --- a/crates/unified/src/client/key_input.rs +++ b/crates/unified/src/client/key_input.rs @@ -1,17 +1,20 @@ -use bevy::{ - app::{App, Update}, - ecs::{event::EventWriter, system::Res}, - input::{ButtonInput, keyboard::KeyCode}, -}; +use crate::attachment::{Joint, JointSnapFor}; +use crate::ecs::{Part, ThrustEvent}; use bevy::color::palettes::css::{FUCHSIA, GREEN}; use bevy::dev_tools::picking_debug::DebugPickingMode; use bevy::gizmos::AppGizmoBuilder; use bevy::log::{debug, info}; use bevy::math::Vec3Swizzles; -use bevy::prelude::{ChildOf, GizmoConfigGroup, Gizmos, GlobalTransform, IntoScheduleConfigs, Query, Reflect, ResMut, Resource, Transform, With}; +use bevy::prelude::{ + ChildOf, GizmoConfigGroup, Gizmos, GlobalTransform, IntoScheduleConfigs, Query, Reflect, + ResMut, Resource, Transform, With, +}; +use bevy::{ + app::{App, Update}, + ecs::{event::EventWriter, system::Res}, + input::{ButtonInput, keyboard::KeyCode}, +}; use bevy_rapier2d::render::DebugRenderContext; -use crate::attachment::{Joint, JointSnapFor}; -use crate::ecs::{Part, ThrustEvent}; pub fn key_input_plugin(app: &mut App) { app.add_systems(Update, directional_keys) @@ -40,11 +43,7 @@ fn debug_render_keybind( } } - -fn directional_keys( - keys: Res>, - mut thrust_event: EventWriter, -) { +fn directional_keys(keys: Res>, mut thrust_event: EventWriter) { if keys.just_pressed(KeyCode::KeyW) || keys.just_pressed(KeyCode::ArrowUp) { thrust_event.write(ThrustEvent::Up(true)); } else if keys.just_released(KeyCode::KeyW) || keys.just_released(KeyCode::ArrowUp) { @@ -70,20 +69,19 @@ fn directional_keys( } } -fn draw_attachment_debug(joints: Query<&GlobalTransform, With>, snaps: Query<&GlobalTransform, With>, mut gizmos: Gizmos, mut state: ResMut) { - if !state.0 { return; } +fn draw_attachment_debug( + joints: Query<&GlobalTransform, With>, + snaps: Query<&GlobalTransform, With>, + mut gizmos: Gizmos, + mut state: ResMut, +) { + if !state.0 { + return; + } for joint_target in joints.iter() { - gizmos.cross_2d( - joint_target.translation().xy(), - 4.0, - FUCHSIA - ); + gizmos.cross_2d(joint_target.translation().xy(), 4.0, FUCHSIA); } for joint_snap in snaps.iter() { - gizmos.cross_2d( - joint_snap.translation().xy(), - 4.0, - GREEN - ); + gizmos.cross_2d(joint_snap.translation().xy(), 4.0, GREEN); } -} \ No newline at end of file +} diff --git a/crates/unified/src/client/mod.rs b/crates/unified/src/client/mod.rs index 9bc46dd20e2b312935167b3a4d4e1f0b87464e7a..ee3eb746704e68d3753830dfbf9b4db2679c4124 100644 --- a/crates/unified/src/client/mod.rs +++ b/crates/unified/src/client/mod.rs @@ -1,16 +1,17 @@ mod colors; -mod parts; mod key_input; mod net; +mod particles; +mod parts; +mod planet; mod starfield; mod ui; -mod planet; mod zoom; -mod particles; -use crate::client::parts::parts_plugin; -use planet::incoming_planets::incoming_planets_plugin; use crate::client::key_input::key_input_plugin; +use crate::client::net::set_config; +use crate::client::parts::parts_plugin; +use crate::client::planet::indicators::indicators_plugin; use crate::client::starfield::starfield_plugin; use crate::client::ui::ui_plugin; use crate::client::zoom::zoom_plugin; @@ -24,8 +25,7 @@ use bevy::prelude::*; use bevy::window::PrimaryWindow; use bevy_egui::EguiPlugin; use bevy_replicon::shared::server_entity_map::ServerEntityMap; -use crate::client::net::set_config; -use crate::client::planet::indicators::indicators_plugin; +use planet::incoming_planets::incoming_planets_plugin; pub struct ClientPlugin { pub server: String, @@ -71,15 +71,16 @@ fn find_me( for (entity, player, part) in q_clients.iter() { if player.client == entity { commands.entity(entity).insert(Me); - let mut heart_sprite = Sprite::from_image(asset_server.load("sprites/hearty_heart.png")); + let mut heart_sprite = + Sprite::from_image(asset_server.load("sprites/hearty_heart.png")); heart_sprite.custom_size = Some(Vec2::new(part.width, part.height)); heart_sprite.color = Color::srgb(20.0, 0.0, 0.0); commands.spawn(( - ChildOf(entity), - heart_sprite, - Transform::from_xyz(0.0, 0.0, 10.0) - )); + ChildOf(entity), + heart_sprite, + Transform::from_xyz(0.0, 0.0, 10.0), + )); } } } diff --git a/crates/unified/src/client/net.rs b/crates/unified/src/client/net.rs index ad06d21bfd40362f9ff7bb0cff6f9ebfd1cec488..213ca24b560e87a17cf536cdaa6058fa4cb2a0b9 100644 --- a/crates/unified/src/client/net.rs +++ b/crates/unified/src/client/net.rs @@ -10,7 +10,6 @@ pub fn set_config(mut q: Query<&mut TransportConfig, Added>) { } } - pub fn on_connecting( trigger: Trigger, names: Query<&Name>, diff --git a/crates/unified/src/client/particles/mod.rs b/crates/unified/src/client/particles/mod.rs index 6aca94747f7c514c80878d20026657b352b25632..f947aceb7c63108c14fc53c2c8c9a898d393b091 100644 --- a/crates/unified/src/client/particles/mod.rs +++ b/crates/unified/src/client/particles/mod.rs @@ -3,7 +3,5 @@ use bevy::app::{App, Plugin}; pub struct ParticlePlugin; impl Plugin for ParticlePlugin { - fn build(&self, app: &mut App) { - - } + fn build(&self, app: &mut App) {} } diff --git a/crates/unified/src/client/parts.rs b/crates/unified/src/client/parts.rs index cef5c307932fd5584022dd62802be36e590208e5..b9a883e788c1af25461961c8de3c439c21cca1d2 100644 --- a/crates/unified/src/client/parts.rs +++ b/crates/unified/src/client/parts.rs @@ -1,9 +1,9 @@ -use std::fmt::Debug; +use crate::client::Me; use crate::ecs::{CursorWorldCoordinates, DragRequestEvent, Part}; use bevy::prelude::*; use bevy_rapier2d::dynamics::MassProperties; use bevy_rapier2d::prelude::{AdditionalMassProperties, ReadMassProperties, RigidBody}; -use crate::client::Me; +use std::fmt::Debug; pub fn parts_plugin(app: &mut App) { app.insert_resource(DragResource(None)); @@ -63,20 +63,36 @@ fn handle_updated_parts( #[derive(Resource)] struct DragResource(Option); - -fn on_part_click(ev: Trigger>, sprites: Query<&Sprite, Without>, mut drag: ResMut) { - if ev.button != PointerButton::Primary { return; }; - let Ok(sprite) = sprites.get(ev.target()) else { return; }; +fn on_part_click( + ev: Trigger>, + sprites: Query<&Sprite, Without>, + mut drag: ResMut, +) { + if ev.button != PointerButton::Primary { + return; + }; + let Ok(sprite) = sprites.get(ev.target()) else { + return; + }; drag.0 = Some(ev.target()); } -fn on_part_release(ev: Trigger>, mut drag: ResMut, mut events: EventWriter, cursor: Res) { - if ev.button != PointerButton::Primary { return; }; +fn on_part_release( + ev: Trigger>, + mut drag: ResMut, + mut events: EventWriter, + cursor: Res, +) { + if ev.button != PointerButton::Primary { + return; + }; - if let Some(e) = drag.0 && let Some(c) = cursor.0 { + if let Some(e) = drag.0 + && let Some(c) = cursor.0 + { debug!(?e, ?c, "sending drag request"); events.write(DragRequestEvent(e, c)); } drag.0 = None; -} \ No newline at end of file +} diff --git a/crates/unified/src/client/planet/incoming_planets.rs b/crates/unified/src/client/planet/incoming_planets.rs index 62c1ebdb9484d22b86685c270b3147ce84e1f8ee..684c581a1c5663c26bd8a4e6fb190d01bd895ab1 100644 --- a/crates/unified/src/client/planet/incoming_planets.rs +++ b/crates/unified/src/client/planet/incoming_planets.rs @@ -11,7 +11,7 @@ fn handle_incoming_planets( new_planets: Query<(Entity, &Planet), Added>, asset_server: Res, meshes: ResMut>, - materials: ResMut> + materials: ResMut>, ) { for (new_entity, new_planet) in new_planets.iter() { let mut sprite = Sprite::from_image(asset_server.load(&new_planet.sprite)); @@ -21,11 +21,11 @@ fn handle_incoming_planets( sprite.color = c; } - let mut commands = commands - .entity(new_entity); + let mut commands = commands.entity(new_entity); - commands.insert(AdditionalMassProperties::Mass(new_planet.mass)) - .insert(sprite); + commands + .insert(AdditionalMassProperties::Mass(new_planet.mass)) + .insert(sprite); trace!(?new_planet, "prepared new planet"); } @@ -35,7 +35,7 @@ fn handle_updated_planets( updated_planets: Query<(Entity, &Planet), Changed>, asset_server: Res, meshes: ResMut>, - materials: ResMut> + materials: ResMut>, ) { for (updated_entity, updated_planet) in updated_planets.iter() { let mut sprite = Sprite::from_image(asset_server.load(&updated_planet.sprite)); @@ -44,18 +44,19 @@ fn handle_updated_planets( updated_planet.radius * 2.0, )); - if let Some(SpecialSpriteProperties::ForceColor(c)) = updated_planet.special_sprite_properties { + if let Some(SpecialSpriteProperties::ForceColor(c)) = + updated_planet.special_sprite_properties + { sprite.color = c; } let mut commands = commands.entity(updated_entity); - commands.remove::() + commands + .remove::() .insert(AdditionalMassProperties::Mass(updated_planet.mass)) .remove::() .insert(sprite); - - trace!(?updated_planet, "updated planet"); } } diff --git a/crates/unified/src/client/planet/indicators.rs b/crates/unified/src/client/planet/indicators.rs index 07192df47a9308e38cd67083f4294f814fcf0db8..068bf76bd9a1577094550e573ce9c4f46a0d1462 100644 --- a/crates/unified/src/client/planet/indicators.rs +++ b/crates/unified/src/client/planet/indicators.rs @@ -1,8 +1,8 @@ -use bevy::prelude::*; -use bevy::window::PrimaryWindow; use crate::client::Me; use crate::config::planet::Planet; use crate::ecs::MainCamera; +use bevy::prelude::*; +use bevy::window::PrimaryWindow; pub fn indicators_plugin(app: &mut App) { app.add_systems(PreUpdate, (add_indicators, update_indicators)) @@ -14,27 +14,45 @@ struct PlanetIndicator(String); #[derive(Component)] struct HasIndicator(Entity); -fn add_indicators(planets_wo_indicators: Query<(Entity, &Planet), Without>, player: Query>, asset_server: Res, mut commands: Commands) { - let Ok(me) = player.single() else { return; }; +fn add_indicators( + planets_wo_indicators: Query<(Entity, &Planet), Without>, + player: Query>, + asset_server: Res, + mut commands: Commands, +) { + let Ok(me) = player.single() else { + return; + }; for (planet, planet_data) in &planets_wo_indicators { - let Some(indicator_url) = &planet_data.indicator_sprite else { continue }; + let Some(indicator_url) = &planet_data.indicator_sprite else { + continue; + }; let mut sprite = Sprite::from_image(asset_server.load(indicator_url)); sprite.custom_size = Some(Vec2::new(25.0, 25.0)); - let indicator = commands.spawn(( - ChildOf(me), - PlanetIndicator(planet_data.name.clone()), - sprite, - Transform::from_xyz(0.0, 0.0, 0.0) - )).id(); + let indicator = commands + .spawn(( + ChildOf(me), + PlanetIndicator(planet_data.name.clone()), + sprite, + Transform::from_xyz(0.0, 0.0, 0.0), + )) + .id(); commands.entity(planet).insert(HasIndicator(indicator)); } } -fn update_indicators(changed_planets_w_indicators: Query<(&Planet, &HasIndicator), Changed>, asset_server: Res, mut commands: Commands) { +fn update_indicators( + changed_planets_w_indicators: Query<(&Planet, &HasIndicator), Changed>, + asset_server: Res, + mut commands: Commands, +) { for (planet_data, indicator) in changed_planets_w_indicators.iter() { - let Some(indicator_sprite) = &planet_data.indicator_sprite else { continue; }; + let Some(indicator_sprite) = &planet_data.indicator_sprite else { + continue; + }; let mut sprite = Sprite::from_image(asset_server.load(indicator_sprite)); sprite.custom_size = Some(Vec2::new(50.0, 50.0)); - commands.entity(indicator.0) + commands + .entity(indicator.0) .remove::() .insert(sprite); } @@ -42,12 +60,21 @@ fn update_indicators(changed_planets_w_indicators: Query<(&Planet, &HasIndicator fn update_indicators_position( planets_w_indicator: Query<(&Transform, &HasIndicator), Without>, player: Query<&Transform, (With, Without)>, - mut indicators: Query<(&mut Transform, &mut Sprite), (With, Without, Without, Without)>, + mut indicators: Query< + (&mut Transform, &mut Sprite), + ( + With, + Without, + Without, + Without, + ), + >, window: Query<&Window, With>, camera: Single<&Transform, (With, Without)>, -) -{ - let Ok(player_position) = player.single() else { return; }; +) { + let Ok(player_position) = player.single() else { + return; + }; let Ok(window) = window.single() else { return }; for (planet_position, indicator_id) in &planets_w_indicator { @@ -60,7 +87,9 @@ fn update_indicators_position( offset.x = offset.x.clamp(-half_window_width, half_window_width); offset.y = offset.y.clamp(-half_window_height, half_window_height); - let Ok((mut this_indicator, mut this_sprite)) = indicators.get_mut(indicator_id.0) else { continue; }; + let Ok((mut this_indicator, mut this_sprite)) = indicators.get_mut(indicator_id.0) else { + continue; + }; this_sprite.custom_size = Some(Vec2::splat(sprite_size)); @@ -68,4 +97,4 @@ fn update_indicators_position( this_indicator.translation = inv_rot.mul_vec3(Vec3::new(offset.x, offset.y, 0.0)); this_indicator.rotation = inv_rot; } -} \ No newline at end of file +} diff --git a/crates/unified/src/client/planet/mod.rs b/crates/unified/src/client/planet/mod.rs index d30672ab3a2eeef5d563f998819cbe00b7973b49..a019aa739e80095b6fdeb9d1d59e5ad27e63c88b 100644 --- a/crates/unified/src/client/planet/mod.rs +++ b/crates/unified/src/client/planet/mod.rs @@ -1,2 +1,2 @@ pub mod incoming_planets; -pub mod indicators; \ No newline at end of file +pub mod indicators; diff --git a/crates/unified/src/client/starfield.rs b/crates/unified/src/client/starfield.rs index b4380ae3629fb6e21b68ec2e24f66281f824bc9b..6b7b2df1e6b0b283a0367f9c9a6361bba144250c 100644 --- a/crates/unified/src/client/starfield.rs +++ b/crates/unified/src/client/starfield.rs @@ -168,12 +168,18 @@ pub fn resize_starfield( camera: Single<&Transform, With>, ) { for event in resize_event.read() { - starfield_back.single_mut().unwrap().custom_size = - Some(Vec2::new(event.width, event.height) * camera.scale.z + Vec2::splat(BACK_STARFIELD_SIZE * 2.0)); - starfield_mid.single_mut().unwrap().custom_size = - Some(Vec2::new(event.width, event.height) * camera.scale.z + Vec2::splat(MID_STARFIELD_SIZE * 2.0)); - starfield_front.single_mut().unwrap().custom_size = - Some(Vec2::new(event.width, event.height) * camera.scale.z + Vec2::splat(FRONT_STARFIELD_SIZE * 2.0)); + starfield_back.single_mut().unwrap().custom_size = Some( + Vec2::new(event.width, event.height) * camera.scale.z + + Vec2::splat(BACK_STARFIELD_SIZE * 2.0), + ); + starfield_mid.single_mut().unwrap().custom_size = Some( + Vec2::new(event.width, event.height) * camera.scale.z + + Vec2::splat(MID_STARFIELD_SIZE * 2.0), + ); + starfield_front.single_mut().unwrap().custom_size = Some( + Vec2::new(event.width, event.height) * camera.scale.z + + Vec2::splat(FRONT_STARFIELD_SIZE * 2.0), + ); } } @@ -206,7 +212,16 @@ pub fn update_starfield( ), >, window: Single<&Window>, - camera: Single<&Transform, (With, Without, Without, Without, Without)>, + camera: Single< + &Transform, + ( + With, + Without, + Without, + Without, + Without, + ), + >, player: Query<&Transform, (With, Without)>, ) { let Some(player) = player.iter().next() else { @@ -218,17 +233,35 @@ pub fn update_starfield( //starfield_pos.translation = (player.translation / STARFIELD_SIZE).round() * STARFIELD_SIZE; starfield_back_pos.translation = player.translation + (-player.translation / 3.0) % BACK_STARFIELD_SIZE - + (Vec3::new(window.resolution.width(), -window.resolution.height() + BACK_STARFIELD_SIZE, 0.0)*camera.scale.z/2.0) % BACK_STARFIELD_SIZE + + (Vec3::new( + window.resolution.width(), + -window.resolution.height() + BACK_STARFIELD_SIZE, + 0.0, + ) * camera.scale.z + / 2.0) + % BACK_STARFIELD_SIZE + Vec3::new(0.0, BACK_STARFIELD_SIZE, 0.0) - Vec3::new(0.0, 0.0, 5.0); starfield_mid_pos.translation = player.translation + (-player.translation / 2.5) % MID_STARFIELD_SIZE - + (Vec3::new(window.resolution.width(), -window.resolution.height() + MID_STARFIELD_SIZE, 0.0)*camera.scale.z/2.0) % MID_STARFIELD_SIZE + + (Vec3::new( + window.resolution.width(), + -window.resolution.height() + MID_STARFIELD_SIZE, + 0.0, + ) * camera.scale.z + / 2.0) + % MID_STARFIELD_SIZE + Vec3::new(0.0, MID_STARFIELD_SIZE, 0.0) - Vec3::new(0.0, 0.0, 4.5); starfield_front_pos.translation = player.translation + (-player.translation / 2.0) % FRONT_STARFIELD_SIZE - + (Vec3::new(window.resolution.width(), -window.resolution.height() + FRONT_STARFIELD_SIZE, 0.0)*camera.scale.z/2.0) % FRONT_STARFIELD_SIZE + + (Vec3::new( + window.resolution.width(), + -window.resolution.height() + FRONT_STARFIELD_SIZE, + 0.0, + ) * camera.scale.z + / 2.0) + % FRONT_STARFIELD_SIZE + Vec3::new(0.0, FRONT_STARFIELD_SIZE, 0.0) - Vec3::new(0.0, 0.0, 4.0); } diff --git a/crates/unified/src/client/zoom.rs b/crates/unified/src/client/zoom.rs index 4d39931d4e3943950e86a550dcdb6f25125eade3..b14021f37eb620e6060c8fc3f4449b4dd4a9b4cd 100644 --- a/crates/unified/src/client/zoom.rs +++ b/crates/unified/src/client/zoom.rs @@ -1,6 +1,15 @@ -use bevy::{input::mouse::{MouseScrollUnit, MouseWheel}, prelude::*}; +use bevy::{ + input::mouse::{MouseScrollUnit, MouseWheel}, + prelude::*, +}; -use crate::{client::{starfield::{BACK_STARFIELD_SIZE, FRONT_STARFIELD_SIZE, MID_STARFIELD_SIZE}, Me}, ecs::{MainCamera, StarfieldBack, StarfieldFront, StarfieldMid}}; +use crate::{ + client::{ + Me, + starfield::{BACK_STARFIELD_SIZE, FRONT_STARFIELD_SIZE, MID_STARFIELD_SIZE}, + }, + ecs::{MainCamera, StarfieldBack, StarfieldFront, StarfieldMid}, +}; pub fn zoom_plugin(app: &mut App) { app.add_systems(Update, on_scroll); @@ -33,8 +42,26 @@ fn on_scroll( Without, ), >, - mut camera: Single<&mut Transform, (With, Without, Without, Without, Without)>, - player: Single<&Transform, (With, Without, Without, Without, Without)>, + mut camera: Single< + &mut Transform, + ( + With, + Without, + Without, + Without, + Without, + ), + >, + player: Single< + &Transform, + ( + With, + Without, + Without, + Without, + Without, + ), + >, ) { let (mut starfield_back, mut starfield_back_pos) = starfield_back.into_inner(); let (mut starfield_mid, mut starfield_mid_pos) = starfield_mid.into_inner(); @@ -55,17 +82,26 @@ fn on_scroll( Some(window.size() * camera.scale.z + Vec2::splat(FRONT_STARFIELD_SIZE * 2.0)); starfield_back_pos.translation = player.translation + (-player.translation / 3.0) % BACK_STARFIELD_SIZE - + (Vec3::new(window.resolution.width(), -window.resolution.height(), 0.0)*camera.scale.z/2.0) % BACK_STARFIELD_SIZE + + (Vec3::new(window.resolution.width(), -window.resolution.height(), 0.0) + * camera.scale.z + / 2.0) + % BACK_STARFIELD_SIZE + Vec3::new(0.0, BACK_STARFIELD_SIZE, 0.0) - Vec3::new(0.0, 0.0, 5.0); starfield_mid_pos.translation = player.translation + (-player.translation / 2.5) % MID_STARFIELD_SIZE - + (Vec3::new(window.resolution.width(), -window.resolution.height(), 0.0)*camera.scale.z/2.0) % MID_STARFIELD_SIZE + + (Vec3::new(window.resolution.width(), -window.resolution.height(), 0.0) + * camera.scale.z + / 2.0) + % MID_STARFIELD_SIZE + Vec3::new(0.0, MID_STARFIELD_SIZE, 0.0) - Vec3::new(0.0, 0.0, 4.5); starfield_front_pos.translation = player.translation + (-player.translation / 2.0) % FRONT_STARFIELD_SIZE - + (Vec3::new(window.resolution.width(), -window.resolution.height(), 0.0)*camera.scale.z/2.0) % FRONT_STARFIELD_SIZE + + (Vec3::new(window.resolution.width(), -window.resolution.height(), 0.0) + * camera.scale.z + / 2.0) + % FRONT_STARFIELD_SIZE + Vec3::new(0.0, FRONT_STARFIELD_SIZE, 0.0) - Vec3::new(0.0, 0.0, 4.0); } diff --git a/crates/unified/src/config/mod.rs b/crates/unified/src/config/mod.rs index 7a72fe4956d4cb1056ae35d874bfc1b856602c6c..4702097c3cdff582ce6fd9d5262bade70b74c74a 100644 --- a/crates/unified/src/config/mod.rs +++ b/crates/unified/src/config/mod.rs @@ -1,3 +1,3 @@ +pub mod part; pub mod planet; pub mod world; -pub mod part; diff --git a/crates/unified/src/config/part.rs b/crates/unified/src/config/part.rs index 54d52a0955a6c955066686b6af2f3e56b5fa9160..f47bfc5f31035e917842bec538965d34e20fd986 100644 --- a/crates/unified/src/config/part.rs +++ b/crates/unified/src/config/part.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; pub struct PartConfig { pub part: PartPartConfig, pub physics: PartPhysicsConfig, - pub joints: Vec + pub joints: Vec, } #[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq)] pub struct PartPartConfig { @@ -19,7 +19,7 @@ pub struct PartPartConfig { pub struct PartPhysicsConfig { pub width: f32, pub height: f32, - pub mass: f32 + pub mass: f32, } #[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq)] pub struct JointConfig { @@ -40,4 +40,4 @@ impl From for Transform { ..Default::default() } } - } \ No newline at end of file +} diff --git a/crates/unified/src/config/planet.rs b/crates/unified/src/config/planet.rs index b45ad9bb39580514a08673971993530e4049ad45..8899a53eec59c5edc258f618e50a3243af92fa8d 100644 --- a/crates/unified/src/config/planet.rs +++ b/crates/unified/src/config/planet.rs @@ -18,10 +18,9 @@ pub struct Planet { #[derive(Deserialize, TypePath, Serialize, Clone, Debug)] pub enum SpecialSpriteProperties { - ForceColor(Color) + ForceColor(Color), } - #[derive(Bundle)] pub struct PlanetBundle { pub planet: Planet, diff --git a/crates/unified/src/config/world.rs b/crates/unified/src/config/world.rs index 7e8d7f1fcee13f7790176a8ea94b1db6d5d04501..d503345c743e36729f4931b0d81d03cf5c5b4d8f 100644 --- a/crates/unified/src/config/world.rs +++ b/crates/unified/src/config/world.rs @@ -13,14 +13,14 @@ pub struct GlobalWorldConfig { pub struct WorldConfig { pub gravity: f32, pub spawn_parts_at: String, - pub spawn_parts_interval_secs: f32 + pub spawn_parts_interval_secs: f32, } #[derive(Deserialize, Asset, TypePath, Clone)] pub struct PartConfig { pub default_width: f32, pub default_height: f32, - pub default_mass: f32 + pub default_mass: f32, } #[derive(Deserialize, Asset, TypePath, Clone)] diff --git a/crates/unified/src/ecs.rs b/crates/unified/src/ecs.rs index 7c20e8975cc3bc2415240979da962c900062174e..09aa73693601bc62d5e3fca927125570985aee8d 100644 --- a/crates/unified/src/ecs.rs +++ b/crates/unified/src/ecs.rs @@ -21,7 +21,6 @@ pub struct StarfieldBack; #[derive(Resource, Default)] pub struct CursorWorldCoordinates(pub Option); - #[derive(Debug, Deserialize, Event, Serialize)] pub enum ThrustEvent { Up(bool), @@ -31,7 +30,13 @@ pub enum ThrustEvent { } #[derive(Component, Serialize, Deserialize, Debug)] -#[require(ReadMassProperties, RigidBody::Dynamic, ExternalForce, ExternalImpulse, Replicated)] +#[require( + ReadMassProperties, + RigidBody::Dynamic, + ExternalForce, + ExternalImpulse, + Replicated +)] pub struct Part { pub sprite: String, pub width: f32, @@ -68,4 +73,4 @@ pub struct Particles { } #[derive(Serialize, Deserialize, Event, Debug, MapEntities, Clone)] -pub struct DragRequestEvent(#[entities] pub Entity, pub Vec2); \ No newline at end of file +pub struct DragRequestEvent(#[entities] pub Entity, pub Vec2); diff --git a/crates/unified/src/lib.rs b/crates/unified/src/lib.rs index fbeac3d22229ab74210dd2693106cb5ae51a4cd8..85be0a9cf2503c1b065bda43c1979f118f2e6b3d 100644 --- a/crates/unified/src/lib.rs +++ b/crates/unified/src/lib.rs @@ -15,16 +15,16 @@ pub mod wasm_entrypoint; #[cfg(target_arch = "wasm32")] pub use wasm_entrypoint::*; +pub mod attachment; pub mod client; pub mod client_plugins; pub mod config; -pub mod particles; pub mod ecs; +#[cfg(all(not(target_arch = "wasm32"), feature = "particle_editor"))] +pub mod particle_editor; +pub mod particles; #[cfg(all(not(target_arch = "wasm32"), feature = "native"))] pub mod server; #[cfg(all(not(target_arch = "wasm32"), feature = "native"))] pub mod server_plugins; pub mod shared_plugins; -#[cfg(all(not(target_arch = "wasm32"), feature = "particle_editor"))] -pub mod particle_editor; -pub mod attachment; \ No newline at end of file diff --git a/crates/unified/src/main.rs b/crates/unified/src/main.rs index 13bcd098ceda70c2ba41be21a947239d6fd11783..b2c74e10dd1941155c70fe1065a7c2a023339be1 100644 --- a/crates/unified/src/main.rs +++ b/crates/unified/src/main.rs @@ -29,7 +29,7 @@ enum Cli { max_clients: usize, }, #[cfg(all(not(target_arch = "wasm32"), feature = "particle_editor"))] - ParticleEditor {} + ParticleEditor {}, } fn main() -> AppExit { @@ -38,8 +38,7 @@ fn main() -> AppExit { tracing_subscriber::fmt() .with_env_filter( - EnvFilter::from_default_env() - .add_directive(Directive::from_str("naga=error").unwrap()) + EnvFilter::from_default_env().add_directive(Directive::from_str("naga=error").unwrap()), ) .finish() .init(); @@ -66,7 +65,7 @@ fn main() -> AppExit { max_clients, }); app.add_plugins(SharedPluginGroup); - }, + } #[cfg(all(not(target_arch = "wasm32"), feature = "particle_editor"))] Cli::ParticleEditor {} => { app.add_plugins(starkingdoms::particle_editor::particle_editor_plugin); diff --git a/crates/unified/src/particle_editor/ecs.rs b/crates/unified/src/particle_editor/ecs.rs index 7a785e5ea62ee588ace6995ce2ef2b6af3484076..dab9f99dd2cd4236a0bff3dc6f88b361662277ce 100644 --- a/crates/unified/src/particle_editor/ecs.rs +++ b/crates/unified/src/particle_editor/ecs.rs @@ -1,6 +1,12 @@ use std::time::Duration; -use bevy::{asset::Handle, ecs::component::Component, render::mesh::Mesh, sprite::ColorMaterial, time::{Timer, TimerMode}}; +use bevy::{ + asset::Handle, + ecs::component::Component, + render::mesh::Mesh, + sprite::ColorMaterial, + time::{Timer, TimerMode}, +}; use crate::particles::ParticleEffect; @@ -11,7 +17,10 @@ pub struct Particle; pub struct LifetimeTimer(pub Timer); impl LifetimeTimer { pub fn new(lifetime: f32) -> LifetimeTimer { - LifetimeTimer(Timer::new(Duration::from_secs_f32(lifetime), TimerMode::Once)) + LifetimeTimer(Timer::new( + Duration::from_secs_f32(lifetime), + TimerMode::Once, + )) } } diff --git a/crates/unified/src/particle_editor/hooks.rs b/crates/unified/src/particle_editor/hooks.rs index 28fb9cc5e9d404f6de2f36b3f069e8d2dcd7e086..f2c7643df5b35ebc38a183225708e2d0463f70b9 100644 --- a/crates/unified/src/particle_editor/hooks.rs +++ b/crates/unified/src/particle_editor/hooks.rs @@ -11,8 +11,11 @@ fn init_particle_effect( particle_effect: Query<(Entity, &ParticleEffect), Added>, ) { for (entity, effect) in particle_effect { - commands.get_entity(entity).unwrap().insert( - SpawnDelayTimer::new(effect.batch_spawn_delay_seconds.sample(&mut rand::rng())) - ); + commands + .get_entity(entity) + .unwrap() + .insert(SpawnDelayTimer::new( + effect.batch_spawn_delay_seconds.sample(&mut rand::rng()), + )); } } diff --git a/crates/unified/src/particle_editor/mod.rs b/crates/unified/src/particle_editor/mod.rs index f1b75f75224725144316910d9b01584cdfa49dc4..48cd00af26aba1f89ffd61aec77b619663c8bf46 100644 --- a/crates/unified/src/particle_editor/mod.rs +++ b/crates/unified/src/particle_editor/mod.rs @@ -1,14 +1,17 @@ -use std::collections::BTreeMap; +use crate::{ + particle_editor::{hooks::hooks_plugin, spawn::spawn_plugin}, + particles::{LifetimeCurve, ParticleEffect, RandF32, RandUsize, RandVec2}, +}; use bevy::prelude::*; -use bevy_egui::{egui, EguiContexts, EguiPlugin, EguiPrimaryContextPass}; +use bevy_egui::{EguiContexts, EguiPlugin, EguiPrimaryContextPass, egui}; use bevy_rapier2d::plugin::{NoUserData, RapierPhysicsPlugin}; use ordered_float::OrderedFloat; use ron::ser::PrettyConfig; -use crate::{particle_editor::{hooks::hooks_plugin, spawn::spawn_plugin}, particles::{LifetimeCurve, ParticleEffect, RandF32, RandUsize, RandVec2}}; +use std::collections::BTreeMap; -mod spawn; -mod hooks; mod ecs; +mod hooks; +mod spawn; pub fn particle_editor_plugin(app: &mut App) { app.add_plugins(DefaultPlugins); @@ -26,40 +29,46 @@ pub fn particle_editor_plugin(app: &mut App) { add_scale_v: 0.0, add_color_t: 0.0, add_color_v: [0u8; 4], - scale_curve: LifetimeCurve::new(&[ - (0.0f32, 5.0), - (2.0, 0.0) - ]).0.iter().map(|u| (u.0.clone(), u.1.clone())).collect::>(), - color_curve: vec![(OrderedFloat(0.0f32), [255, 0, 0, 255])] + scale_curve: LifetimeCurve::new(&[(0.0f32, 5.0), (2.0, 0.0)]) + .0 + .iter() + .map(|u| (u.0.clone(), u.1.clone())) + .collect::>(), + color_curve: vec![(OrderedFloat(0.0f32), [255, 0, 0, 255])], }); } -fn setup_editor_effect( - mut commands: Commands, -) { +fn setup_editor_effect(mut commands: Commands) { commands.spawn(( ParticleEffect { lifetime_seconds: RandF32 { value: 2.0, randomness: 0.1, }, - batch_spawn_delay_seconds: RandF32 { value: 0.1, randomness: 0.05 }, + batch_spawn_delay_seconds: RandF32 { + value: 0.1, + randomness: 0.05, + }, particles_in_batch: RandUsize { value: 1, - randomness: 1 + randomness: 1, }, initial_linear_velocity: RandVec2 { - x: RandF32 { value: 0.0, randomness: 0.5 }, - y: RandF32 { value: 10.0, randomness: 1.0 } + x: RandF32 { + value: 0.0, + randomness: 0.5, + }, + y: RandF32 { + value: 10.0, + randomness: 1.0, + }, }, - initial_angular_velocity: RandF32 { value: 1.0, randomness: 0.5 }, - scale: LifetimeCurve::new(&[ - (0.0f32, 5.0), - (2.0, 0.0) - ]), - color: LifetimeCurve::new(&[ - (0.0f32, Srgba::new(1.0, 0.0, 0.0, 1.0).into()), - ]), + initial_angular_velocity: RandF32 { + value: 1.0, + randomness: 0.5, + }, + scale: LifetimeCurve::new(&[(0.0f32, 5.0), (2.0, 0.0)]), + color: LifetimeCurve::new(&[(0.0f32, Srgba::new(1.0, 0.0, 0.0, 1.0).into())]), }, Transform::from_xyz(0.0, 0.0, 0.0), )); @@ -81,149 +90,213 @@ struct EditorResource { add_color_v: [u8; 4], scale_curve: Vec<(OrderedFloat, f32)>, - color_curve: Vec<(OrderedFloat, [u8; 4])> + color_curve: Vec<(OrderedFloat, [u8; 4])>, } - -fn editor_ui(mut contexts: EguiContexts, effect: Single<&mut ParticleEffect>, mut editor_resource: ResMut) -> Result { +fn editor_ui( + mut contexts: EguiContexts, + effect: Single<&mut ParticleEffect>, + mut editor_resource: ResMut, +) -> Result { let mut effect = effect.into_inner(); - egui::Window::new("Particle Effect").resizable(false).show(contexts.ctx_mut()?, |ui| { - egui::Grid::new("effect").striped(true).show(ui, |ui| { - draw_rand_f32(&mut effect.lifetime_seconds, "Lifetime (seconds): ", ui); - draw_rand_f32(&mut effect.batch_spawn_delay_seconds, "Delay in between batches (seconds): ", ui); - draw_rand_usize(&mut effect.particles_in_batch, "Number of particles in batch: ", ui); - - draw_rand_f32(&mut effect.initial_linear_velocity.x, "Linear velocity (x-axis, m/s): ", ui); - draw_rand_f32(&mut effect.initial_linear_velocity.y, "Linear velocity (y-axis, m/s): ", ui); - draw_rand_f32(&mut effect.initial_angular_velocity, "Angular velocity (radians/second): ", ui); - - ui.separator(); - ui.label("Scale curve"); - if ui.button("sort").clicked() { - editor_resource.scale_curve.sort_by_key(|u|u.0); - } - ui.end_row(); - - editor_resource.scale_curve.retain_mut(|(k, v)| { - ui.label("scale t="); - ui.add(egui::DragValue::new(k.as_mut()).speed(0.01).range(0.0f32..=effect.lifetime_seconds.value)); + egui::Window::new("Particle Effect") + .resizable(false) + .show(contexts.ctx_mut()?, |ui| { + egui::Grid::new("effect").striped(true).show(ui, |ui| { + draw_rand_f32(&mut effect.lifetime_seconds, "Lifetime (seconds): ", ui); + draw_rand_f32( + &mut effect.batch_spawn_delay_seconds, + "Delay in between batches (seconds): ", + ui, + ); + draw_rand_usize( + &mut effect.particles_in_batch, + "Number of particles in batch: ", + ui, + ); + + draw_rand_f32( + &mut effect.initial_linear_velocity.x, + "Linear velocity (x-axis, m/s): ", + ui, + ); + draw_rand_f32( + &mut effect.initial_linear_velocity.y, + "Linear velocity (y-axis, m/s): ", + ui, + ); + draw_rand_f32( + &mut effect.initial_angular_velocity, + "Angular velocity (radians/second): ", + ui, + ); + + ui.separator(); + ui.label("Scale curve"); + if ui.button("sort").clicked() { + editor_resource.scale_curve.sort_by_key(|u| u.0); + } + ui.end_row(); + + editor_resource.scale_curve.retain_mut(|(k, v)| { + ui.label("scale t="); + ui.add( + egui::DragValue::new(k.as_mut()) + .speed(0.01) + .range(0.0f32..=effect.lifetime_seconds.value), + ); + ui.label("v="); + ui.add(egui::DragValue::new(v).speed(0.01)); + let r = ui.button("-"); + ui.end_row(); + !r.clicked() + }); + + ui.separator(); + ui.end_row(); + + ui.label("new scale: t="); + ui.add( + egui::DragValue::new(&mut editor_resource.add_scale_t) + .speed(0.01) + .range(0.0f32..=effect.lifetime_seconds.value), + ); ui.label("v="); - ui.add(egui::DragValue::new(v).speed(0.01)); - let r = ui.button("-"); + ui.add(egui::DragValue::new(&mut editor_resource.add_scale_v).speed(0.01)); + if ui.button("+").clicked() { + let new_v = ( + OrderedFloat(editor_resource.add_scale_t), + editor_resource.add_scale_v, + ) + .clone(); + editor_resource.scale_curve.push(new_v); + } ui.end_row(); - !r.clicked() - }); - ui.separator(); - ui.end_row(); - - ui.label("new scale: t="); - ui.add(egui::DragValue::new(&mut editor_resource.add_scale_t).speed(0.01).range(0.0f32..=effect.lifetime_seconds.value)); - ui.label("v="); - ui.add(egui::DragValue::new(&mut editor_resource.add_scale_v).speed(0.01)); - if ui.button("+").clicked() { - let new_v = (OrderedFloat(editor_resource.add_scale_t), editor_resource.add_scale_v).clone(); - editor_resource.scale_curve.push(new_v); - } - ui.end_row(); - - effect.scale = LifetimeCurve(BTreeMap::from_iter(editor_resource.scale_curve.iter().copied())); - - ui.separator(); - ui.end_row(); - - ui.separator(); - ui.label("Color curve"); - if ui.button("sort").clicked() { - editor_resource.color_curve.sort_by_key(|u|u.0); - } - ui.end_row(); - - editor_resource.color_curve.retain_mut(|(k, v)| { - ui.label("color t="); - ui.add(egui::DragValue::new(k.as_mut()).speed(0.01).range(0.0f32..=effect.lifetime_seconds.value)); + effect.scale = LifetimeCurve(BTreeMap::from_iter( + editor_resource.scale_curve.iter().copied(), + )); + + ui.separator(); + ui.end_row(); + + ui.separator(); + ui.label("Color curve"); + if ui.button("sort").clicked() { + editor_resource.color_curve.sort_by_key(|u| u.0); + } + ui.end_row(); + + editor_resource.color_curve.retain_mut(|(k, v)| { + ui.label("color t="); + ui.add( + egui::DragValue::new(k.as_mut()) + .speed(0.01) + .range(0.0f32..=effect.lifetime_seconds.value), + ); + ui.label("v="); + ui.color_edit_button_srgba_unmultiplied(v); + let r = ui.button("-"); + ui.end_row(); + !r.clicked() + }); + + ui.separator(); + ui.end_row(); + + ui.label("new color: t="); + ui.add( + egui::DragValue::new(&mut editor_resource.add_color_t) + .speed(0.01) + .range(0.0f32..=effect.lifetime_seconds.value), + ); ui.label("v="); - ui.color_edit_button_srgba_unmultiplied(v); - let r = ui.button("-"); + ui.color_edit_button_srgba_unmultiplied(&mut editor_resource.add_color_v); + if ui.button("+").clicked() { + let new_v = ( + OrderedFloat(editor_resource.add_color_t), + editor_resource.add_color_v, + ) + .clone(); + editor_resource.color_curve.push(new_v); + } ui.end_row(); - !r.clicked() - }); - ui.separator(); - ui.end_row(); - - ui.label("new color: t="); - ui.add(egui::DragValue::new(&mut editor_resource.add_color_t).speed(0.01).range(0.0f32..=effect.lifetime_seconds.value)); - ui.label("v="); - ui.color_edit_button_srgba_unmultiplied(&mut editor_resource.add_color_v); - if ui.button("+").clicked() { - let new_v = (OrderedFloat(editor_resource.add_color_t), editor_resource.add_color_v).clone(); - editor_resource.color_curve.push(new_v); - } - ui.end_row(); - - let curve_copied = editor_resource.color_curve.clone(); - effect.color = LifetimeCurve(BTreeMap::from_iter(curve_copied.iter().map( - |(u, v)| ( - *u, - Color::Srgba(Srgba::new( - v[0] as f32 / 256.0, - v[1] as f32 / 256.0, - v[2] as f32 / 256.0, - v[3] as f32 / 256.0 - )) - ) - ))); - - ui.separator(); - ui.end_row(); - }); - ui.horizontal(|ui| { - if ui.button("Generate").clicked() { - effect.scale = LifetimeCurve(BTreeMap::from_iter(editor_resource.scale_curve.iter().copied())); let curve_copied = editor_resource.color_curve.clone(); - effect.color = LifetimeCurve(BTreeMap::from_iter(curve_copied.iter().map( - |(u, v)| ( - *u, - Color::Srgba(Srgba::new( - v[0] as f32 / 256.0, - v[1] as f32 / 256.0, - v[2] as f32 / 256.0, - v[3] as f32 / 256.0 - )) - ) - ))); - - editor_resource.ser_field = ron::ser::to_string(effect.as_ref()).unwrap(); - editor_resource.status = "Ready; Generated OK".to_string(); - } - if ui.button("Load").clicked() { - match ron::from_str(&editor_resource.ser_field) { - Ok(e) => { - *effect = e; - editor_resource.scale_curve = effect.scale.0.iter().map(|u| (u.0.clone(), u.1.clone())).collect::>(); - editor_resource.color_curve = effect.color.0.iter().map(|u| ( - u.0.clone(), - { - let mut r = [0u8; 4]; - let srgba: Srgba = (*u.1).into(); - r[0] = (srgba.red * 256.0).floor() as u8; - r[1] = (srgba.green * 256.0).floor() as u8; - r[2] = (srgba.blue * 256.0).floor() as u8; - r[3] = (srgba.alpha * 256.0).floor() as u8; - r - } - )).collect::>(); - }, - Err(e) => { - editor_resource.status = e.to_string(); - } - }; - } + effect.color = + LifetimeCurve(BTreeMap::from_iter(curve_copied.iter().map(|(u, v)| { + ( + *u, + Color::Srgba(Srgba::new( + v[0] as f32 / 256.0, + v[1] as f32 / 256.0, + v[2] as f32 / 256.0, + v[3] as f32 / 256.0, + )), + ) + }))); + + ui.separator(); + ui.end_row(); + }); + ui.horizontal(|ui| { + if ui.button("Generate").clicked() { + effect.scale = LifetimeCurve(BTreeMap::from_iter( + editor_resource.scale_curve.iter().copied(), + )); + let curve_copied = editor_resource.color_curve.clone(); + effect.color = + LifetimeCurve(BTreeMap::from_iter(curve_copied.iter().map(|(u, v)| { + ( + *u, + Color::Srgba(Srgba::new( + v[0] as f32 / 256.0, + v[1] as f32 / 256.0, + v[2] as f32 / 256.0, + v[3] as f32 / 256.0, + )), + ) + }))); + + editor_resource.ser_field = ron::ser::to_string(effect.as_ref()).unwrap(); + editor_resource.status = "Ready; Generated OK".to_string(); + } + if ui.button("Load").clicked() { + match ron::from_str(&editor_resource.ser_field) { + Ok(e) => { + *effect = e; + editor_resource.scale_curve = effect + .scale + .0 + .iter() + .map(|u| (u.0.clone(), u.1.clone())) + .collect::>(); + editor_resource.color_curve = effect + .color + .0 + .iter() + .map(|u| { + (u.0.clone(), { + let mut r = [0u8; 4]; + let srgba: Srgba = (*u.1).into(); + r[0] = (srgba.red * 256.0).floor() as u8; + r[1] = (srgba.green * 256.0).floor() as u8; + r[2] = (srgba.blue * 256.0).floor() as u8; + r[3] = (srgba.alpha * 256.0).floor() as u8; + r + }) + }) + .collect::>(); + } + Err(e) => { + editor_resource.status = e.to_string(); + } + }; + } + }); + ui.text_edit_multiline(&mut editor_resource.ser_field); + ui.text_edit_multiline(&mut editor_resource.status.as_str()); }); - ui.text_edit_multiline(&mut editor_resource.ser_field); - ui.text_edit_multiline(&mut editor_resource.status.as_str()); - }); Ok(()) } diff --git a/crates/unified/src/particle_editor/spawn.rs b/crates/unified/src/particle_editor/spawn.rs index 3462c0c4d73c8be4a933be1ccaefe4f9bde4fea3..ed00eec7ee319134dd3127401560d6f8897367cd 100644 --- a/crates/unified/src/particle_editor/spawn.rs +++ b/crates/unified/src/particle_editor/spawn.rs @@ -3,7 +3,10 @@ use std::time::Duration; use bevy::prelude::*; use bevy_rapier2d::prelude::{RigidBody, Velocity}; -use crate::{particle_editor::ecs::{CircleMesh, LifetimeTimer, ParentEffect, Particle, SpawnDelayTimer}, particles::ParticleEffect}; +use crate::{ + particle_editor::ecs::{CircleMesh, LifetimeTimer, ParentEffect, Particle, SpawnDelayTimer}, + particles::ParticleEffect, +}; pub fn spawn_plugin(app: &mut App) { app.add_systems(Update, spawn_particles); @@ -21,24 +24,41 @@ fn spawn_particles( delay_timer.0.tick(time.delta()); if delay_timer.0.just_finished() { for _ in 0..effect.particles_in_batch.sample(&mut rand::rng()) { - let circle = CircleMesh(meshes.add(Circle::new(1.0)), - materials.add(effect.color.sample(effect.color.clamp_time(0.0).unwrap()).unwrap())); + let circle = CircleMesh( + meshes.add(Circle::new(1.0)), + materials.add( + effect + .color + .sample(effect.color.clamp_time(0.0).unwrap()) + .unwrap(), + ), + ); commands.spawn(( RigidBody::Dynamic, Particle, - transform.with_scale(Vec3::splat(effect.scale.sample(effect.scale.clamp_time(0.0).unwrap()).unwrap())), + transform.with_scale(Vec3::splat( + effect + .scale + .sample(effect.scale.clamp_time(0.0).unwrap()) + .unwrap(), + )), Mesh2d(circle.0.clone()), MeshMaterial2d(circle.1.clone()), Velocity { linvel: effect.initial_linear_velocity.sample(&mut rand::rng()), angvel: effect.initial_angular_velocity.sample(&mut rand::rng()), }, - LifetimeTimer(Timer::from_seconds(effect.lifetime_seconds.sample(&mut rand::rng()), TimerMode::Once)), + LifetimeTimer(Timer::from_seconds( + effect.lifetime_seconds.sample(&mut rand::rng()), + TimerMode::Once, + )), circle, ParentEffect(effect.clone()), )); } - delay_timer.0.set_duration(Duration::from_secs_f32(effect.batch_spawn_delay_seconds.sample(&mut rand::rng()))); + delay_timer.0.set_duration(Duration::from_secs_f32( + effect.batch_spawn_delay_seconds.sample(&mut rand::rng()), + )); delay_timer.0.reset(); } } @@ -46,15 +66,34 @@ fn spawn_particles( fn lifetime_particles( mut commands: Commands, - mut particles: Query<(Entity, &mut LifetimeTimer, &mut Transform, &CircleMesh, &ParentEffect), With>, + mut particles: Query< + ( + Entity, + &mut LifetimeTimer, + &mut Transform, + &CircleMesh, + &ParentEffect, + ), + With, + >, time: ResMut