A "domain specific language" designed to make building UIs in Bevy more pleasant. This DSL uses the same ingredients that bevyui uses, so those already familiar with bevyui should have an easy time learning it.
```rust use bevyuidsl::*;
fn startup(mut commands: Commands, assets: Res
// Obligatory camera
commands.spawn(Camera2dBundle::default());
scale.scale = 2.0;
// Spawns ui and gathers entity ids
let mut hiya = None;
let mut howdy = None;
root(c_root, &assets, &mut commands, |p| { // Spawns the root NodeBundle. AssetServer gets propagated.
node((c_half, c_green), p, |p| { // Spawns the left pane as a NodeBundle.
text("This is the left pane!", c_text, c_pixel, p); // Spawns a TextBundle.
text("Do you like it?", c_text, c_pixel, p);
text_button("Hiya", c_button_left, c_pixel, p).set(&mut hiya); // Spawns a ButtonBundle with a TextBundle child in the middle. Convenience widget.
grid(6, 6, c_grid, p, |p, _row, _col| { // Spawns a NodeBundle container with a NodeBundle for each cell (6x6).
image(c_inv_slot, p);
});
text("Le grid", c_text, c_pixel, p);
});
node((c_half, c_blue), p, |p| {
text("This is the right pane!", c_text, c_pixel, p);
text("Indeed, I do!", c_text, c_pixel, p);
text_button("Howdy", c_button_right, c_pixel, p).set(&mut howdy);
});
});
// Inserts marker components into the gathered entities.
// Useful when you need to interact with specific entities in the UI
commands
.entity(hiya.unwrap())
.insert(UiId::HiyaButton);
commands
.entity(howdy.unwrap())
.insert(UiId::HowdyButton);
}
```
This system spawns a UI using widgets like root, node, text, text_button, etc. You can even create your own widgets! They're just functions!
In this example, root is a function that takes a class called croot. The croot function just manipulates a NodeBundle, which is NodeBundle::default() by default. Ultimately, the NodeBundle in question gets spawned.
Like root, node also takes in a class (or a tuple of classes) and spawns a NodeBundle. When a tuple of classes is supplied, the callback functions are applied in order of left to right.
```rust fn c_root(b: &mut NodeBundle) { b.style.size = Size::new(Val::Percent(100.), Val::Percent(100.)); }
fn chalf(b: &mut NodeBundle) { let s = &mut b.style; s.size = Size::new(Val::Percent(50.), Val::Percent(100.)); s.flexdirection = FlexDirection::Column; s.justifycontent = JustifyContent::Center; s.alignitems = AlignItems::Center; s.padding = UiRect::all(Val::Px(10.)); }
fn cgreen(b: &mut NodeBundle) { b.backgroundcolor = Color::rgb_u8(125, 212, 148).into(); }
fn cblue(b: &mut NodeBundle) { b.backgroundcolor = Color::rgb_u8(125, 164, 212).into(); }
fn ctext(a: &AssetServer, b: &mut TextBundle) { b.style.margin = UiRect::all(Val::Px(10.)); }
fn cbuttonleft(assets: &AssetServer, b: &mut ButtonBundle) { let s = &mut b.style; s.size = Size::new(Val::Px(64.), Val::Px(24.)); s.justifycontent = JustifyContent::Center; s.alignitems = AlignItems::Center; b.backgroundcolor = Color::rgbu8(66, 135, 245).into(); b.image = assets.load("button.png").into(); }
fn cbuttonright(assets: &AssetServer, b: &mut ButtonBundle) { let s = &mut b.style; s.size = Size::new(Val::Px(64.), Val::Px(24.)); s.justifycontent = JustifyContent::Center; s.alignitems = AlignItems::Center; b.backgroundcolor = Color::rgbu8(57, 179, 118).into(); b.image = assets.load("button.png").into(); }
fn c_grid(b: &mut NodeBundle) { b.style.size = Size::new(Val::Px(200.), Val::Px(200.)); b.style.margin = UiRect::all(Val::Px(10.)); }
fn cinvslot(assets: &AssetServer, b: &mut ImageBundle) { b.style.size = Size::new(Val::Px(32.), Val::Px(32.)); b.image = assets.load("item_slot.png").into(); }
fn cpixel(assets: &AssetServer, s: &mut TextStyle) { s.font = assets.load("prstartk.ttf").into(); s.fontsize = 8.; s.color = Color::WHITE.into(); } ```
Some classes only depend a single bundle. Others depend on an AssetServer to manipulate their respective types.
It is recommended that you only set the fields you wish to overwrite in your classes. Be careful, for instance, of using ..default()
as this will overwrite even the fields you don't specify. This is very bad when combining classes using the tuple syntax.
To make creating classes a little less verbose, there is an optional module you can import called classhelpers. This module is made available by enabling the feature flag classhelpers in your Cargo.toml file. It includes various helper functions and constants to make your life easier. It is recommended that you put your class functions in their own module when using these helpers to avoid namespace pollution with the rest of your UI code.
```rust use bevyuidsl::; use bevy_ui_dsl::class_helpers::;
fn cnode(b: &mut NodeBundle) { let s = &mut b.style; s.size = size(pc(50), pc(50)); s.flexdirection = COLUMN; s.justifycontent = JUSTIFYCENTER; s.alignitems = ALIGNCENTER; s.padding = all(px(10)); } ```
Creating a widget is just a matter of creating a function that follows a certain convention. No more, no less. It will usually require a Classrust
/// Spawns a [
NodeBundle`] with children.
pub fn node(
class: impl Class
```
| bevy | bevy-ui-dsl | | ---- | ----------- | | 0.9 | 0.1 - 0.2 |