#ecs #bevy #proc

mevy_ecs_syntax

token handling for mevy_ecs!

15 releases

Uses new Rust 2024

new 0.2.3 Oct 27, 2025
0.2.2 Apr 25, 2025
0.1.11 Apr 7, 2025
0.1.9 Mar 10, 2025
0.1.3 Jan 15, 2025

#1766 in Game dev

30 downloads per month
Used in 2 crates (via mevy_ecs)

MIT/Apache

39KB
794 lines

A growing set of macros which add some witchcraft into bevy, currently available: 🪄

  • Simpler Entity spawning & modifying
  • Style Sheet Notation for bevy_ui components (and your own) - ui!(( width: 20px; ))
  • Simplified Notation for Color, Val and UiRect - code!{ let red = #ff0000; //..any code }

[!IMPORTANT] This crate is meant to provide macros only - no additional bevy plugins, resources, components or systems

Setup

Multiple bevy versions are supported and managed by features:

# bevy 0.16
mevy = {version="0.2",features=["0.16"]}

# bevy 0.15
mevy = {version="0.2",features=["0.15"]}

Then just use all of it:

use bevy::prelude::*;
use mevy::*;

Simpler Hierarchy Spawning

Spawn children just by stating [] - the 'names' are just variables containing their Entity

entity!{
    <world> // pass a mut World, Commands, ... variable
    SpecificChild(optional_child_name); // insert component
    .observe(..);                       // use method
    > Pointer<Click>{..};               // quick observe (e.g. 'on click')
    // component/bundle;
    // .method(..);
    [optional_child_name][
        // component;
        // .method(..);
    ]
}

Modify entities in a 'quick and dirty' way:

entity!{
    <world|#Component> // select every entity with this Component
    <Children.iter()>  // > select all children of those
    <Children.iter()>  // >> infinitely chain those selectors
    .despawn();        // despawn all of the last selected
}

CSS-like notation for bevy_ui

Using ui!((..)) (inner round braces) will return a tuple of mentioned components only.

c.spawn(ui!((
    size:          100px 100px;
    border:        5px #ff0000;
    box_shadow:    10% 10% 3px 8px #ffaa44;
    background:    #ffffff;
    border_radius: 6px;
    neat_outline;
)?));
//^ optional ? (or any token): hovering shows the returned tuple (if LSP used)

/// function as custom fields or p refabs
fn neat_outline() -> Outline {ui!((
    outline: 3px 1px #00ff00;
))}

Code Replacement Macro

Using the code!{} macro simplifies constructing:

  • Color by writing #rgb/#rgba/#rrggbb/#rrggbbaa
  • Val by writing 0px/0%/0vw/0vh/0vmin/0vmax/@(auto)
  • UiRect by writing [>0px]/[>0px 0px]/[>0px 0px 0px]/[>0px 0px 0px 0px] (css-like)

So you can do fun things like:

let shadow = code!{BoxShadow{
    // use #... is replaced with Color, meaning you can e.g. use methods 
    color: #FF1265.mix(&#F93ECA,0.4).with_alpha(0.2),
    x_offset: 100px,
    y_offset: 50%,
    spread_radius: 3.1vh,
    blur_radius: 40.23vmax,
}}};
let color = code!{#FF0000};
// or multiple things in the macro
code!{
    let color2 = #00FF00;
    let color3 = #6600AA;
}
println!{"{color2:?}"}

Design

Crates are separated into:

  • crate/*/syntax: token handling, meant to be reusable
  • crate/*: actual macros, based on that 'syntax'

[!NOTE] Only relevant if you dig deeper into this crate: The versions of those are not hard linked, since the macros can keep (or gain) features, even if the the syntax api has changed. So if one of those is 0.2.x and the other 0.5.x at some point, don't worry.

Dependencies

~0.8–1.3MB
~23K SLoC