Cuicui Layout
A dumb layout algorithm you can rely on, built for and with bevy.
For some reasons, the Cyberpunk main menu has become the 7GUI of bevy, so here
is the Cyberpunk main menu using cuicui_layout_bevy_ui.
Code
use LayoutDsl as Dsl;
cmds.spawn;
let menu_buttons = ;
let title_card = serv.;
let font = serv.load;
let bg = serv.load;
let board = serv.load;
let button = serv.load;
dsl! ;
Running examples
Use the cargo run --bin command to list possible examples, and run them.
We do this because it allows us to have different dependencies between examples.
Stability
This crate is in expansion, use at your own risk, it is extremely likely that a lot of things are going to break a lot.
Using cuicui_layout
- Chose which crate you want to use:
- Interested in a ready-made UI library on top of
bevy_ui?cuicui_layout_bevy_uiis for you! - Want more flexibility? Using
cuicui_layouton top ofbevy_spritewill let you integrate your UI with a lot of 3rd party crates that only work with sprites!cuicui_layout_bevy_spriteis for you! - Using a custom renderer or want your UI to be part of the 3D environment?
Build on top of
cuicui_layoutitself then!
- Interested in a ready-made UI library on top of
- Add the chosen crate as a dependency to your crate.
cargo add cuicui_layout_bevy_ui - Use the
layout!macro to build a UI (text representation coming soon). - That's it! You are now using
cuicui_layout, congratulations! Make sure to check theLayoutTypedocs to learn the current capabilities ofcuicui_layout.
Please note that cuicui_layout won't magically make sprite components work in
UI nodes.
cuicui_layout crates
This repository contains several crates:
cuicui_dsl(dsl): Thedsl!macro andDslBundle.cuicui_layout(layout): The base algorithm and components, does not make any assumption about how it is used, beside the requirement that layout nodes be bevyEntitiyand usesbevy_hierarchy. Exports aLayoutDslto use with thedsl!macro.cuicui_layout_bevy_ui(ui): Integration withbevy_ui, including extension toUiDslforUiImage,Text, background images and background colors.cuicui_layout_bevy_sprite(sprite):bevy_spriteintegration, supportsMesh2dHandle,SpriteandText2d. This isn't as good as thebevy_ui-based integration when it comes to content-driven sizes, but otherwise should work very much like thebevy_uiintegration.
Cargo features
cuicui_layout_bevy_sprite/sprite_text(on by default): implement content-sized layout nodes forText2dBundle.cuicui_layout/reflect(on by default): Derivebevy_reflecttraits for cuicui_layout types & register them.
Why cuicui layout
- Friendly algo with less things to keep in your head and good defaults.[^1]
- Uses and takes full advantage of the bevy ECS.
- Only controls
PosRect, notTransform, you need to add a system that setsTransformbased onPosRect. - Fully flexible and extensible, can be used with
bevy_ui,bevy_sprite, your own stuff. - Fantatstically easy to extend, like really.
- Helpful and fully detailed error messages when things are incoherent or broken. As opposed to FlexBox, which goes "this is fine π₯πΆπ₯" and leaves you to guess why things do not turn out as expected.
[^1]: aspirational, currently not really the case.
Why not Flexbox
You are writing text to get 2d visual results on screen.
The translation from text to screen should be trivial, easy to do in your head.
Otherwise you need visual feedback to get what you want.
Bevy, even with hot reloading or bevy-inspector-egui
will always have extremely slow visual feedback.
Flexbox has too many parameters and depends on implicit properties of UI elements, it is not possible to emulate it in your head.
cuicui's layout, in contrast to Flexbox is easy to fit in your head. In fact, I will forecefully push cuicui's layout algorithm in your head in two short bullet points.
- A node can be a
Node::Containerand distribute its children along aDirectioneither by evenly spacing them (Distribution::FillParent) or putting them directly one after another (Distribution::Start). - A
Container's size can be expressed as a static value, a fraction of the size of what contains it, or a multiple of what it contains. - The content of a
Containercan beAlignmentto the start, end or center of its parent (by default it's centered).
That's it. There are some edge cases, but cuicui will yell at you
tell you nicely when you hit them and tell you how to handle them properly.
Flexbox FAQ
Q: Where is padding?
A: padding is equivalent to margin in cuicui_layout. margin and border
doesn't make conceptual sense.
Q: How do I center a node?
A: Add an empty node at the start and end of the container, and use fill_parent
Q: What is the equivalent of flex_direction?
A: use row and column
Q: What are the equivalents of column-reverse and row-reverse?
A: None. Use Alignment::End and swap your elements! Note that the *-reverse
flows in flexbox are very useful for internationalization. However,
when making a game, it is not enough to just swap the elements! Artistic control is
paramount and internationalization needs to be taken as a whole in the context of the UI.
Q: What is the equivalent of flex_wrap?
A: None, do you really need it?
Q: What is the equivalent of align_item, align_self, align_content, justify_content?
A: After 5 years of working with CSS, I still have no clue which one does what,
and whether they really do anything, so I wont' adventure an asnwer.
Q: What is the equivalent of flex_grow, flex_shrink, flex_basis, gap?
A: Do you even know what they do?
Q: Why can't child container overflow their parents? A: It's likely you didn't expect this, so we report it as an error.
Version matrix
| bevy | latest supporting version |
|---|---|
| 0.10 | 0.3.0 |
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT) at your option.
Contribution
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.