From 5cc97da98b6c5d56c5222ffb8f17d984f5b4585d Mon Sep 17 00:00:00 2001 From: extrawurst Date: Tue, 29 Apr 2025 19:55:40 +0200 Subject: [PATCH] use new spawn api --- src/abilities/gun.rs | 37 ++++++----- src/abilities/missile.rs | 61 +++++++++--------- src/aim/target_ui.rs | 102 ++++++++++++++---------------- src/backpack/backpack_ui.rs | 123 ++++++++++++++++++------------------ src/camera.rs | 25 ++++---- src/heads/heads_ui.rs | 114 ++++++++++++++++----------------- src/keys.rs | 29 ++++----- src/player.rs | 56 ++++++++-------- 8 files changed, 265 insertions(+), 282 deletions(-) diff --git a/src/abilities/gun.rs b/src/abilities/gun.rs index 814e531..696ae15 100644 --- a/src/abilities/gun.rs +++ b/src/abilities/gun.rs @@ -100,24 +100,22 @@ fn on_trigger_gun( let mut t = Transform::from_translation(state.pos).with_rotation(rotation); t.translation += t.forward().as_vec3() * 2.0; - commands - .spawn(( - Name::new("projectile-gun"), - GunProjectile { - time: time.elapsed_secs(), - owner_head: state.head, - }, - Collider::capsule_endpoints(0.5, Vec3::new(0., 0., 0.), Vec3::new(0., 0., -3.)), - CollisionLayers::new( - LayerMask(GameLayer::Projectile.to_bits()), - LayerMask(state.target_layer.to_bits() | GameLayer::Level.to_bits()), - ), - Sensor, - CollisionEventsEnabled, - Visibility::default(), - t, - )) - .with_child(Gizmo { + commands.spawn(( + Name::new("projectile-gun"), + GunProjectile { + time: time.elapsed_secs(), + owner_head: state.head, + }, + Collider::capsule_endpoints(0.5, Vec3::new(0., 0., 0.), Vec3::new(0., 0., -3.)), + CollisionLayers::new( + LayerMask(GameLayer::Projectile.to_bits()), + LayerMask(state.target_layer.to_bits() | GameLayer::Level.to_bits()), + ), + Sensor, + CollisionEventsEnabled, + Visibility::default(), + t, + Children::spawn(Spawn(Gizmo { handle: gizmo_assets.add({ let mut g = GizmoAsset::default(); g.line(Vec3::Z * -2., Vec3::Z * 2., LinearRgba::rgb(0.9, 0.9, 0.)); @@ -128,7 +126,8 @@ fn on_trigger_gun( ..default() }, ..default() - }); + })), + )); } fn update(mut query: Query<&mut Transform, With>) { diff --git a/src/abilities/missile.rs b/src/abilities/missile.rs index 90e37ee..e0e905e 100644 --- a/src/abilities/missile.rs +++ b/src/abilities/missile.rs @@ -114,39 +114,40 @@ fn on_trigger_missile( let mesh = assets.projectiles["missile.glb"].clone(); let asset = gltf_assets.get(&mesh).unwrap(); - commands - .spawn(( - Name::new("projectile-missle"), - MissileProjectile { - time: time.elapsed_secs(), - damage: head.damage, - }, - Collider::capsule_endpoints(0.4, Vec3::new(0., 0., 2.), Vec3::new(0., 0., -2.)), - CollisionLayers::new( - LayerMask(GameLayer::Projectile.to_bits()), - LayerMask(state.target_layer.to_bits() | GameLayer::Level.to_bits()), + commands.spawn(( + Name::new("projectile-missle"), + MissileProjectile { + time: time.elapsed_secs(), + damage: head.damage, + }, + Collider::capsule_endpoints(0.4, Vec3::new(0., 0., 2.), Vec3::new(0., 0., -2.)), + CollisionLayers::new( + LayerMask(GameLayer::Projectile.to_bits()), + LayerMask(state.target_layer.to_bits() | GameLayer::Level.to_bits()), + ), + Sensor, + CollisionEventsEnabled, + Visibility::default(), + t, + children![ + ( + Transform::from_rotation(Quat::from_rotation_x(PI / 2.).inverse()) + .with_scale(Vec3::splat(0.04)), + SceneRoot(asset.scenes[0].clone()), ), - Sensor, - CollisionEventsEnabled, - Visibility::default(), - t, - )) - .with_child(( - Transform::from_rotation(Quat::from_rotation_x(PI / 2.).inverse()) - .with_scale(Vec3::splat(0.04)), - SceneRoot(asset.scenes[0].clone()), - )) - .with_child(( - Trail::new(t.translation, LinearRgba::rgb(0.9, 0.9, 0.)), - Gizmo { - handle: gizmo_assets.add(GizmoAsset::default()), - line_config: GizmoLineConfig { - width: 10., + ( + Trail::new(t.translation, LinearRgba::rgb(0.9, 0.9, 0.)), + Gizmo { + handle: gizmo_assets.add(GizmoAsset::default()), + line_config: GizmoLineConfig { + width: 10., + ..default() + }, ..default() }, - ..default() - }, - )); + ) + ], + )); } fn update(mut query: Query<&mut Transform, With>) { diff --git a/src/aim/target_ui.rs b/src/aim/target_ui.rs index 0d5b364..fcd66dc 100644 --- a/src/aim/target_ui.rs +++ b/src/aim/target_ui.rs @@ -29,55 +29,46 @@ pub fn plugin(app: &mut App) { } fn setup(mut commands: Commands, assets: Res) { - commands - .spawn(( - Name::new("target-ui"), - Node { - position_type: PositionType::Absolute, - top: Val::Px(150.0), - left: Val::Px(20.0), - height: Val::Px(74.0), - ..default() - }, - )) - .with_children(|parent| { - spawn_head_ui( - parent, - assets.head_bg.clone(), - assets.head_regular.clone(), - assets.head_damage.clone(), - ); - }); + commands.spawn(( + Name::new("target-ui"), + Node { + position_type: PositionType::Absolute, + top: Val::Px(150.0), + left: Val::Px(20.0), + height: Val::Px(74.0), + ..default() + }, + children![spawn_head_ui( + assets.head_bg.clone(), + assets.head_regular.clone(), + assets.head_damage.clone(), + )], + )); commands.insert_resource(TargetUi::default()); } -fn spawn_head_ui( - parent: &mut ChildSpawnerCommands, - bg: Handle, - regular: Handle, - damage: Handle, -) { +fn spawn_head_ui(bg: Handle, regular: Handle, damage: Handle) -> impl Bundle { const SIZE: f32 = 90.0; const DAMAGE_SIZE: f32 = 74.0; - parent - .spawn((Node { + ( + Node { position_type: PositionType::Relative, justify_content: JustifyContent::Center, align_items: AlignItems::Center, width: Val::Px(SIZE), ..default() - },)) - .with_children(|parent| { - parent.spawn(( + }, + children![ + ( Node { position_type: PositionType::Absolute, ..default() }, ImageNode::new(bg), - )); - parent.spawn(( + ), + ( Node { position_type: PositionType::Absolute, ..default() @@ -85,38 +76,37 @@ fn spawn_head_ui( ImageNode::default(), Visibility::Hidden, HeadImage, - )); - parent.spawn(( + ), + ( Node { position_type: PositionType::Absolute, ..default() }, ImageNode::new(regular), - )); - parent - .spawn((Node { + ), + ( + Node { height: Val::Px(DAMAGE_SIZE), width: Val::Px(DAMAGE_SIZE), ..default() - },)) - .with_children(|parent| { - parent - .spawn(( - HeadDamage, - Node { - position_type: PositionType::Absolute, - display: Display::Block, - overflow: Overflow::clip(), - top: Val::Px(0.), - left: Val::Px(0.), - right: Val::Px(0.), - height: Val::Percent(25.), - ..default() - }, - )) - .with_child(ImageNode::new(damage)); - }); - }); + }, + children![( + HeadDamage, + Node { + position_type: PositionType::Absolute, + display: Display::Block, + overflow: Overflow::clip(), + top: Val::Px(0.), + left: Val::Px(0.), + right: Val::Px(0.), + height: Val::Percent(25.), + ..default() + }, + children![ImageNode::new(damage)] + )] + ) + ], + ) } fn update( diff --git a/src/backpack/backpack_ui.rs b/src/backpack/backpack_ui.rs index 6252585..6be0f9d 100644 --- a/src/backpack/backpack_ui.rs +++ b/src/backpack/backpack_ui.rs @@ -2,7 +2,7 @@ use super::{BackbackSwapEvent, Backpack, UiHeadState}; use crate::{ GameState, global_observer, heads::HeadsImages, loading_assets::UIAssets, sounds::PlaySound, }; -use bevy::prelude::*; +use bevy::{ecs::spawn::SpawnIter, prelude::*}; static HEAD_SLOTS: usize = 5; @@ -57,31 +57,34 @@ pub fn plugin(app: &mut App) { } fn setup(mut commands: Commands, assets: Res) { - commands - .spawn(( - Name::new("backpack-ui"), - BackpackMarker, - Visibility::Hidden, - Node { - position_type: PositionType::Absolute, - top: Val::Px(20.0), - right: Val::Px(20.0), - height: Val::Px(74.0), - ..default() - }, - )) - .with_children(|parent| { - for i in 0..HEAD_SLOTS { + commands.spawn(( + Name::new("backpack-ui"), + BackpackMarker, + Visibility::Hidden, + Node { + position_type: PositionType::Absolute, + top: Val::Px(20.0), + right: Val::Px(20.0), + height: Val::Px(74.0), + ..default() + }, + Children::spawn(SpawnIter((0..HEAD_SLOTS).map({ + let bg = assets.head_bg.clone(); + let regular = assets.head_regular.clone(); + let selector = assets.head_selector.clone(); + let damage = assets.head_damage.clone(); + + move |i| { spawn_head_ui( - parent, - assets.head_bg.clone(), - assets.head_regular.clone(), - assets.head_selector.clone(), - assets.head_damage.clone(), + bg.clone(), + regular.clone(), + selector.clone(), + damage.clone(), i, - ); + ) } - }); + }))), + )); commands.spawn(( Name::new("backpack-head-count-ui"), @@ -105,26 +108,25 @@ fn setup(mut commands: Commands, assets: Res) { } fn spawn_head_ui( - parent: &mut ChildSpawnerCommands, bg: Handle, regular: Handle, selector: Handle, damage: Handle, head_slot: usize, -) { +) -> impl Bundle { const SIZE: f32 = 90.0; const DAMAGE_SIZE: f32 = 74.0; - parent - .spawn((Node { + ( + Node { position_type: PositionType::Relative, justify_content: JustifyContent::Center, align_items: AlignItems::Center, width: Val::Px(SIZE), ..default() - },)) - .with_children(|parent| { - parent.spawn(( + }, + children![ + ( Name::new("selector"), Node { position_type: PositionType::Absolute, @@ -134,16 +136,16 @@ fn spawn_head_ui( Visibility::Hidden, ImageNode::new(selector).with_flip_y(), HeadSelector(head_slot), - )); - parent.spawn(( + ), + ( Name::new("bg"), Node { position_type: PositionType::Absolute, ..default() }, ImageNode::new(bg), - )); - parent.spawn(( + ), + ( Name::new("head"), Node { position_type: PositionType::Absolute, @@ -152,43 +154,40 @@ fn spawn_head_ui( ImageNode::default(), Visibility::Hidden, HeadImage(head_slot), - )); - parent.spawn(( + ), + ( Name::new("rings"), Node { position_type: PositionType::Absolute, ..default() }, ImageNode::new(regular), - )); - parent - .spawn(( - Name::new("health"), + ), + ( + Name::new("health"), + Node { + height: Val::Px(DAMAGE_SIZE), + width: Val::Px(DAMAGE_SIZE), + ..default() + }, + children![( + Name::new("damage_ring"), + HeadDamage(head_slot), Node { - height: Val::Px(DAMAGE_SIZE), - width: Val::Px(DAMAGE_SIZE), + position_type: PositionType::Absolute, + display: Display::Block, + overflow: Overflow::clip(), + top: Val::Px(0.), + left: Val::Px(0.), + right: Val::Px(0.), + height: Val::Percent(0.), ..default() }, - )) - .with_children(|parent| { - parent - .spawn(( - Name::new("damage_ring"), - HeadDamage(head_slot), - Node { - position_type: PositionType::Absolute, - display: Display::Block, - overflow: Overflow::clip(), - top: Val::Px(0.), - left: Val::Px(0.), - right: Val::Px(0.), - height: Val::Percent(0.), - ..default() - }, - )) - .with_child(ImageNode::new(damage)); - }); - }); + children![ImageNode::new(damage)] + )] + ) + ], + ) } fn update_visibility( diff --git a/src/camera.rs b/src/camera.rs index 88b9d8e..39f3cd9 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -82,25 +82,24 @@ fn update_ui( let show_ui = cam_state.look_around || cam_state.cutscene; if show_ui { - commands - .spawn(( - CameraUi, - Node { - margin: UiRect::top(Val::Px(20.)) - .with_left(Val::Auto) - .with_right(Val::Auto), - justify_content: JustifyContent::Center, - ..default() - }, - )) - .with_child(( + commands.spawn(( + CameraUi, + Node { + margin: UiRect::top(Val::Px(20.)) + .with_left(Val::Auto) + .with_right(Val::Auto), + justify_content: JustifyContent::Center, + ..default() + }, + children![( Node { display: Display::Block, position_type: PositionType::Absolute, ..default() }, ImageNode::new(assets.camera.clone()), - )); + )], + )); } else { for entity in query.iter() { commands.entity(entity).despawn(); diff --git a/src/heads/heads_ui.rs b/src/heads/heads_ui.rs index a9c855b..0da64ff 100644 --- a/src/heads/heads_ui.rs +++ b/src/heads/heads_ui.rs @@ -1,5 +1,5 @@ use crate::{GameState, backpack::UiHeadState, loading_assets::UIAssets, player::Player}; -use bevy::prelude::*; +use bevy::{ecs::spawn::SpawnIter, prelude::*}; use bevy_ui_gradients::{AngularColorStop, BackgroundGradient, ConicGradient, Gradient, Position}; use std::f32::consts::PI; @@ -36,54 +36,56 @@ pub fn plugin(app: &mut App) { } fn setup(mut commands: Commands, assets: Res) { - commands - .spawn(( - Name::new("heads-ui"), - Node { - position_type: PositionType::Absolute, - bottom: Val::Px(20.0), - right: Val::Px(20.0), - height: Val::Px(74.0), - ..default() - }, - )) - .with_children(|parent| { - for i in 0..HEAD_SLOTS { + commands.spawn(( + Name::new("heads-ui"), + Node { + position_type: PositionType::Absolute, + bottom: Val::Px(20.0), + right: Val::Px(20.0), + height: Val::Px(74.0), + ..default() + }, + Children::spawn(SpawnIter((0..HEAD_SLOTS).map({ + let bg = assets.head_bg.clone(); + let regular = assets.head_regular.clone(); + let selector = assets.head_selector.clone(); + let damage = assets.head_damage.clone(); + + move |i| { spawn_head_ui( - parent, - assets.head_bg.clone(), - assets.head_regular.clone(), - assets.head_selector.clone(), - assets.head_damage.clone(), + bg.clone(), + regular.clone(), + selector.clone(), + damage.clone(), i, - ); + ) } - }); + }))), + )); commands.init_resource::(); } fn spawn_head_ui( - parent: &mut ChildSpawnerCommands, bg: Handle, regular: Handle, selector: Handle, damage: Handle, head_slot: usize, -) { +) -> impl Bundle { const SIZE: f32 = 90.0; const DAMAGE_SIZE: f32 = 74.0; - parent - .spawn((Node { + ( + Node { position_type: PositionType::Relative, justify_content: JustifyContent::Center, align_items: AlignItems::Center, width: Val::Px(SIZE), ..default() - },)) - .with_children(|parent| { - parent.spawn(( + }, + children![ + ( Node { position_type: PositionType::Absolute, top: Val::Px(-30.0), @@ -92,16 +94,15 @@ fn spawn_head_ui( Visibility::Hidden, ImageNode::new(selector), HeadSelector(head_slot), - )); - - parent.spawn(( + ), + ( Node { position_type: PositionType::Absolute, ..default() }, ImageNode::new(bg), - )); - parent.spawn(( + ), + ( Name::new("head-icon"), Node { position_type: PositionType::Absolute, @@ -120,38 +121,37 @@ fn spawn_head_ui( ImageNode::default(), Visibility::Hidden, HeadImage(head_slot), - )); - parent.spawn(( + ), + ( Node { position_type: PositionType::Absolute, ..default() }, ImageNode::new(regular), - )); - parent - .spawn((Node { + ), + ( + Node { height: Val::Px(DAMAGE_SIZE), width: Val::Px(DAMAGE_SIZE), ..default() - },)) - .with_children(|parent| { - parent - .spawn(( - HeadDamage(head_slot), - Node { - position_type: PositionType::Absolute, - display: Display::Block, - overflow: Overflow::clip(), - top: Val::Px(0.), - left: Val::Px(0.), - right: Val::Px(0.), - height: Val::Percent(25.), - ..default() - }, - )) - .with_child(ImageNode::new(damage)); - }); - }); + }, + children![( + HeadDamage(head_slot), + Node { + position_type: PositionType::Absolute, + display: Display::Block, + overflow: Overflow::clip(), + top: Val::Px(0.), + left: Val::Px(0.), + right: Val::Px(0.), + height: Val::Percent(25.), + ..default() + }, + children![ImageNode::new(damage)] + )] + ) + ], + ) } fn update( diff --git a/src/keys.rs b/src/keys.rs index a808cd1..c7484cd 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -28,24 +28,23 @@ fn on_spawn_key(trigger: Trigger, mut commands: Commands, assets: Res< let angle = rand::random::() * PI * 2.; let spawn_dir = Quat::from_rotation_y(angle) * Vec3::new(0.5, 0.6, 0.).normalize(); - commands - .spawn(( - Name::new("key"), - Key(id.clone()), - Transform::from_translation(*position), - Visibility::default(), - Collider::sphere(1.5), - ExternalImpulse::new(spawn_dir * 180.).with_persistence(false), - LockedAxes::ROTATION_LOCKED, - RigidBody::Dynamic, - CollisionEventsEnabled, - Restitution::new(0.6), - )) - .with_child(( + commands.spawn(( + Name::new("key"), + Key(id.clone()), + Transform::from_translation(*position), + Visibility::default(), + Collider::sphere(1.5), + ExternalImpulse::new(spawn_dir * 180.).with_persistence(false), + LockedAxes::ROTATION_LOCKED, + RigidBody::Dynamic, + CollisionEventsEnabled, + Restitution::new(0.6), + Children::spawn(Spawn(( Billboard, SquishAnimation(2.6), SceneRoot(assets.mesh_key.clone()), - )); + ))), + )); } fn collect_key( diff --git a/src/player.rs b/src/player.rs index 618d3ec..7af0635 100644 --- a/src/player.rs +++ b/src/player.rs @@ -64,37 +64,33 @@ fn spawn( let gravity = Vector::NEG_Y * 40.0; let collider = Collider::capsule(0.9, 1.2); - commands - .spawn(( - Name::from("player"), - Player, - ActiveHead(0), - ActiveHeads::new([ - Some(HeadState::new(0, heads_db.as_ref())), - Some(HeadState::new(3, heads_db.as_ref())), - Some(HeadState::new(6, heads_db.as_ref())), - Some(HeadState::new(10, heads_db.as_ref())), - Some(HeadState::new(9, heads_db.as_ref())), - ]), - Hitpoints::new(100), - CameraTarget, - transform, + commands.spawn(( + Name::from("player"), + Player, + ActiveHead(0), + ActiveHeads::new([ + Some(HeadState::new(0, heads_db.as_ref())), + Some(HeadState::new(3, heads_db.as_ref())), + Some(HeadState::new(6, heads_db.as_ref())), + Some(HeadState::new(10, heads_db.as_ref())), + Some(HeadState::new(9, heads_db.as_ref())), + ]), + Hitpoints::new(100), + CameraTarget, + transform, + Visibility::default(), + // LockedAxes::ROTATION_LOCKED, todo + CollisionLayers::new(LayerMask(GameLayer::Player.to_bits()), LayerMask::ALL), + CharacterControllerBundle::new(collider, gravity), + children![( + Name::new("player-rig"), + Transform::default(), Visibility::default(), - // LockedAxes::ROTATION_LOCKED, todo - CollisionLayers::new(LayerMask(GameLayer::Player.to_bits()), LayerMask::ALL), - CharacterControllerBundle::new(collider, gravity), - )) - .with_children(|parent| { - parent - .spawn(( - Name::new("player-rig"), - Transform::default(), - Visibility::default(), - PlayerBodyMesh, - CameraArmRotation, - )) - .with_child(AnimatedCharacter(0)); - }); + PlayerBodyMesh, + CameraArmRotation, + children![AnimatedCharacter(0)] + )], + )); commands.spawn(( AudioPlayer::new(asset_server.load("sfx/heads/angry demonstrator.ogg")),