Implement easier pattern for `vello` graphics creation (quality of life improvement)
nixon-voxell opened this issue · 0 comments
The Problem
At the moment, creating a simple rect is extremely verbose:
fn xxx_system(mut commands: Commands, mut scenes: ResMut<Assets<VelloScene>>) {
//...
commands.spawn(VelloRectBundle {
rect: VelloRect::anchor_center(DVec2::new(100.0, 100.0), DVec4::splat(10.0)),
fill: FillStyle::from_brush(Color::WHITE),
stroke: StrokeStyle::from_brush(Color::WHITE).with_style(4.0),
scene_bundle: VelloSceneBundle {
scene: scenes.add(VelloScene::default()),
transform: Transform::from_xyz(-200.0, 0.0, 0.0),
..default()
},
});
//...
}
By default, all of the Component
s inside the Bundle
implements the Default
trait, this means that if the user is not interested in setting for example the color and transform of the rect, they can do something like this:
commands.spawn(VelloRectBundle {
rect: VelloRect::anchor_center(DVec2::new(100.0, 100.0), DVec4::splat(10.0)),
scene_bundle: VelloSceneBundle {
scene: scenes.add(VelloScene::default()),
..default()
},
..default()
});
Although it makes the code shorter, setting up simple graphics like a rect should be even more compact. Notice also that users will always need to add the scene_bundle
component manually as it contains an asset handle that needs to be created for the vello
renderer to pick up. Furthermore, users only have the choice to pick and choose which Component
inside the Bundle
to be left out. For example, in the VelloRect
component, users are required to choose the anchor style, define the size of the rect, and the radius of the rect. Wouldn't it be nice if users get to choose which one of those to be left out for default values?
Proposed Pattern
The builder pattern is what first come to my mind. The idea is to provide a good default value for places where it is not needed and allow for customization only where the user intends.
Here is a mock up on how it might look like:
create_rect(100.0, 100.0)
.radius(10.0)
.fill(Color::WHITE)
.build(&mut commands, &mut scenes);
As you can see, the user can now pick and choose individual values of the rect to be left out or customized. The final build function is then called to spawn the actual rect using commands
and scenes
. If the user is not interested in any customizations, they would only need to fill in the required data for a rect creation:
create_rect(100.0, 100.0).build(&mut commands, &mut scenes);
An even better API proposal might be to create trait functions for the Command
struct so that we can omit the &mut commands
input for the build function:
commands.create_rect(100.0, 100.0).build(&mut scenes);