mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 12:43:34 +00:00
Have EntityCommands methods consume self for easier chaining (#14897)
# Objective Fixes #14883 ## Solution Pretty simple update to `EntityCommands` methods to consume `self` and return it rather than taking `&mut self`. The things probably worth noting: * I added `#[allow(clippy::should_implement_trait)]` to the `add` method because it causes a linting conflict with `std::ops::Add`. * `despawn` and `log_components` now return `Self`. I'm not sure if that's exactly the desired behavior so I'm happy to adjust if that seems wrong. ## Testing Tested with `cargo run -p ci`. I think that should be sufficient to call things good. ## Migration Guide The most likely migration needed is changing code from this: ``` let mut entity = commands.get_or_spawn(entity); if depth_prepass { entity.insert(DepthPrepass); } if normal_prepass { entity.insert(NormalPrepass); } if motion_vector_prepass { entity.insert(MotionVectorPrepass); } if deferred_prepass { entity.insert(DeferredPrepass); } ``` to this: ``` let mut entity = commands.get_or_spawn(entity); if depth_prepass { entity = entity.insert(DepthPrepass); } if normal_prepass { entity = entity.insert(NormalPrepass); } if motion_vector_prepass { entity = entity.insert(MotionVectorPrepass); } if deferred_prepass { entity.insert(DeferredPrepass); } ``` as can be seen in several of the example code updates here. There will probably also be instances where mutable `EntityCommands` vars no longer need to be mutable.
This commit is contained in:
parent
44620dd6ae
commit
484721be80
20 changed files with 211 additions and 153 deletions
|
@ -1,4 +1,5 @@
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
component::Component,
|
component::Component,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
|
@ -44,19 +45,11 @@ pub fn spawn_commands(criterion: &mut Criterion) {
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
let mut commands = Commands::new(&mut command_queue, &world);
|
let mut commands = Commands::new(&mut command_queue, &world);
|
||||||
for i in 0..entity_count {
|
for i in 0..entity_count {
|
||||||
let mut entity = commands.spawn_empty();
|
let mut entity = commands
|
||||||
|
.spawn_empty()
|
||||||
if black_box(i % 2 == 0) {
|
.insert_if(A, || black_box(i % 2 == 0))
|
||||||
entity.insert(A);
|
.insert_if(B, || black_box(i % 3 == 0))
|
||||||
}
|
.insert_if(C, || black_box(i % 4 == 0));
|
||||||
|
|
||||||
if black_box(i % 3 == 0) {
|
|
||||||
entity.insert(B);
|
|
||||||
}
|
|
||||||
|
|
||||||
if black_box(i % 4 == 0) {
|
|
||||||
entity.insert(C);
|
|
||||||
}
|
|
||||||
|
|
||||||
if black_box(i % 5 == 0) {
|
if black_box(i % 5 == 0) {
|
||||||
entity.despawn();
|
entity.despawn();
|
||||||
|
|
|
@ -584,20 +584,12 @@ pub fn extract_camera_prepass_phase(
|
||||||
|
|
||||||
live_entities.insert(entity);
|
live_entities.insert(entity);
|
||||||
|
|
||||||
let mut entity = commands.get_or_spawn(entity);
|
commands
|
||||||
|
.get_or_spawn(entity)
|
||||||
if depth_prepass {
|
.insert_if(DepthPrepass, || depth_prepass)
|
||||||
entity.insert(DepthPrepass);
|
.insert_if(NormalPrepass, || normal_prepass)
|
||||||
}
|
.insert_if(MotionVectorPrepass, || motion_vector_prepass)
|
||||||
if normal_prepass {
|
.insert_if(DeferredPrepass, || deferred_prepass);
|
||||||
entity.insert(NormalPrepass);
|
|
||||||
}
|
|
||||||
if motion_vector_prepass {
|
|
||||||
entity.insert(MotionVectorPrepass);
|
|
||||||
}
|
|
||||||
if deferred_prepass {
|
|
||||||
entity.insert(DeferredPrepass);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
opaque_3d_prepass_phases.retain(|entity, _| live_entities.contains(entity));
|
opaque_3d_prepass_phases.retain(|entity, _| live_entities.contains(entity));
|
||||||
|
|
|
@ -364,9 +364,7 @@ impl<'w, 's> Commands<'w, 's> {
|
||||||
/// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
|
/// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
|
pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
|
||||||
let mut e = self.spawn_empty();
|
self.spawn_empty().insert(bundle)
|
||||||
e.insert(bundle);
|
|
||||||
e
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the [`EntityCommands`] for the requested [`Entity`].
|
/// Returns the [`EntityCommands`] for the requested [`Entity`].
|
||||||
|
@ -951,10 +949,51 @@ impl EntityCommands<'_> {
|
||||||
/// # bevy_ecs::system::assert_is_system(add_combat_stats_system);
|
/// # bevy_ecs::system::assert_is_system(add_combat_stats_system);
|
||||||
/// ```
|
/// ```
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn insert(&mut self, bundle: impl Bundle) -> &mut Self {
|
pub fn insert(self, bundle: impl Bundle) -> Self {
|
||||||
self.add(insert(bundle, InsertMode::Replace))
|
self.add(insert(bundle, InsertMode::Replace))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Similar to [`Self::insert`] but will only insert if the predicate returns true.
|
||||||
|
/// This is useful for chaining method calls.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// The command will panic when applied if the associated entity does not exist.
|
||||||
|
///
|
||||||
|
/// To avoid a panic in this case, use the command [`Self::try_insert_if`] instead.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use bevy_ecs::prelude::*;
|
||||||
|
/// # #[derive(Resource)]
|
||||||
|
/// # struct PlayerEntity { entity: Entity }
|
||||||
|
/// # impl PlayerEntity { fn is_spectator(&self) -> bool { true } }
|
||||||
|
/// #[derive(Component)]
|
||||||
|
/// struct StillLoadingStats;
|
||||||
|
/// #[derive(Component)]
|
||||||
|
/// struct Health(u32);
|
||||||
|
///
|
||||||
|
/// fn add_health_system(mut commands: Commands, player: Res<PlayerEntity>) {
|
||||||
|
/// commands
|
||||||
|
/// .entity(player.entity)
|
||||||
|
/// .insert_if(Health(10), || !player.is_spectator())
|
||||||
|
/// .remove::<StillLoadingStats>();
|
||||||
|
/// }
|
||||||
|
/// # bevy_ecs::system::assert_is_system(add_health_system);
|
||||||
|
/// ```
|
||||||
|
#[track_caller]
|
||||||
|
pub fn insert_if<F>(self, bundle: impl Bundle, condition: F) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce() -> bool,
|
||||||
|
{
|
||||||
|
if condition() {
|
||||||
|
self.add(insert(bundle, InsertMode::Replace))
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds a [`Bundle`] of components to the entity without overwriting.
|
/// Adds a [`Bundle`] of components to the entity without overwriting.
|
||||||
///
|
///
|
||||||
/// This is the same as [`EntityCommands::insert`], but in case of duplicate
|
/// This is the same as [`EntityCommands::insert`], but in case of duplicate
|
||||||
|
@ -968,7 +1007,7 @@ impl EntityCommands<'_> {
|
||||||
///
|
///
|
||||||
/// To avoid a panic in this case, use the command [`Self::try_insert_if_new`]
|
/// To avoid a panic in this case, use the command [`Self::try_insert_if_new`]
|
||||||
/// instead.
|
/// instead.
|
||||||
pub fn insert_if_new(&mut self, bundle: impl Bundle) -> &mut Self {
|
pub fn insert_if_new(self, bundle: impl Bundle) -> Self {
|
||||||
self.add(insert(bundle, InsertMode::Keep))
|
self.add(insert(bundle, InsertMode::Keep))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -988,16 +1027,15 @@ impl EntityCommands<'_> {
|
||||||
/// - `T` must have the same layout as the one passed during `component_id` creation.
|
/// - `T` must have the same layout as the one passed during `component_id` creation.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub unsafe fn insert_by_id<T: Send + 'static>(
|
pub unsafe fn insert_by_id<T: Send + 'static>(
|
||||||
&mut self,
|
self,
|
||||||
component_id: ComponentId,
|
component_id: ComponentId,
|
||||||
value: T,
|
value: T,
|
||||||
) -> &mut Self {
|
) -> Self {
|
||||||
let caller = Location::caller();
|
let caller = Location::caller();
|
||||||
// SAFETY: same invariants as parent call
|
// SAFETY: same invariants as parent call
|
||||||
self.add(unsafe {insert_by_id(component_id, value, move |entity| {
|
self.add(unsafe {insert_by_id(component_id, value, move |entity| {
|
||||||
panic!("error[B0003]: {caller}: Could not insert a component {component_id:?} (with type {}) for entity {entity:?} because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/#b0003", std::any::type_name::<T>());
|
panic!("error[B0003]: {caller}: Could not insert a component {component_id:?} (with type {}) for entity {entity:?} because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/#b0003", std::any::type_name::<T>());
|
||||||
})});
|
})})
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to add a dynamic component to an entity.
|
/// Attempts to add a dynamic component to an entity.
|
||||||
|
@ -1009,13 +1047,12 @@ impl EntityCommands<'_> {
|
||||||
/// - [`ComponentId`] must be from the same world as `self`.
|
/// - [`ComponentId`] must be from the same world as `self`.
|
||||||
/// - `T` must have the same layout as the one passed during `component_id` creation.
|
/// - `T` must have the same layout as the one passed during `component_id` creation.
|
||||||
pub unsafe fn try_insert_by_id<T: Send + 'static>(
|
pub unsafe fn try_insert_by_id<T: Send + 'static>(
|
||||||
&mut self,
|
self,
|
||||||
component_id: ComponentId,
|
component_id: ComponentId,
|
||||||
value: T,
|
value: T,
|
||||||
) -> &mut Self {
|
) -> Self {
|
||||||
// SAFETY: same invariants as parent call
|
// SAFETY: same invariants as parent call
|
||||||
self.add(unsafe { insert_by_id(component_id, value, |_| {}) });
|
self.add(unsafe { insert_by_id(component_id, value, |_| {}) })
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to add a [`Bundle`] of components to the entity.
|
/// Tries to add a [`Bundle`] of components to the entity.
|
||||||
|
@ -1067,10 +1104,48 @@ impl EntityCommands<'_> {
|
||||||
/// # bevy_ecs::system::assert_is_system(add_combat_stats_system);
|
/// # bevy_ecs::system::assert_is_system(add_combat_stats_system);
|
||||||
/// ```
|
/// ```
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn try_insert(&mut self, bundle: impl Bundle) -> &mut Self {
|
pub fn try_insert(self, bundle: impl Bundle) -> Self {
|
||||||
self.add(try_insert(bundle, InsertMode::Replace))
|
self.add(try_insert(bundle, InsertMode::Replace))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Similar to [`Self::try_insert`] but will only try to insert if the predicate returns true.
|
||||||
|
/// This is useful for chaining method calls.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use bevy_ecs::prelude::*;
|
||||||
|
/// # #[derive(Resource)]
|
||||||
|
/// # struct PlayerEntity { entity: Entity }
|
||||||
|
/// # impl PlayerEntity { fn is_spectator(&self) -> bool { true } }
|
||||||
|
/// #[derive(Component)]
|
||||||
|
/// struct StillLoadingStats;
|
||||||
|
/// #[derive(Component)]
|
||||||
|
/// struct Health(u32);
|
||||||
|
///
|
||||||
|
/// fn add_health_system(mut commands: Commands, player: Res<PlayerEntity>) {
|
||||||
|
/// commands.entity(player.entity)
|
||||||
|
/// .try_insert_if(Health(10), || !player.is_spectator())
|
||||||
|
/// .remove::<StillLoadingStats>();
|
||||||
|
///
|
||||||
|
/// commands.entity(player.entity)
|
||||||
|
/// // This will not panic nor will it add the component
|
||||||
|
/// .try_insert_if(Health(5), || !player.is_spectator());
|
||||||
|
/// }
|
||||||
|
/// # bevy_ecs::system::assert_is_system(add_health_system);
|
||||||
|
/// ```
|
||||||
|
#[track_caller]
|
||||||
|
pub fn try_insert_if<F>(self, bundle: impl Bundle, condition: F) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce() -> bool,
|
||||||
|
{
|
||||||
|
if condition() {
|
||||||
|
self.add(try_insert(bundle, InsertMode::Replace))
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Tries to add a [`Bundle`] of components to the entity without overwriting.
|
/// Tries to add a [`Bundle`] of components to the entity without overwriting.
|
||||||
///
|
///
|
||||||
/// This is the same as [`EntityCommands::try_insert`], but in case of duplicate
|
/// This is the same as [`EntityCommands::try_insert`], but in case of duplicate
|
||||||
|
@ -1080,7 +1155,7 @@ impl EntityCommands<'_> {
|
||||||
/// # Note
|
/// # Note
|
||||||
///
|
///
|
||||||
/// Unlike [`Self::insert_if_new`], this will not panic if the associated entity does not exist.
|
/// Unlike [`Self::insert_if_new`], this will not panic if the associated entity does not exist.
|
||||||
pub fn try_insert_if_new(&mut self, bundle: impl Bundle) -> &mut Self {
|
pub fn try_insert_if_new(self, bundle: impl Bundle) -> Self {
|
||||||
self.add(try_insert(bundle, InsertMode::Keep))
|
self.add(try_insert(bundle, InsertMode::Keep))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,7 +1194,7 @@ impl EntityCommands<'_> {
|
||||||
/// }
|
/// }
|
||||||
/// # bevy_ecs::system::assert_is_system(remove_combat_stats_system);
|
/// # bevy_ecs::system::assert_is_system(remove_combat_stats_system);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn remove<T>(&mut self) -> &mut Self
|
pub fn remove<T>(self) -> Self
|
||||||
where
|
where
|
||||||
T: Bundle,
|
T: Bundle,
|
||||||
{
|
{
|
||||||
|
@ -1127,12 +1202,12 @@ impl EntityCommands<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a component from the entity.
|
/// Removes a component from the entity.
|
||||||
pub fn remove_by_id(&mut self, component_id: ComponentId) -> &mut Self {
|
pub fn remove_by_id(self, component_id: ComponentId) -> Self {
|
||||||
self.add(remove_by_id(component_id))
|
self.add(remove_by_id(component_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes all components associated with the entity.
|
/// Removes all components associated with the entity.
|
||||||
pub fn clear(&mut self) -> &mut Self {
|
pub fn clear(self) -> Self {
|
||||||
self.add(clear())
|
self.add(clear())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1164,8 +1239,8 @@ impl EntityCommands<'_> {
|
||||||
/// # bevy_ecs::system::assert_is_system(remove_character_system);
|
/// # bevy_ecs::system::assert_is_system(remove_character_system);
|
||||||
/// ```
|
/// ```
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn despawn(&mut self) {
|
pub fn despawn(self) -> Self {
|
||||||
self.add(despawn());
|
self.add(despawn())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes an [`EntityCommand`] to the queue, which will get executed for the current [`Entity`].
|
/// Pushes an [`EntityCommand`] to the queue, which will get executed for the current [`Entity`].
|
||||||
|
@ -1184,7 +1259,8 @@ impl EntityCommands<'_> {
|
||||||
/// # }
|
/// # }
|
||||||
/// # bevy_ecs::system::assert_is_system(my_system);
|
/// # bevy_ecs::system::assert_is_system(my_system);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn add<M: 'static>(&mut self, command: impl EntityCommand<M>) -> &mut Self {
|
#[allow(clippy::should_implement_trait)]
|
||||||
|
pub fn add<M: 'static>(mut self, command: impl EntityCommand<M>) -> Self {
|
||||||
self.commands.add(command.with_entity(self.entity));
|
self.commands.add(command.with_entity(self.entity));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -1226,7 +1302,7 @@ impl EntityCommands<'_> {
|
||||||
/// }
|
/// }
|
||||||
/// # bevy_ecs::system::assert_is_system(remove_combat_stats_system);
|
/// # bevy_ecs::system::assert_is_system(remove_combat_stats_system);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn retain<T>(&mut self) -> &mut Self
|
pub fn retain<T>(self) -> Self
|
||||||
where
|
where
|
||||||
T: Bundle,
|
T: Bundle,
|
||||||
{
|
{
|
||||||
|
@ -1238,8 +1314,8 @@ impl EntityCommands<'_> {
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// The command will panic when applied if the associated entity does not exist.
|
/// The command will panic when applied if the associated entity does not exist.
|
||||||
pub fn log_components(&mut self) {
|
pub fn log_components(self) -> Self {
|
||||||
self.add(log_components);
|
self.add(log_components)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the underlying [`Commands`].
|
/// Returns the underlying [`Commands`].
|
||||||
|
@ -1251,18 +1327,14 @@ impl EntityCommands<'_> {
|
||||||
/// watches this entity.
|
/// watches this entity.
|
||||||
///
|
///
|
||||||
/// [`Trigger`]: crate::observer::Trigger
|
/// [`Trigger`]: crate::observer::Trigger
|
||||||
pub fn trigger(&mut self, event: impl Event) -> &mut Self {
|
pub fn trigger(mut self, event: impl Event) -> Self {
|
||||||
self.commands.trigger_targets(event, self.entity);
|
self.commands.trigger_targets(event, self.entity);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an [`Observer`] listening for a trigger of type `T` that targets this entity.
|
/// Creates an [`Observer`] listening for a trigger of type `T` that targets this entity.
|
||||||
pub fn observe<E: Event, B: Bundle, M>(
|
pub fn observe<E: Event, B: Bundle, M>(self, system: impl IntoObserverSystem<E, B, M>) -> Self {
|
||||||
&mut self,
|
self.add(observe(system))
|
||||||
system: impl IntoObserverSystem<E, B, M>,
|
|
||||||
) -> &mut Self {
|
|
||||||
self.add(observe(system));
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -581,7 +581,7 @@ pub fn extract_camera_previous_view_data(
|
||||||
) {
|
) {
|
||||||
for (entity, camera, maybe_previous_view_data) in cameras_3d.iter() {
|
for (entity, camera, maybe_previous_view_data) in cameras_3d.iter() {
|
||||||
if camera.is_active {
|
if camera.is_active {
|
||||||
let mut entity = commands.get_or_spawn(entity);
|
let entity = commands.get_or_spawn(entity);
|
||||||
|
|
||||||
if let Some(previous_view_data) = maybe_previous_view_data {
|
if let Some(previous_view_data) = maybe_previous_view_data {
|
||||||
entity.insert(previous_view_data.clone());
|
entity.insert(previous_view_data.clone());
|
||||||
|
|
|
@ -154,7 +154,7 @@ fn apply_wireframe_material(
|
||||||
global_material: Res<GlobalWireframeMaterial>,
|
global_material: Res<GlobalWireframeMaterial>,
|
||||||
) {
|
) {
|
||||||
for e in removed_wireframes.read().chain(no_wireframes.iter()) {
|
for e in removed_wireframes.read().chain(no_wireframes.iter()) {
|
||||||
if let Some(mut commands) = commands.get_entity(e) {
|
if let Some(commands) = commands.get_entity(e) {
|
||||||
commands.remove::<Handle<WireframeMaterial>>();
|
commands.remove::<Handle<WireframeMaterial>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,7 +231,7 @@ pub fn update_interactions(
|
||||||
for (hovered_entity, new_interaction) in new_interaction_state.drain() {
|
for (hovered_entity, new_interaction) in new_interaction_state.drain() {
|
||||||
if let Ok(mut interaction) = interact.get_mut(hovered_entity) {
|
if let Ok(mut interaction) = interact.get_mut(hovered_entity) {
|
||||||
*interaction = new_interaction;
|
*interaction = new_interaction;
|
||||||
} else if let Some(mut entity_commands) = commands.get_entity(hovered_entity) {
|
} else if let Some(entity_commands) = commands.get_entity(hovered_entity) {
|
||||||
entity_commands.try_insert(new_interaction);
|
entity_commands.try_insert(new_interaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -935,9 +935,7 @@ pub fn extract_cameras(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut commands = commands.get_or_spawn(entity);
|
let mut commands = commands.get_or_spawn(entity).insert((
|
||||||
|
|
||||||
commands.insert((
|
|
||||||
ExtractedCamera {
|
ExtractedCamera {
|
||||||
target: camera.target.normalize(primary_window),
|
target: camera.target.normalize(primary_window),
|
||||||
viewport: camera.viewport.clone(),
|
viewport: camera.viewport.clone(),
|
||||||
|
@ -973,15 +971,15 @@ pub fn extract_cameras(
|
||||||
));
|
));
|
||||||
|
|
||||||
if let Some(temporal_jitter) = temporal_jitter {
|
if let Some(temporal_jitter) = temporal_jitter {
|
||||||
commands.insert(temporal_jitter.clone());
|
commands = commands.insert(temporal_jitter.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(render_layers) = render_layers {
|
if let Some(render_layers) = render_layers {
|
||||||
commands.insert(render_layers.clone());
|
commands = commands.insert(render_layers.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(perspective) = projection {
|
if let Some(perspective) = projection {
|
||||||
commands.insert(perspective.clone());
|
commands = commands.insert(perspective.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if gpu_culling {
|
if gpu_culling {
|
||||||
|
|
|
@ -150,7 +150,7 @@ fn apply_wireframe_material(
|
||||||
global_material: Res<GlobalWireframe2dMaterial>,
|
global_material: Res<GlobalWireframe2dMaterial>,
|
||||||
) {
|
) {
|
||||||
for e in removed_wireframes.read().chain(no_wireframes.iter()) {
|
for e in removed_wireframes.read().chain(no_wireframes.iter()) {
|
||||||
if let Some(mut commands) = commands.get_entity(e) {
|
if let Some(commands) = commands.get_entity(e) {
|
||||||
commands.remove::<Handle<Wireframe2dMaterial>>();
|
commands.remove::<Handle<Wireframe2dMaterial>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,8 +88,7 @@ pub fn create_windows<F: QueryFilter + 'static>(
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Ok(handle_wrapper) = RawHandleWrapper::new(winit_window) {
|
if let Ok(handle_wrapper) = RawHandleWrapper::new(winit_window) {
|
||||||
let mut entity = commands.entity(entity);
|
commands.entity(entity).insert(handle_wrapper.clone());
|
||||||
entity.insert(handle_wrapper.clone());
|
|
||||||
if let Some(handle_holder) = handle_holder {
|
if let Some(handle_holder) = handle_holder {
|
||||||
*handle_holder.0.lock().unwrap() = Some(handle_wrapper);
|
*handle_holder.0.lock().unwrap() = Some(handle_wrapper);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ fn spawn_sprites(
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
if let Some(scale_mode) = scale_mode {
|
if let Some(scale_mode) = scale_mode {
|
||||||
cmd.insert(scale_mode);
|
cmd = cmd.insert(scale_mode);
|
||||||
}
|
}
|
||||||
cmd.with_children(|builder| {
|
cmd.with_children(|builder| {
|
||||||
builder.spawn(Text2dBundle {
|
builder.spawn(Text2dBundle {
|
||||||
|
|
|
@ -49,16 +49,18 @@ fn modify_aa(
|
||||||
// No AA
|
// No AA
|
||||||
if keys.just_pressed(KeyCode::Digit1) {
|
if keys.just_pressed(KeyCode::Digit1) {
|
||||||
*msaa = Msaa::Off;
|
*msaa = Msaa::Off;
|
||||||
camera.remove::<Fxaa>();
|
camera = camera
|
||||||
camera.remove::<SmaaSettings>();
|
.remove::<Fxaa>()
|
||||||
camera.remove::<TemporalAntiAliasBundle>();
|
.remove::<SmaaSettings>()
|
||||||
|
.remove::<TemporalAntiAliasBundle>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// MSAA
|
// MSAA
|
||||||
if keys.just_pressed(KeyCode::Digit2) && *msaa == Msaa::Off {
|
if keys.just_pressed(KeyCode::Digit2) && *msaa == Msaa::Off {
|
||||||
camera.remove::<Fxaa>();
|
camera = camera
|
||||||
camera.remove::<SmaaSettings>();
|
.remove::<Fxaa>()
|
||||||
camera.remove::<TemporalAntiAliasBundle>();
|
.remove::<SmaaSettings>()
|
||||||
|
.remove::<TemporalAntiAliasBundle>();
|
||||||
|
|
||||||
*msaa = Msaa::Sample4;
|
*msaa = Msaa::Sample4;
|
||||||
}
|
}
|
||||||
|
@ -79,10 +81,10 @@ fn modify_aa(
|
||||||
// FXAA
|
// FXAA
|
||||||
if keys.just_pressed(KeyCode::Digit3) && fxaa.is_none() {
|
if keys.just_pressed(KeyCode::Digit3) && fxaa.is_none() {
|
||||||
*msaa = Msaa::Off;
|
*msaa = Msaa::Off;
|
||||||
camera.remove::<SmaaSettings>();
|
camera = camera
|
||||||
camera.remove::<TemporalAntiAliasBundle>();
|
.remove::<SmaaSettings>()
|
||||||
|
.remove::<TemporalAntiAliasBundle>()
|
||||||
camera.insert(Fxaa::default());
|
.insert(Fxaa::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
// FXAA Settings
|
// FXAA Settings
|
||||||
|
@ -112,10 +114,10 @@ fn modify_aa(
|
||||||
// SMAA
|
// SMAA
|
||||||
if keys.just_pressed(KeyCode::Digit4) && smaa.is_none() {
|
if keys.just_pressed(KeyCode::Digit4) && smaa.is_none() {
|
||||||
*msaa = Msaa::Off;
|
*msaa = Msaa::Off;
|
||||||
camera.remove::<Fxaa>();
|
camera = camera
|
||||||
camera.remove::<TemporalAntiAliasBundle>();
|
.remove::<Fxaa>()
|
||||||
|
.remove::<TemporalAntiAliasBundle>()
|
||||||
camera.insert(SmaaSettings::default());
|
.insert(SmaaSettings::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
// SMAA Settings
|
// SMAA Settings
|
||||||
|
@ -137,10 +139,10 @@ fn modify_aa(
|
||||||
// TAA
|
// TAA
|
||||||
if keys.just_pressed(KeyCode::Digit5) && taa.is_none() {
|
if keys.just_pressed(KeyCode::Digit5) && taa.is_none() {
|
||||||
*msaa = Msaa::Off;
|
*msaa = Msaa::Off;
|
||||||
camera.remove::<Fxaa>();
|
camera
|
||||||
camera.remove::<SmaaSettings>();
|
.remove::<Fxaa>()
|
||||||
|
.remove::<SmaaSettings>()
|
||||||
camera.insert(TemporalAntiAliasBundle::default());
|
.insert(TemporalAntiAliasBundle::default());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,16 +70,17 @@ fn main() {
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, app_settings: Res<AppSettings>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, app_settings: Res<AppSettings>) {
|
||||||
// Spawn the camera. Enable HDR and bloom, as that highlights the depth of
|
// Spawn the camera. Enable HDR and bloom, as that highlights the depth of
|
||||||
// field effect.
|
// field effect.
|
||||||
let mut camera = commands.spawn(Camera3dBundle {
|
let camera = commands
|
||||||
transform: Transform::from_xyz(0.0, 4.5, 8.25).looking_at(Vec3::ZERO, Vec3::Y),
|
.spawn(Camera3dBundle {
|
||||||
camera: Camera {
|
transform: Transform::from_xyz(0.0, 4.5, 8.25).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
hdr: true,
|
camera: Camera {
|
||||||
|
hdr: true,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
tonemapping: Tonemapping::TonyMcMapface,
|
||||||
..default()
|
..default()
|
||||||
},
|
})
|
||||||
tonemapping: Tonemapping::TonyMcMapface,
|
.insert(BloomSettings::NATURAL);
|
||||||
..default()
|
|
||||||
});
|
|
||||||
camera.insert(BloomSettings::NATURAL);
|
|
||||||
|
|
||||||
// Insert the depth of field settings.
|
// Insert the depth of field settings.
|
||||||
if let Some(dof_settings) = Option::<DepthOfFieldSettings>::from(*app_settings) {
|
if let Some(dof_settings) = Option::<DepthOfFieldSettings>::from(*app_settings) {
|
||||||
|
|
|
@ -144,18 +144,17 @@ fn spawn_cars(
|
||||||
|
|
||||||
for i in 0..N_CARS {
|
for i in 0..N_CARS {
|
||||||
let color = colors[i % colors.len()].clone();
|
let color = colors[i % colors.len()].clone();
|
||||||
let mut entity = commands.spawn((
|
let mut entity = commands
|
||||||
PbrBundle {
|
.spawn((
|
||||||
mesh: box_mesh.clone(),
|
PbrBundle {
|
||||||
material: color.clone(),
|
mesh: box_mesh.clone(),
|
||||||
transform: Transform::from_scale(Vec3::splat(0.5)),
|
material: color.clone(),
|
||||||
..default()
|
transform: Transform::from_scale(Vec3::splat(0.5)),
|
||||||
},
|
..default()
|
||||||
Moves(i as f32 * 2.0),
|
},
|
||||||
));
|
Moves(i as f32 * 2.0),
|
||||||
if i == 0 {
|
))
|
||||||
entity.insert(CameraTracked);
|
.insert_if(CameraTracked, || i == 0);
|
||||||
}
|
|
||||||
entity.with_children(|parent| {
|
entity.with_children(|parent| {
|
||||||
parent.spawn(PbrBundle {
|
parent.spawn(PbrBundle {
|
||||||
mesh: box_mesh.clone(),
|
mesh: box_mesh.clone(),
|
||||||
|
|
|
@ -123,29 +123,34 @@ fn update(
|
||||||
|
|
||||||
let (camera_entity, ssao_settings, temporal_jitter) = camera.single();
|
let (camera_entity, ssao_settings, temporal_jitter) = camera.single();
|
||||||
|
|
||||||
let mut commands = commands.entity(camera_entity);
|
let mut commands = commands
|
||||||
|
.entity(camera_entity)
|
||||||
|
.insert_if(
|
||||||
|
ScreenSpaceAmbientOcclusionSettings {
|
||||||
|
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::Low,
|
||||||
|
},
|
||||||
|
|| keycode.just_pressed(KeyCode::Digit2),
|
||||||
|
)
|
||||||
|
.insert_if(
|
||||||
|
ScreenSpaceAmbientOcclusionSettings {
|
||||||
|
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::Medium,
|
||||||
|
},
|
||||||
|
|| keycode.just_pressed(KeyCode::Digit3),
|
||||||
|
)
|
||||||
|
.insert_if(
|
||||||
|
ScreenSpaceAmbientOcclusionSettings {
|
||||||
|
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::High,
|
||||||
|
},
|
||||||
|
|| keycode.just_pressed(KeyCode::Digit4),
|
||||||
|
)
|
||||||
|
.insert_if(
|
||||||
|
ScreenSpaceAmbientOcclusionSettings {
|
||||||
|
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::Ultra,
|
||||||
|
},
|
||||||
|
|| keycode.just_pressed(KeyCode::Digit5),
|
||||||
|
);
|
||||||
if keycode.just_pressed(KeyCode::Digit1) {
|
if keycode.just_pressed(KeyCode::Digit1) {
|
||||||
commands.remove::<ScreenSpaceAmbientOcclusionSettings>();
|
commands = commands.remove::<ScreenSpaceAmbientOcclusionSettings>();
|
||||||
}
|
|
||||||
if keycode.just_pressed(KeyCode::Digit2) {
|
|
||||||
commands.insert(ScreenSpaceAmbientOcclusionSettings {
|
|
||||||
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::Low,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if keycode.just_pressed(KeyCode::Digit3) {
|
|
||||||
commands.insert(ScreenSpaceAmbientOcclusionSettings {
|
|
||||||
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::Medium,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if keycode.just_pressed(KeyCode::Digit4) {
|
|
||||||
commands.insert(ScreenSpaceAmbientOcclusionSettings {
|
|
||||||
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::High,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if keycode.just_pressed(KeyCode::Digit5) {
|
|
||||||
commands.insert(ScreenSpaceAmbientOcclusionSettings {
|
|
||||||
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::Ultra,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if keycode.just_pressed(KeyCode::Space) {
|
if keycode.just_pressed(KeyCode::Space) {
|
||||||
if temporal_jitter.is_some() {
|
if temporal_jitter.is_some() {
|
||||||
|
|
|
@ -310,7 +310,7 @@ fn setup_node_rects(commands: &mut Commands) {
|
||||||
));
|
));
|
||||||
|
|
||||||
if let NodeType::Clip(ref clip) = node_type {
|
if let NodeType::Clip(ref clip) = node_type {
|
||||||
container.insert((
|
container = container.insert((
|
||||||
Interaction::None,
|
Interaction::None,
|
||||||
RelativeCursorPosition::default(),
|
RelativeCursorPosition::default(),
|
||||||
(*clip).clone(),
|
(*clip).clone(),
|
||||||
|
|
|
@ -148,7 +148,7 @@ fn on_remove_mine(
|
||||||
fn explode_mine(trigger: Trigger<Explode>, query: Query<&Mine>, mut commands: Commands) {
|
fn explode_mine(trigger: Trigger<Explode>, query: Query<&Mine>, mut commands: Commands) {
|
||||||
// If a triggered event is targeting a specific entity you can access it with `.entity()`
|
// If a triggered event is targeting a specific entity you can access it with `.entity()`
|
||||||
let id = trigger.entity();
|
let id = trigger.entity();
|
||||||
let Some(mut entity) = commands.get_entity(id) else {
|
let Some(entity) = commands.get_entity(id) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
info!("Boom! {:?} exploded.", id.index());
|
info!("Boom! {:?} exploded.", id.index());
|
||||||
|
|
|
@ -743,7 +743,7 @@ mod menu {
|
||||||
button_text_style.clone(),
|
button_text_style.clone(),
|
||||||
));
|
));
|
||||||
for volume_setting in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] {
|
for volume_setting in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] {
|
||||||
let mut entity = parent.spawn((
|
let entity = parent.spawn((
|
||||||
ButtonBundle {
|
ButtonBundle {
|
||||||
style: Style {
|
style: Style {
|
||||||
width: Val::Px(30.0),
|
width: Val::Px(30.0),
|
||||||
|
|
|
@ -257,7 +257,7 @@ fn spawn_button(
|
||||||
));
|
));
|
||||||
|
|
||||||
if let Some(image) = image {
|
if let Some(image) = image {
|
||||||
builder.insert(UiImage::new(image));
|
builder = builder.insert(UiImage::new(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
if spawn_text {
|
if spawn_text {
|
||||||
|
|
|
@ -163,26 +163,23 @@ fn setup(
|
||||||
fibonacci_spiral_on_sphere(golden_ratio, i, N_POINTS);
|
fibonacci_spiral_on_sphere(golden_ratio, i, N_POINTS);
|
||||||
let unit_sphere_p = spherical_polar_to_cartesian(spherical_polar_theta_phi);
|
let unit_sphere_p = spherical_polar_to_cartesian(spherical_polar_theta_phi);
|
||||||
let (mesh, transform) = meshes.choose(&mut material_rng).unwrap();
|
let (mesh, transform) = meshes.choose(&mut material_rng).unwrap();
|
||||||
let mut cube = commands.spawn(PbrBundle {
|
commands
|
||||||
mesh: mesh.clone(),
|
.spawn(PbrBundle {
|
||||||
material: materials.choose(&mut material_rng).unwrap().clone(),
|
mesh: mesh.clone(),
|
||||||
transform: Transform::from_translation((radius * unit_sphere_p).as_vec3())
|
material: materials.choose(&mut material_rng).unwrap().clone(),
|
||||||
.looking_at(Vec3::ZERO, Vec3::Y)
|
transform: Transform::from_translation((radius * unit_sphere_p).as_vec3())
|
||||||
.mul_transform(*transform),
|
.looking_at(Vec3::ZERO, Vec3::Y)
|
||||||
..default()
|
.mul_transform(*transform),
|
||||||
});
|
..default()
|
||||||
if args.no_frustum_culling {
|
})
|
||||||
cube.insert(NoFrustumCulling);
|
.insert_if(NoFrustumCulling, || args.no_frustum_culling)
|
||||||
}
|
.insert_if(NoAutomaticBatching, || args.no_automatic_batching);
|
||||||
if args.no_automatic_batching {
|
|
||||||
cube.insert(NoAutomaticBatching);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// camera
|
// camera
|
||||||
let mut camera = commands.spawn(Camera3dBundle::default());
|
let mut camera = commands.spawn(Camera3dBundle::default());
|
||||||
if args.gpu_culling {
|
if args.gpu_culling {
|
||||||
camera.insert(GpuCulling);
|
camera = camera.insert(GpuCulling);
|
||||||
}
|
}
|
||||||
if args.no_cpu_culling {
|
if args.no_cpu_culling {
|
||||||
camera.insert(NoCpuCulling);
|
camera.insert(NoCpuCulling);
|
||||||
|
|
|
@ -413,7 +413,7 @@ fn spawn_tree(
|
||||||
&& (depth >= update_filter.min_depth && depth <= update_filter.max_depth);
|
&& (depth >= update_filter.min_depth && depth <= update_filter.max_depth);
|
||||||
|
|
||||||
if update {
|
if update {
|
||||||
cmd.insert(UpdateValue(sep));
|
cmd = cmd.insert(UpdateValue(sep));
|
||||||
result.active_nodes += 1;
|
result.active_nodes += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,7 +426,7 @@ fn spawn_tree(
|
||||||
};
|
};
|
||||||
|
|
||||||
// only insert the components necessary for the transform propagation
|
// only insert the components necessary for the transform propagation
|
||||||
cmd.insert(TransformBundle::from(transform));
|
cmd = cmd.insert(TransformBundle::from(transform));
|
||||||
|
|
||||||
cmd.id()
|
cmd.id()
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue