Skip to content

Commit

Permalink
Adding WorldQuery for WithBundle (bevyengine#2024)
Browse files Browse the repository at this point in the history
In response to bevyengine#2023, here is a draft for a PR. 

Fixes bevyengine#2023

I've added an example to show how to use `WithBundle`, and also to test it out. 

Right now there is a bug: If a bundle and a query are "the same", then it doesn't filter out
what it needs to filter out. 

Example: 

```
Print component initated from bundle.
[examples/ecs/query_bundle.rs:57] x = Dummy( <========= This should not get printed
    111,
)
[examples/ecs/query_bundle.rs:57] x = Dummy(
    222,
)
Show all components
[examples/ecs/query_bundle.rs:50] x = Dummy(
    111,
)
[examples/ecs/query_bundle.rs:50] x = Dummy(
    222,
)
```

However, it behaves the right way, if I add one more component to the bundle,
so the query and the bundle doesn't look the same:

```
Print component initated from bundle.
[examples/ecs/query_bundle.rs:57] x = Dummy(
    222,
)
Show all components
[examples/ecs/query_bundle.rs:50] x = Dummy(
    111,
)
[examples/ecs/query_bundle.rs:50] x = Dummy(
    222,
)
```

I hope this helps. I'm definitely up for tinkering with this, and adding anything that I'm asked to add
or change. 





Co-authored-by: Carter Anderson <mcanders1@gmail.com>
  • Loading branch information
2 people authored and ostwilkens committed Jul 27, 2021
1 parent 0c16215 commit 0c2f17f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ path = "examples/ecs/system_sets.rs"
name = "timers"
path = "examples/ecs/timers.rs"

[[example]]
name = "query_bundle"
path = "examples/ecs/query_bundle.rs"

# Games
[[example]]
name = "alien_cake_addict"
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::{any::TypeId, collections::HashMap};
/// An ordered collection of components, commonly used for spawning entities, and adding and
/// removing components in bulk.
///
/// You cannot query for a bundle, only individual components within it.
/// In order to query for components in a bundle use [crate::query::WithBundle].
///
/// Typically, you will simply use `#[derive(Bundle)]` when creating your own `Bundle`.
/// The `Bundle` trait is automatically implemented for tuples of components:
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_ecs/src/query/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ impl<'a, T: Component> Fetch<'a> for WithoutFetch<T> {

pub struct WithBundle<T: Bundle>(PhantomData<T>);

impl<T: Bundle> WorldQuery for WithBundle<T> {
type Fetch = WithBundleFetch<T>;
type State = WithBundleState<T>;
}

pub struct WithBundleFetch<T: Bundle> {
is_dense: bool,
marker: PhantomData<T>,
Expand Down
10 changes: 10 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ git checkout v0.4.0

## Table of Contents

- [Examples](#examples)
- [Table of Contents](#table-of-contents)
- [The Bare Minimum](#the-bare-minimum)
- [Hello, World!](#hello-world)
- [Cross-Platform Examples](#cross-platform-examples)
Expand All @@ -53,8 +55,15 @@ git checkout v0.4.0
- [Window](#window)
- [Platform-Specific Examples](#platform-specific-examples)
- [Android](#android)
- [Setup](#setup)
- [Build & Run](#build--run)
- [Old phones](#old-phones)
- [iOS](#ios)
- [Setup](#setup-1)
- [Build & Run](#build--run-1)
- [WASM](#wasm)
- [Setup](#setup-2)
- [Build & Run](#build--run-2)

# The Bare Minimum

Expand Down Expand Up @@ -145,6 +154,7 @@ Example | File | Description
`fixed_timestep` | [`ecs/fixed_timestep.rs`](./ecs/fixed_timestep.rs) | Shows how to create systems that run every fixed timestep, rather than every tick
`hierarchy` | [`ecs/hierarchy.rs`](./ecs/hierarchy.rs) | Creates a hierarchy of parents and children entities
`parallel_query` | [`ecs/parallel_query.rs`](./ecs/parallel_query.rs) | Illustrates parallel queries with `ParallelIterator`
`query_bundle` | [`ecs/query_bundle.rs`](./ecs/query_bundle.rs) | Shows how to query entities that contain components in a `Bundle`
`removal_detection` | [`ecs/removal_detection.rs`](./ecs/removal_detection.rs) | Query for entities that had a specific component removed in a previous stage during the current frame.
`startup_system` | [`ecs/startup_system.rs`](./ecs/startup_system.rs) | Demonstrates a startup system (one that runs once when the app starts up)
`state` | [`ecs/state.rs`](./ecs/state.rs) | Illustrates how to use States to control transitioning from a Menu state to an InGame state
Expand Down
50 changes: 50 additions & 0 deletions examples/ecs/query_bundle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use bevy::{log::LogPlugin, prelude::*};

fn main() {
App::build()
.add_plugin(LogPlugin)
.add_startup_system(setup.system())
.add_system(log_names.system().label(LogNamesSystem))
.add_system(log_person_bundles.system().after(LogNamesSystem))
.run();
}

#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)]
struct LogNamesSystem;

#[derive(Debug)]
struct Name(String);

#[derive(Debug)]
struct Age(usize);

#[derive(Debug, Bundle)]
struct PersonBundle {
name: Name,
age: Age,
}

/// Sets up two entities, one with a [Name] component as part of a bundle,
/// and one entity with [Name] only.
fn setup(mut commands: Commands) {
commands.spawn().insert(Name("Steve".to_string()));
commands.spawn().insert_bundle(PersonBundle {
name: Name("Bob".to_string()),
age: Age(40),
});
}

fn log_names(query: Query<&Name>) {
info!("Log all entities with `Name` component");
// this will necessarily have to print both components.
for name in query.iter() {
info!("{:?}", name);
}
}
fn log_person_bundles(query: Query<&Name, WithBundle<PersonBundle>>) {
info!("Log `Name` components from entities that have all components in `PersonBundle`.");
// this should only print `Name("Bob")`.
for name in query.iter() {
info!("{:?}", name);
}
}

0 comments on commit 0c2f17f

Please sign in to comment.