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

Use impl Into<A> for Assets::add #10878

Merged
merged 2 commits into from
Jan 8, 2024

Conversation

Jondolf
Copy link
Contributor

@Jondolf Jondolf commented Dec 5, 2023

Motivation

When spawning entities into a scene, it is very common to create assets like meshes and materials and to add them via asset handles. A common setup might look like this:

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    commands.spawn(PbrBundle {
        mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
        material: materials.add(StandardMaterial::from(Color::RED)),
        ..default()
    });
}

Let's take a closer look at the part that adds the assets using add.

mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(StandardMaterial::from(Color::RED)),

Here, "mesh" and "material" are both repeated three times. It's very explicit, but I find it to be a bit verbose. In addition to being more code to read and write, the extra characters can sometimes also lead to the code being formatted to span multiple lines even though the core task, adding e.g. a primitive mesh, is extremely simple.

A way to address this is by using .into():

mesh: meshes.add(shape::Cube { size: 1.0 }.into()),
material: materials.add(Color::RED.into()),

This is fine, but from the names and the type of meshes, we already know what the type should be. It's very clear that Cube should be turned into a Mesh because of the context it's used in. .into() is just seven characters, but it's so common that it quickly adds up and gets annoying.

It would be nice if you could skip all of the conversion and let Bevy handle it for you:

mesh: meshes.add(shape::Cube { size: 1.0 }),
material: materials.add(Color::RED),

Objective

Make adding assets more ergonomic by making Assets::add take an impl Into<A> instead of A.

Solution

Assets::add now takes an impl Into<A> instead of A, so e.g. this works:

    commands.spawn(PbrBundle {
        mesh: meshes.add(shape::Cube { size: 1.0 }),
        material: materials.add(Color::RED),
        ..default()
    });

I also changed all examples to use this API, which increases consistency as well because Mesh::from and into were being used arbitrarily even in the same file. This also gets rid of some lines of code because formatting is nicer.


Changelog

  • Assets::add now takes an impl Into<A> instead of A
  • Examples don't use T::from(K) or K.into() when adding assets

Migration Guide

Some into calls that worked previously might now be broken because of the new trait bounds. You need to either remove into or perform the conversion explicitly with from:

// Doesn't compile
let mesh_handle = meshes.add(shape::Cube { size: 1.0 }.into()),

// These compile
let mesh_handle = meshes.add(shape::Cube { size: 1.0 }),
let mesh_handle = meshes.add(Mesh::from(shape::Cube { size: 1.0 })),

Concerns

I believe the primary concerns might be:

  1. Is this too implicit?
  2. Does this increase codegen bloat?

Previously, the two APIs were using into or from, and now it's "nothing" or from. You could argue that into is slightly more explicit than "nothing" in cases like the earlier examples where a Color gets converted to e.g. a StandardMaterial, but I personally don't think into adds much value even in this case, and you could still see the actual type from the asset type.

As for codegen bloat, I doubt it adds that much, but I'm not very familiar with the details of codegen. I personally value the user-facing code reduction and ergonomics improvements that these changes would provide, but it might be worth checking the other effects in more detail.

Another slight concern is migration pain; apps might have a ton of into calls that would need to be removed, and it did take me a while to do so for Bevy itself (maybe around 20-40 minutes). However, I think the fact that there are so many into calls just highlights that the API could be made nicer, and I'd gladly migrate my own projects for it.

@Jondolf Jondolf added A-Assets Load files from disk to use for things like images, models, and sounds C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide labels Dec 5, 2023
@alice-i-cecile
Copy link
Member

As for codegen bloat, I doubt it adds that much, but I'm not very familiar with the details of codegen. I personally value the user-facing code reduction and ergonomics improvements that these changes would provide, but it might be worth checking the other effects in more detail.

I agree with this perspective. Nice change!

@alice-i-cecile alice-i-cecile added this to the 0.13 milestone Dec 9, 2023
Copy link
Contributor

@NthTensor NthTensor left a comment

Choose a reason for hiding this comment

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

I much prefer this API. Wonder if there are any other places we could use impl Into. Didn't review every single one of the examples in detail, but the CI says you are good.

@mockersf mockersf added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Jan 7, 2024
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Jan 8, 2024
Merged via the queue into bevyengine:main with commit a795de3 Jan 8, 2024
23 checks passed
github-merge-queue bot pushed a commit that referenced this pull request Jan 9, 2024
# Objective

A few of these were missed in #10878

## Solution

Fix em
@Jondolf Jondolf deleted the impl-into-for-asset-add branch January 9, 2024 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Assets Load files from disk to use for things like images, models, and sounds C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants