Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Merged by Bors] - Convenience method for entity naming #7186

Closed
wants to merge 7 commits into from

Conversation

Aceeri
Copy link
Member

@Aceeri Aceeri commented Jan 14, 2023

Objective

  • Trying to make it easier to have a more user friendly debugging name for when you want to print out an entity.

Solution

  • Add a new WorldQuery struct DebugName to format the Name if the entity has one, otherwise formats the Entity id.
    This means we can do this and get more descriptive errors without much more effort:
fn my_system(moving: Query<(DebugName, &mut Position, &Velocity)>) {
    for (name, mut position, velocity) in &mut moving {
        position += velocity; 
        if position.is_nan() {
            error!("{:?} has an invalid position state", name);
        }
    }
}

Changelog

  • Added DebugName world query for more human friendly debug names of entities.

Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that only working on exactly Query<&'w Name> types is too limiting: generally I want to combine this with other filters.

First question is would this make more sense to make a method on Name itself, or on Option<Name>? Unfortunately won't work because you don't have access to the entity information...

What about a custom WorldQuery type (just use the derive macro) that you can stick in your queries then?

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Usability A simple quality-of-life change that makes Bevy easier to use labels Jan 14, 2023
@Aceeri
Copy link
Member Author

Aceeri commented Jan 15, 2023

I think that only working on exactly Query<&'w Name> types is too limiting: generally I want to combine this with other filters.

I feel like it doesn't make a bunch of sense since I feel like it'd be more misleading for an entity to have a Name but having it only return the Entity because it didn't meet the criteria. Unless I'm completely misunderstanding, I mostly just don't really see myself having a usecase for Query<&Name, With<Transform>> or similar.

What about a custom WorldQuery type (just use the derive macro) that you can stick in your queries then?

I'm a bit confused by this, do you mean something like this?

#[derive(WorldQuery)]
struct DebugInfo {
    names: Query<&Name>,
    transforms: Query<&Transform>,
}

impl DebugInfo {
    pub fn fmt(&self, entity: Entity) -> Box<dyn Debug> {
        if let Some(name) = self.names.get(entity) { return Box::new(name.as_str()); }
        if let Some(transform) = self.transforms.get(entity) { ... }
        Box::new(entity)
    }
}

@alice-i-cecile
Copy link
Member

alice-i-cecile commented Jan 15, 2023

I meant something like:

#[derive(WorldQuery)
pub struct EntityDebugInfo {
   name: Option<&Name>,
   entity: Entity,
}

pub enum EntityIdentifier {
   Named(String),
   Nameless(Entity),
}

// This struct is autogenerated as a query item with the WorldQuery derive macro
impl EntityDebugInfoItem {
   fn identifier(&self) -> EntityIdentifier {
      match self.name {
         Some(name) => EntityIdentifier::Name(name),
         None => EntityIdentifier::Nameless(self.entity),
      }
   }
}

This would allow you to toss this into a Query<EntityDebugInfo, With<Physics>> nicely. Or when you don't care, just Query<EntityDebugInfo>.

@Aceeri
Copy link
Member Author

Aceeri commented Jan 15, 2023

Ah I see, ya I agree fully actually, that way we can even just impl Debug and it'd be just error!("entity {:?} is messed up", entity_debug)

@Aceeri
Copy link
Member Author

Aceeri commented Jan 18, 2023

@alice-i-cecile Should be more in that vein now, also simplified the code a good bit.

#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self.name {
Some(name) => std::fmt::Debug::fmt(&name, f),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe it would be worth printing out the self.entity too since Name isnt required to be a unique identifier

Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That shaped up very nicely! Can we add a tiny doc test to demonstrate usage before we merge?

@@ -76,6 +78,25 @@ impl std::fmt::Display for Name {
}
}

/// Convenient query for giving a human friendly name to an entity.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a no_run doc test here to demonstrate how this is used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually helped me catch that I implemented Debug on DebugName instead of DebugNameItem, should we keep it no_run?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah, it's fine to let it run.

Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bors r+

bors bot pushed a commit that referenced this pull request Jan 30, 2023
# Objective
- Trying to make it easier to have a more user friendly debugging name for when you want to print out an entity.

## Solution
- Add a new `WorldQuery` struct `DebugName` to format the `Name` if the entity has one, otherwise formats the `Entity` id.
This means we can do this and get more descriptive errors without much more effort:
```rust
fn my_system(moving: Query<(DebugName, &mut Position, &Velocity)>) {
    for (name, mut position, velocity) in &mut moving {
        position += velocity; 
        if position.is_nan() {
            error!("{:?} has an invalid position state", name);
        }
    }
}
```

---

## Changelog
- Added `DebugName` world query for more human friendly debug names of entities.
@bors bors bot changed the title Convenience method for entity naming [Merged by Bors] - Convenience method for entity naming Jan 30, 2023
@bors bors bot closed this Jan 30, 2023
ItsDoot pushed a commit to ItsDoot/bevy that referenced this pull request Feb 1, 2023
# Objective
- Trying to make it easier to have a more user friendly debugging name for when you want to print out an entity.

## Solution
- Add a new `WorldQuery` struct `DebugName` to format the `Name` if the entity has one, otherwise formats the `Entity` id.
This means we can do this and get more descriptive errors without much more effort:
```rust
fn my_system(moving: Query<(DebugName, &mut Position, &Velocity)>) {
    for (name, mut position, velocity) in &mut moving {
        position += velocity; 
        if position.is_nan() {
            error!("{:?} has an invalid position state", name);
        }
    }
}
```

---

## Changelog
- Added `DebugName` world query for more human friendly debug names of entities.
cart added a commit that referenced this pull request Apr 26, 2023
# Objective
This is just an oversight on my part when I implemented this in
#7186, there isn't much reason to
print out the hash of a `Name` like it does currently:
```
Name { hash: 1608798714325729304, name: "Suzanne" } (7v0)
```

## Solution
Instead it would be better if we just printed out the string like so:
```
"Suzanne" (7v0)
```

As it conveys all of the information in a less cluttered and immediately
intuitive way which was the original purpose of `DebugName`. Which I
also think translates to `Name` as well since I mostly see it as a thin
wrapper around a string.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Usability A simple quality-of-life change that makes Bevy easier to use
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants