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

Add ChildBuilder::commands method #2448

Closed
wants to merge 1 commit into from

Conversation

Havvy
Copy link

@Havvy Havvy commented Jul 11, 2021

Objective

Access the Commands directly from within a with_children closure.

Solution

Add a .commands() method to ChildBuilder to access Commands directly.

This method lets us access `Commands` directly while in the
`with_children` method. This is useful if you're doing something
like inserting resources associated to one of the children entities.
@github-actions github-actions bot added the S-Needs-Triage This issue needs to be labelled label Jul 11, 2021
@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 and removed S-Needs-Triage This issue needs to be labelled labels Jul 11, 2021
@Ixentus
Copy link
Contributor

Ixentus commented Jul 11, 2021

parent.commands().insert_resource(ImportantLocation(entity)); I wonder what it means to insert a resource into a parent?

@NiklasEi
Copy link
Member

I agree with @Ixentus and imagine that this could be quite confusing. In the case of your documentation example, I think it would be clearer to remember the entity and insert the resource later on after spawning.
Do you have other use cases where you need command access inside the with_children closure?

@mockersf
Copy link
Member

mockersf commented Jul 11, 2021

While this doesn't expose anything that's not already possible through ChildBuilder::add_command, as mentioned above I think it isn't a good api to expose as it can bring errors in understanding.

I would prefer to have specialised functions on the ChildBuilder to issue the commands you want, with a clear name.

@Havvy
Copy link
Author

Havvy commented Jul 11, 2021

Would it help if the method name said it wasn't attached to the parent? Something like commands_unattached_to_parent or raw_commands? Another alternative is to make a method commands_without_parent(|commands| ...) but adding another layer of closures seemed pointless.

And yes, this doesn't formally add anything that ChildBuilder::add_command doesn't already do, so if you don't like this method, then that one should also be removed.

For my use case, I think storing the entity in a local to run after the fact breaks the locality of reading, making it harder to understand what the code is doing. The declared local, setting the local, and then actually inserting the resource with the local will all be in completely different locations. Like, they are multiple screens away.

@alice-i-cecile
Copy link
Member

And yes, this doesn't formally add anything that ChildBuilder::add_command doesn't already do, so if you don't like this method, then that one should also be removed.

There's something to be said for both "make the hard things hard" and "there should be only one way to do things". I think Ixentus raises an important point about the confusion this could induce.

In general I'm not thrilled with the level of mental hoops required to work with ChildBuilder. My preference is to deprecate it completely in favor of relations (#1627), but that's a long way off.

@Ixentus
Copy link
Contributor

Ixentus commented Jul 12, 2021

So if I understand correctly, you're adding Commands to the Childbuilder to use Commands inside it. However you can trivially do this by adding a second mut Commands to the system parameters:

fn setup_locations(mut commands: Commands, mut commandsb: Commands) {
    commands
        .spawn()
        .insert(Transform::from_xyz(1.0, 0.0, 0.0))
        .insert(GlobalTransform::default())
        .with_children(|parent| {
            let entity = parent
                .spawn()
                .insert(Transform::from_xyz(1.0, 0.0, 0.0))
                .insert(GlobalTransform::default())
                .id();

            commandsb.insert_resource(ImportantLocation(entity));
        });
}

I'm not sure this is even documented though, so this PR made sense :)

Comment on lines +93 to +94
/// Calling [`spawn`][Commands::spawn] or [`spawn_bundle`][Commands::spawn_bundle] on the
/// returned value will **not** insert the parent and children components.
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like a footgun waiting to happen...

Copy link
Author

Choose a reason for hiding this comment

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

It's a footgun on the already-present add_commands method.

@Havvy
Copy link
Author

Havvy commented Jul 14, 2021

I don't forsee this being approved, so I'm going to close it. Do note that the underlying motivation is still there, and that add_command still exists with the same footguns.

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.

7 participants