bevy_lunex
bevy_lunex copied to clipboard
DSL thoughts
I have been thinking a bit about a DSL syntax for bevy_lunex. This syntax could easily be translated to pure-rust without too much additional verbosity, but I wanted to see if I could figure out a nice DSL.
Here is an example:
#[derive(LnxStyle)]
struct PlainTextStyle
{
font : &'static str,
font_size : usize,
color : Color,
}
/// Deriving `LnxParams` transforms the text fields into lnx 'param methods' (see the example).
#[derive(LnxParams, Default)]
struct PlainTextParams
{
justify: Justification,
width: Option<f32>,
height: Option<f32>,
depth: f32,
}
impl Into<TextParams> for PlainTextParams
{
fn into(self) -> TextParams
{
let params = match self.justify
{
Justification::Center => TextParams::center(),
_ => unimplemented!()
}
params.set_width(self.width);
params.set_height(self.height);
params.depth(depth);
}
}
#[lnx_prefab]
fn plain_text(lnx: &mut LnxContext, text: &str, params: PlainTextParams)
{
let style = lnx.get_style::<PlainTextStyle>().unwrap();
let text_style = TextStyle {
font : lnx.asset_server().load(style.font),
font_size : style.font_size,
color : style.color,
};
let text_params: TextParams = params
.into()
.with_style(&text_style);
lnx.commands().spawn(TextElementBundle::new(lnx.widget().clone(), text_params, text));
}
#[LnxStyleBundle]
struct BaseStyle
{
plain: PlainTextStyle,
}
impl Default for BaseStyle
{
//define the style
}
#[LnxStyleBundle]
struct DisplayStyle
{
plain: PlainTextStyle,
}
impl Default for PlainTextStyle
{
//define the style
}
let ui =
lnx!{
// import rust bindings or lnx scripts
use ui::prefabs::{plain_text, PlainTextParams};
use ui::prefabs::text_params::Center;
// registers style handles that can be referenced in the widget tree
// - style bundles are default-initialize, unpacked, and stored in Arcs; copies are minimized in the widget tree
styles[
base_style: BaseStyle
display_style: DisplayStyle
]
// [r] creates a relative widget and implicitly sets it in the lnx context widget stack
// - when entering a {} block, a new empty widget stack entry is added, then popped when leaving the block
// - when a new widget is created within a block, the previous entry in the stack is over-written (but the other widget
// handle remains valid until leaving the block where it is created)
[r] root: rx(0, 100) ry(0, 100)
{
// sets the current style in the lnx context style stack
// - all previous styles in the stack will be hidden
[style] set(base_style)
// this nameless widget is implicitly a child of `root`
[r] _: rx(20, 80), ry(42.5, 57.5)
{
// layers `display_style` on top of the previous style in the style stack
// - the parent style will be used whenever the child style cannot satisfy a prefab's requirements
[style] add(display_style)
// style and parent widget are implicitly passed to the prefab
// - we use 'param methods' to define parameters in the prefab
// - if there is a param method name conflict, you must resolve the conflict with the names of the
// target structs
[inject] plain_text("Hello, World!", justify(Center), height(100), PlainTextParams::width(100))
}
}
}