Skip to content

Commit a795de3

Browse files
authored
Use impl Into<A> for Assets::add (bevyengine#10878)
# 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: ```rust 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`. ```rust 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()`: ```rust 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: ```rust 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: ```rust 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`: ```rust // 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.
1 parent 54a943d commit a795de3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+247
-268
lines changed

crates/bevy_asset/src/assets.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,9 @@ impl<A: Asset> Assets<A> {
361361

362362
/// Adds the given `asset` and allocates a new strong [`Handle`] for it.
363363
#[inline]
364-
pub fn add(&mut self, asset: A) -> Handle<A> {
364+
pub fn add(&mut self, asset: impl Into<A>) -> Handle<A> {
365365
let index = self.dense_storage.allocator.reserve();
366-
self.insert_with_index(index, asset).unwrap();
366+
self.insert_with_index(index, asset.into()).unwrap();
367367
Handle::Strong(
368368
self.handle_provider
369369
.get_handle(index.into(), false, None, None),

errors/B0004.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ fn setup_cube(
3333
.with_children(|parent| {
3434
// cube
3535
parent.spawn(PbrBundle {
36-
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
37-
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
36+
mesh: meshes.add(shape::Cube { size: 1.0 }),
37+
material: materials.add(Color::rgb(0.8, 0.7, 0.6)),
3838
transform: Transform::from_xyz(0.0, 0.5, 0.0),
3939
..default()
4040
});
@@ -80,8 +80,8 @@ fn setup_cube(
8080
.with_children(|parent| {
8181
// cube
8282
parent.spawn(PbrBundle {
83-
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
84-
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
83+
mesh: meshes.add(shape::Cube { size: 1.0 }),
84+
material: materials.add(Color::rgb(0.8, 0.7, 0.6)),
8585
transform: Transform::from_xyz(0.0, 0.5, 0.0),
8686
..default()
8787
});

examples/2d/2d_shapes.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn setup(
1818

1919
// Circle
2020
commands.spawn(MaterialMesh2dBundle {
21-
mesh: meshes.add(shape::Circle::new(50.).into()).into(),
21+
mesh: meshes.add(shape::Circle::new(50.)).into(),
2222
material: materials.add(ColorMaterial::from(Color::PURPLE)),
2323
transform: Transform::from_translation(Vec3::new(-150., 0., 0.)),
2424
..default()
@@ -37,17 +37,15 @@ fn setup(
3737

3838
// Quad
3939
commands.spawn(MaterialMesh2dBundle {
40-
mesh: meshes
41-
.add(shape::Quad::new(Vec2::new(50., 100.)).into())
42-
.into(),
40+
mesh: meshes.add(shape::Quad::new(Vec2::new(50., 100.))).into(),
4341
material: materials.add(ColorMaterial::from(Color::LIME_GREEN)),
4442
transform: Transform::from_translation(Vec3::new(50., 0., 0.)),
4543
..default()
4644
});
4745

4846
// Hexagon
4947
commands.spawn(MaterialMesh2dBundle {
50-
mesh: meshes.add(shape::RegularPolygon::new(50., 6).into()).into(),
48+
mesh: meshes.add(shape::RegularPolygon::new(50., 6)).into(),
5149
material: materials.add(ColorMaterial::from(Color::TURQUOISE)),
5250
transform: Transform::from_translation(Vec3::new(150., 0., 0.)),
5351
..default()

examples/2d/bloom_2d.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fn setup(
4848

4949
// Circle mesh
5050
commands.spawn(MaterialMesh2dBundle {
51-
mesh: meshes.add(shape::Circle::new(100.).into()).into(),
51+
mesh: meshes.add(shape::Circle::new(100.)).into(),
5252
// 4. Put something bright in a dark environment to see the effect
5353
material: materials.add(ColorMaterial::from(Color::rgb(7.5, 0.0, 7.5))),
5454
transform: Transform::from_translation(Vec3::new(-200., 0., 0.)),
@@ -57,9 +57,7 @@ fn setup(
5757

5858
// Hexagon mesh
5959
commands.spawn(MaterialMesh2dBundle {
60-
mesh: meshes
61-
.add(shape::RegularPolygon::new(100., 6).into())
62-
.into(),
60+
mesh: meshes.add(shape::RegularPolygon::new(100., 6)).into(),
6361
// 4. Put something bright in a dark environment to see the effect
6462
material: materials.add(ColorMaterial::from(Color::rgb(6.25, 9.4, 9.1))),
6563
transform: Transform::from_translation(Vec3::new(200., 0., 0.)),

examples/2d/mesh2d.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn setup(
1818
) {
1919
commands.spawn(Camera2dBundle::default());
2020
commands.spawn(MaterialMesh2dBundle {
21-
mesh: meshes.add(Mesh::from(shape::Quad::default())).into(),
21+
mesh: meshes.add(shape::Quad::default()).into(),
2222
transform: Transform::default().with_scale(Vec3::splat(128.)),
2323
material: materials.add(ColorMaterial::from(Color::PURPLE)),
2424
..default()

examples/3d/3d_gizmos.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ fn setup(
2323
});
2424
// plane
2525
commands.spawn(PbrBundle {
26-
mesh: meshes.add(Mesh::from(shape::Plane::from_size(5.0))),
27-
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
26+
mesh: meshes.add(shape::Plane::from_size(5.0)),
27+
material: materials.add(Color::rgb(0.3, 0.5, 0.3)),
2828
..default()
2929
});
3030
// cube
3131
commands.spawn(PbrBundle {
32-
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
33-
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
32+
mesh: meshes.add(shape::Cube { size: 1.0 }),
33+
material: materials.add(Color::rgb(0.8, 0.7, 0.6)),
3434
transform: Transform::from_xyz(0.0, 0.5, 0.0),
3535
..default()
3636
});

examples/3d/3d_scene.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ fn setup(
1717
) {
1818
// circular base
1919
commands.spawn(PbrBundle {
20-
mesh: meshes.add(shape::Circle::new(4.0).into()),
21-
material: materials.add(Color::WHITE.into()),
20+
mesh: meshes.add(shape::Circle::new(4.0)),
21+
material: materials.add(Color::WHITE),
2222
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
2323
..default()
2424
});
2525
// cube
2626
commands.spawn(PbrBundle {
27-
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
28-
material: materials.add(Color::rgb_u8(124, 144, 255).into()),
27+
mesh: meshes.add(shape::Cube { size: 1.0 }),
28+
material: materials.add(Color::rgb_u8(124, 144, 255)),
2929
transform: Transform::from_xyz(0.0, 0.5, 0.0),
3030
..default()
3131
});

examples/3d/3d_shapes.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ fn setup(
3737
});
3838

3939
let shapes = [
40-
meshes.add(shape::Cube::default().into()),
41-
meshes.add(shape::Box::default().into()),
42-
meshes.add(shape::Capsule::default().into()),
43-
meshes.add(shape::Torus::default().into()),
44-
meshes.add(shape::Cylinder::default().into()),
45-
meshes.add(shape::Icosphere::default().try_into().unwrap()),
46-
meshes.add(shape::UVSphere::default().into()),
40+
meshes.add(shape::Cube::default()),
41+
meshes.add(shape::Box::default()),
42+
meshes.add(shape::Capsule::default()),
43+
meshes.add(shape::Torus::default()),
44+
meshes.add(shape::Cylinder::default()),
45+
meshes.add(Mesh::try_from(shape::Icosphere::default()).unwrap()),
46+
meshes.add(shape::UVSphere::default()),
4747
];
4848

4949
let num_shapes = shapes.len();
@@ -78,8 +78,8 @@ fn setup(
7878

7979
// ground plane
8080
commands.spawn(PbrBundle {
81-
mesh: meshes.add(shape::Plane::from_size(50.0).into()),
82-
material: materials.add(Color::SILVER.into()),
81+
mesh: meshes.add(shape::Plane::from_size(50.0)),
82+
material: materials.add(Color::SILVER),
8383
..default()
8484
});
8585

examples/3d/3d_viewport_to_world.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ fn setup(
5151
// plane
5252
commands.spawn((
5353
PbrBundle {
54-
mesh: meshes.add(shape::Plane::from_size(20.).into()),
55-
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
54+
mesh: meshes.add(shape::Plane::from_size(20.)),
55+
material: materials.add(Color::rgb(0.3, 0.5, 0.3)),
5656
..default()
5757
},
5858
Ground,

examples/3d/anti_aliasing.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,8 @@ fn setup(
260260
) {
261261
// Plane
262262
commands.spawn(PbrBundle {
263-
mesh: meshes.add(shape::Plane::from_size(50.0).into()),
264-
material: materials.add(Color::rgb(0.1, 0.2, 0.1).into()),
263+
mesh: meshes.add(shape::Plane::from_size(50.0)),
264+
material: materials.add(Color::rgb(0.1, 0.2, 0.1)),
265265
..default()
266266
});
267267

@@ -273,7 +273,7 @@ fn setup(
273273
// Cubes
274274
for i in 0..5 {
275275
commands.spawn(PbrBundle {
276-
mesh: meshes.add(Mesh::from(shape::Cube { size: 0.25 })),
276+
mesh: meshes.add(shape::Cube { size: 0.25 }),
277277
material: cube_material.clone(),
278278
transform: Transform::from_xyz(i as f32 * 0.25 - 1.0, 0.125, -i as f32 * 0.5),
279279
..default()

examples/3d/atmospheric_fog.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn setup_terrain_scene(
7979
// Sky
8080
commands.spawn((
8181
PbrBundle {
82-
mesh: meshes.add(Mesh::from(shape::Box::default())),
82+
mesh: meshes.add(shape::Box::default()),
8383
material: materials.add(StandardMaterial {
8484
base_color: Color::hex("888888").unwrap(),
8585
unlit: true,

examples/3d/blend_modes.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ fn setup(
146146
.id();
147147

148148
// Chessboard Plane
149-
let black_material = materials.add(Color::BLACK.into());
150-
let white_material = materials.add(Color::WHITE.into());
149+
let black_material = materials.add(Color::BLACK);
150+
let white_material = materials.add(Color::WHITE);
151151

152-
let plane_mesh = meshes.add(shape::Plane::from_size(2.0).into());
152+
let plane_mesh = meshes.add(shape::Plane::from_size(2.0));
153153

154154
for x in -3..4 {
155155
for z in -3..4 {

examples/3d/bloom_3d.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,10 @@ fn setup_scene(
5656
});
5757

5858
let mesh = meshes.add(
59-
shape::Icosphere {
59+
Mesh::try_from(shape::Icosphere {
6060
radius: 0.5,
6161
subdivisions: 5,
62-
}
63-
.try_into()
62+
})
6463
.unwrap(),
6564
);
6665

examples/3d/deferred_rendering.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,16 @@ fn setup(
103103

104104
// Plane
105105
commands.spawn(PbrBundle {
106-
mesh: meshes.add(shape::Plane::from_size(50.0).into()),
106+
mesh: meshes.add(shape::Plane::from_size(50.0)),
107107
material: forward_mat_h.clone(),
108108
..default()
109109
});
110110

111-
let cube_h = meshes.add(Mesh::from(shape::Cube { size: 0.1 }));
112-
let sphere_h = meshes.add(Mesh::from(shape::UVSphere {
111+
let cube_h = meshes.add(shape::Cube { size: 0.1 });
112+
let sphere_h = meshes.add(shape::UVSphere {
113113
radius: 0.125,
114114
..default()
115-
}));
115+
});
116116

117117
// Cubes
118118
commands.spawn(PbrBundle {
@@ -196,7 +196,7 @@ fn setup(
196196
// sky
197197
commands.spawn((
198198
PbrBundle {
199-
mesh: meshes.add(Mesh::from(shape::Box::default())),
199+
mesh: meshes.add(shape::Box::default()),
200200
material: materials.add(StandardMaterial {
201201
base_color: Color::hex("888888").unwrap(),
202202
unlit: true,

examples/3d/fog.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ fn setup_pyramid_scene(
5858
// pillars
5959
for (x, z) in &[(-1.5, -1.5), (1.5, -1.5), (1.5, 1.5), (-1.5, 1.5)] {
6060
commands.spawn(PbrBundle {
61-
mesh: meshes.add(Mesh::from(shape::Box {
61+
mesh: meshes.add(shape::Box {
6262
min_x: -0.5,
6363
max_x: 0.5,
6464
min_z: -0.5,
6565
max_z: 0.5,
6666
min_y: 0.0,
6767
max_y: 3.0,
68-
})),
68+
}),
6969
material: stone.clone(),
7070
transform: Transform::from_xyz(*x, 0.0, *z),
7171
..default()
@@ -97,14 +97,14 @@ fn setup_pyramid_scene(
9797
let size = i as f32 / 2.0 + 3.0;
9898
let y = -i as f32 / 2.0;
9999
commands.spawn(PbrBundle {
100-
mesh: meshes.add(Mesh::from(shape::Box {
100+
mesh: meshes.add(shape::Box {
101101
min_x: -size,
102102
max_x: size,
103103
min_z: -size,
104104
max_z: size,
105105
min_y: 0.0,
106106
max_y: 0.5,
107-
})),
107+
}),
108108
material: stone.clone(),
109109
transform: Transform::from_xyz(0.0, y, 0.0),
110110
..default()
@@ -113,7 +113,7 @@ fn setup_pyramid_scene(
113113

114114
// sky
115115
commands.spawn(PbrBundle {
116-
mesh: meshes.add(Mesh::from(shape::Box::default())),
116+
mesh: meshes.add(shape::Box::default()),
117117
material: materials.add(StandardMaterial {
118118
base_color: Color::hex("888888").unwrap(),
119119
unlit: true,

0 commit comments

Comments
 (0)