Famiq - Getting start
Famiq is a UI library built on top of Bevy UI by providing default widgets and a simple way to manage styles. Instead of writing Rust code for styling, developers can define styles in a well known JSON file. These styles are then parsed into Bevy's native UI styles, significantly reducing boilerplate code. You can read introduction to Famiq here. Today we will create a simple UI app (Counter) in bevy engine using Famiq. The Final result will look like this Create project in your terminal, create new rust project using cargo cargo new counter navigate into counter directory, and install famiq cargo add famiq This will install the latest version of famiq which is v0.2.5. Noted that famiq supports only bevy 0.15.x onward. open the project in your favorite code editor and get ready to write some code! Coding time open main.rs inside src/ directory, paste code below into it use bevy::prelude::*; use famiq::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugins(FamiqPlugin) // required by Famiq .add_systems(Startup, setup) .run(); } fn setup() {} This is what we need to get started in every bevy project. Write setup system to spawn widgets // use this component to keep track of counter number #[derive(Component)] struct Count(i32); fn setup( mut commands: Commands, asset_server: ResMut, // required by Famiq mut famiq_res: ResMut, // required by Famiq ) { // spawn new 2d camera commands.spawn(Camera2d::default()); // create a widget builder with hot-reload feature on let mut builder = FamiqWidgetBuilder::new(&mut commands, &mut famiq_res, &asset_server) .hot_reload(); // Text widget let count_text = fa_text(&mut builder, "0").id("#count-text").build(); builder.insert_component(count_text, Count(0)); // Button widget let button = fa_button(&mut builder, "Press me").id("#button").build(); // Container widget fa_container(&mut builder) .id("#container") .children([count_text, button]) .build(); } What is FamiqWidgetBuilder? In simple terms, FamiqWidgetBuilder is the root UI node that acts as a starting point for building and managing widgets. All widgets are created and structured on top of this root. .hot_reload() is used to enable hot-reload feature. When we make changes to JSON file (style) it will reflect the running app without needing to re-compile. If you run the app cargo run, without any styles, you will see Give our widgets some styles inside root directory, create a folder called assets. Inside assets folder, create a file called styles.json. open styles.json, paste below code into it. { "#container": { "justify_content": "center", "align_items": "center", "width": "300px", "margin": "auto auto auto auto", "background_color": "grey", "padding": "35px 35px 25px 25px", "border": "2px 2px 2px 2px", "border_radius": "10px 10px 10px 10px" }, "#button": { "margin_top": "20px" }, "#count-text": { "font_size": "40", "color": "blue" } } now run the app again, you will see a better UI. By default, famiq will look for json file at assets/styles.json. If you want to use different file name or path, you can call method use_style_path(). let mut builder = FamiqWidgetBuilder::new(&mut commands, &mut famiq_res, &asset_server) .use_style_path("assets/some_name.json") .hot_reload(); Increase counter on button press in order to handle button press, you will to create a new system that run in Update schedule. fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugins(FamiqPlugin) .add_systems(Startup, setup) .add_systems(Update, handle_button_press) // add this .run(); } fn handle_button_press( mut events: EventReader, mut text_res: ResMut, mut count_query: Query ) { for e in events.read() { if e.is_button_pressed() { let mut count = count_query.get_single_mut().unwrap(); count.0 += 1; text_res.update_value_by_id("#count-text", &count.0.to_string()); } } } we need FaInteractionEvent to get the button press event. we need FaTextResource to get or update text widget's value. Now run the app again, you will be able to increase the counter! This post is just about getting start using famiq. For more info, please go to the documentation. Famiq's github: https://github.com/MuongKimhong/famiq Famiq's docs: https://muongkimhong.github.io/famiq/ Famiq's crate: https://crates.io/crates/famiq
![Famiq - Getting start](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftu1ylf73v6w3wpwu5rqr.png)
Famiq is a UI library built on top of Bevy UI by providing default widgets and a simple way to manage styles.
Instead of writing Rust code for styling, developers can define styles in a well known JSON file. These styles are then parsed into Bevy's native UI styles, significantly reducing boilerplate code.
You can read introduction to Famiq here.
Today we will create a simple UI app (Counter) in bevy engine using Famiq.
The Final result will look like this
Create project
- in your terminal, create new rust project using cargo
cargo new counter
- navigate into
counter
directory, and installfamiq
cargo add famiq
This will install the latest version of famiq which is v0.2.5
. Noted that famiq
supports only bevy 0.15.x onward.
- open the project in your favorite code editor and get ready to write some code!
Coding time
- open
main.rs
insidesrc/
directory, paste code below into it
use bevy::prelude::*;
use famiq::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(FamiqPlugin) // required by Famiq
.add_systems(Startup, setup)
.run();
}
fn setup() {}
This is what we need to get started in every bevy project.
- Write setup system to spawn widgets
// use this component to keep track of counter number
#[derive(Component)]
struct Count(i32);
fn setup(
mut commands: Commands,
asset_server: ResMut<AssetServer>, // required by Famiq
mut famiq_res: ResMut<FamiqWidgetResource>, // required by Famiq
) {
// spawn new 2d camera
commands.spawn(Camera2d::default());
// create a widget builder with hot-reload feature on
let mut builder = FamiqWidgetBuilder::new(&mut commands, &mut famiq_res, &asset_server)
.hot_reload();
// Text widget
let count_text = fa_text(&mut builder, "0").id("#count-text").build();
builder.insert_component(count_text, Count(0));
// Button widget
let button = fa_button(&mut builder, "Press me").id("#button").build();
// Container widget
fa_container(&mut builder)
.id("#container")
.children([count_text, button])
.build();
}
What is FamiqWidgetBuilder
?
In simple terms, FamiqWidgetBuilder is the root UI node that acts as a starting point for building and managing widgets. All widgets are created and structured on top of this root.
.hot_reload()
is used to enable hot-reload feature. When we make changes to JSON file (style) it will reflect the running app without needing to re-compile.
If you run the app cargo run
, without any styles, you will see
Give our widgets some styles
- inside root directory, create a folder called
assets
. Insideassets
folder, create a file calledstyles.json
. - open
styles.json
, paste below code into it.
{
"#container": {
"justify_content": "center",
"align_items": "center",
"width": "300px",
"margin": "auto auto auto auto",
"background_color": "grey",
"padding": "35px 35px 25px 25px",
"border": "2px 2px 2px 2px",
"border_radius": "10px 10px 10px 10px"
},
"#button": {
"margin_top": "20px"
},
"#count-text": {
"font_size": "40",
"color": "blue"
}
}
now run the app again, you will see a better UI.
By default, famiq
will look for json file at assets/styles.json
. If you want to use different file name or path, you can call method use_style_path()
.
let mut builder = FamiqWidgetBuilder::new(&mut commands, &mut famiq_res, &asset_server)
.use_style_path("assets/some_name.json")
.hot_reload();
Increase counter on button press
- in order to handle button press, you will to create a new system that run in
Update
schedule.
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(FamiqPlugin)
.add_systems(Startup, setup)
.add_systems(Update, handle_button_press) // add this
.run();
}
fn handle_button_press(
mut events: EventReader<FaInteractionEvent>,
mut text_res: ResMut<FaTextResource>,
mut count_query: Query<&mut Count>
) {
for e in events.read() {
if e.is_button_pressed() {
let mut count = count_query.get_single_mut().unwrap();
count.0 += 1;
text_res.update_value_by_id("#count-text", &count.0.to_string());
}
}
}
- we need
FaInteractionEvent
to get the button press event. - we need
FaTextResource
to get or update text widget's value.
Now run the app again, you will be able to increase the counter!
This post is just about getting start using famiq
. For more info, please go to the documentation.
Famiq's github: https://github.com/MuongKimhong/famiq
Famiq's docs: https://muongkimhong.github.io/famiq/
Famiq's crate: https://crates.io/crates/famiq