jonmo জন্ম
in bengali, jonmo means "birth"
jonmo provides an ergonomic, functional, and declarative API for specifying Bevy system dependency graphs, where "output" handles to nodes of the graph are canonically referred to as "signals". Building upon these signals, jonmo offers a high level entity builder which enables one to declare reactive entities, components, and children using a familiar fluent syntax with semantics and API ported from the incredible FRP signals of futures-signals and its web UI dependents MoonZoon and Dominator.
The runtime of jonmo is quite simple; every frame, the outputs of systems are forwarded to their dependants, recursively. The complexity and power of jonmo really emerges from its monadic signal combinators, defined within the SignalExt, SignalVecExt, and SignalMapExt traits (ported from futures-signals' traits of the same name), which internally manage special Bevy systems that allow for the declarative composition of complex data flows with minimalistic, high-level, signals-oriented methods.
- fine-grained reactivity for all entities, components, and children
- diff-less constant-time reactive updates for collections (available through
MutableVecandMutableBTreeMap) - automated system lifecycle management when using the builder API, simple component on-remove hook when not
- polling API for when one needs an escape hatch from the regular push-based output semantics (polling is used sparsely internally for some combinators)
- either wrappers (a la https://github.com/rayon-rs/either) and type-erased signals (via boxing) for cheap and flexible management of distinct signal types from different branches of logic
no_stdcompatible
//! Simple counter example, ported from a similar example in haalka.
use bevy::prelude::*;
use jonmo::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, JonmoPlugin))
.add_systems(
Startup,
(
|world: &mut World| {
ui_root().spawn(world);
},
camera,
),
)
.run();
}
#[derive(Component, Clone, Deref, DerefMut)]
struct Counter(i32);
fn ui_root() -> JonmoBuilder {
let counter_holder = LazyEntity::new();
JonmoBuilder::from(Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
})
.child(
JonmoBuilder::from(Node {
flex_direction: FlexDirection::Row,
column_gap: Val::Px(15.0),
align_items: AlignItems::Center,
padding: UiRect::all(Val::Px(25.)),
..default()
})
.insert(Counter(0))
.entity_sync(counter_holder.clone())
.child(counter_button(counter_holder.clone(), PINK, "-", -1))
.child(
JonmoBuilder::from((Node::default(), TextFont::from_font_size(25.)))
.component_signal(
SignalBuilder::from_component_lazy(counter_holder.clone())
.map_in(|counter: Counter| *counter)
.dedupe()
.map_in_ref(ToString::to_string)
.map_in(Text)
.map_in(Some),
),
)
.child(counter_button(counter_holder, BLUE, "+", 1)),
)
}
fn counter_button(counter_holder: LazyEntity, color: Color, label: &'static str, step: i32) -> JonmoBuilder {
JonmoBuilder::from((
Node {
width: Val::Px(45.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
BorderRadius::MAX,
BackgroundColor(color),
))
.observe(move |on: On<Pointer<Click>>, mut counters: Query<&mut Counter>| {
if matches!(on.button, PointerButton::Primary) {
if let Ok(mut counter) = counters.get_mut(counter_holder.get()) {
**counter += step;
}
}
})
.child(JonmoBuilder::from((Text::from(label), TextFont::from_font_size(25.))))
}
fn camera(mut commands: Commands) {
commands.spawn(Camera2d);
}All examples are compiled to wasm for both webgl2 and webgpu (check compatibility) and deployed to github pages.
-
a simple increasing timer without using the entity builder, showcasing the least invasive way to start using jonmo signals in existing Bevy apps
-
basic_builder_injectwebgl2 webgpua simple increasing timer injecting the entity builder into an existing entity, showcasing a less invasive way to start using jonmo signals in existing Bevy apps.
-
a simple increasing timer using the entity builder, showcasing the recommended, idiomatic way to use jonmo signals
-
the example above, a simple counter
-
a reactive enumerated list of colors, each with an independent lifetime timer
-
key press counter with swappable save states, showcasing map reactivity
-
diverse filtering options for a list of items, showcasing vector reactivity
| bevy | jonmo |
|---|---|
| 0.17 | 0.4 |
| 0.16 | 0.3 |
| 0.15 | 0.1 |
All code in this repository is dual-licensed under either:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
