Crate bevy_lunex

Crate bevy_lunex 

Source
Expand description

image

§

Blazingly fast retained layout engine for Bevy entities, built around vanilla Bevy ECS. It gives you the ability to make your own custom UI using regular ECS like every other part of your app.

  • Any aspect ratio: Lunex is designed to support ALL window sizes out of the box without deforming. The built in layout types react nicely and intuitively to aspect ratio changes.

  • Optimized: Unlike immediate mode GUI systems, Bevy_Lunex is a retained layout engine. This means the layout is calculated and stored, reducing the need for constant recalculations and offering potential performance benefits, especially for static or infrequently updated UIs.

  • ECS focused: Since it’s built with ECS, you can extend or customize the behavior of your UI by simply adding or modifying components. The interactivity is done by regular systems and events.

  • Worldspace UI: One of the features of Bevy_Lunex is its support for both 2D and 3D UI elements, leveraging Bevy’s Transform component. This opens up a wide range of possibilities for developers looking to integrate UI elements seamlessly into both flat and spatial environments. Diegetic UI is no problem.

§

image

Try out the live WASM demo on Itch.io (Limited performance & stutter due to running on a single thread). For best experience compile the project natively.

§Syntax Example

This is an example of a clickable Button created from scratch using provided components. Thanks to ECS, the syntax is highly modular with strong emphasis on components-per-functionality. As you can see, it is no different from vanilla Bevy ECS.

// Create UI
commands.spawn((
    // Initialize the UI root for 2D
    UiLayoutRoot::new_2d(),
    // Make the UI synchronized with camera viewport size
    UiFetchFromCamera::<0>,
)).with_children(|ui| {

    // Spawn a button in the middle of the screen
    ui.spawn((
        Name::new("My Button"),
        // Specify the position and size of the button
        UiLayout::window().pos(Rl((50.0, 50.0))).size((200.0, 50.0)).pack(),
        // When hovered, it will request the cursor icon to be changed
        OnHoverSetCursor::new(SystemCursorIcon::Pointer),
    )).with_children(|ui| {
        
        // Spawn a child node but with a background
        ui.spawn((
            // You can define layouts for multiple states
            UiLayout::new(vec![
                // The default state, just fill the parent
                (UiBase::id(), UiLayout::window().full()),
                // The hover state, grow to 105% of the parent from center
                (UiHover::id(), UiLayout::window().anchor(Anchor::Center).size(Rl(105.0)))
            ]),
            // Enable the hover state and give it some properties
            UiHover::new().forward_speed(20.0).backward_speed(4.0),
            // You can specify colors for multiple states
            UiColor::new(vec![
                (UiBase::id(), Color::BEVYPUNK_RED.with_alpha(0.15)),
                (UiHover::id(), Color::BEVYPUNK_YELLOW.with_alpha(1.2))
            ]),
            // You can attach any form of rendering to the node, be it sprite, mesh or something custom
            Sprite {
                image: asset_server.load("images/button.png"),
                // Here we enable sprite slicing
                image_mode: SpriteImageMode::Sliced(TextureSlicer { border: BorderRect::all(32.0), ..Default::default() }),
                ..Default::default()
            },
            // Make sure it does not cover the bounding zone of parent
            Pickable::IGNORE,
        )).with_children(|ui| {

            // Spawn a text child node
            ui.spawn((
                // For text we always use window layout to position it. The size is computed at runtime from text bounds
                UiLayout::window().pos((Rh(40.0), Rl(50.0))).anchor(Anchor::CenterLeft).pack(),
                UiColor::new(vec![
                    (UiBase::id(), Color::BEVYPUNK_RED),
                    (UiHover::id(), Color::BEVYPUNK_YELLOW.with_alpha(1.2))
                ]),
                UiHover::new().forward_speed(20.0).backward_speed(4.0),
                // Here we specify the text height proportional to the parent node
                UiTextSize::from(Rh(60.0)),
                // You can attach text like this
                Text2d::new("Click me!"),
                TextFont {
                    font: asset_server.load("fonts/semibold.ttf"),
                    font_size: 64.0,
                    ..Default::default()
                },
                // Make sure it does not cover the bounding zone of parent
                Pickable::IGNORE,
            ));
        });
    })
    // Utility observers that enable the hover state on trigger
    .observe(hover_set::<Pointer<Over>, true>)
    .observe(hover_set::<Pointer<Out>, false>)
    // Interactivity is done through observers, you can query anything here
    .observe(|_: Trigger<Pointer<Click>>| {
        println!("I was clicked!");
    });
});

§Documentation

§Contributing

Any contribution submitted by you will be dual licensed as mentioned below, without any additional terms or conditions. If you have the need to discuss this, please contact me.

§Licensing

Released under both APACHE and MIT licenses. Pick one that suits you the most!

Modules§

prelude

Structs§

Ab
Absolute - Represents non-changing unit. Scale can be modified but by default 1Ab = 1Px.
Align
Align - A type used to define alignment in a node layout.
CursorIconQueue
CursorPlugin
Dimension
Dimension - This component holds width and height used for different Ui components
Em
Size of M - Represents unit that is the size of the symbol M. Which is 16px with font size 16px and so on.
GamepadAttachedCursor
This component is used for SoftwareCursor-Gamepad relation.
GamepadCursor
This will make the SoftwareCursor controllable by a gamepad.
LunexGizmoGroup2d
Gizmo group for UI 2D node debug outlines
LunexGizmoGroup3d
Gizmo group for UI 3D node debug outlines
NoLunexPicking
This component disables the Lunex picking backend for this entity. Use this only if you want to use a different or custom picking bakckend. To disable picking entirely, use Pickable::IGNORE.
OnHoverSetCursor
Requests cursor icon on hover
RecomputeUiLayout
Trigger this event to recompute all UiLayoutRoot entities.
Rectangle2D
Rectangle 2D - Contains computed values from node layout.
Rh
Relative height - Represents scalable unit 0% to 100%. 120% is allowed. Proportional to a height measure even when used in a width field.
Rl
Relative - Represents scalable unit 0% to 100%. 120% is allowed.
Rw
Relative width - Represents scalable unit 0% to 100%. 120% is allowed. Proportional to a width measure even when used in a height field.
SoftwareCursor
Component for creating software mouse.
TextAnimator
This component modifies attached Text2d with a modified string outputted from a time dependant function.
UiBase
Ui Base - The default state for a Ui-Node, used only for the UiBase::id key. It is not a component that you can control.
UiClicked
WORK IN PROGRESS
UiColor
Ui Color - This component is used to control the color of the Ui-Node. It is synchronized with a state machine and allows for specifying unique colors for each state.
UiEmbedding
Ui Embedding - Use this component to mark entities whose texture handles are embeddings instead of regular assets. This means Lunex will resize the actual texture source when Dimension has changed.
UiFetchFromCamera
Ui Fetch From Camera - Attaching this component to UiLayoutRoot will make the Dimension component pull data from a Camera with attached UiSourceCamera that has the same index.
UiHover
Ui Hover - A built in state that should be triggered manually when a pointer hovers over a Ui-Node. This state first needs to be enabled for the entity by adding it as a component.
UiHoverSet
Event that enables the hover transition
UiImageSize
Ui Image Size - This component makes image size the authority instead.
UiIntro
WORK IN PROGRESS
UiLayout
Ui Layout - This component specifies the layout of a Ui-Node, which must be spawned as a child of either UiLayoutRoot or UiLayout to work. Based on the provided layout other attached components on this entity are overwritten to match the computed structure.
UiLayoutRoot
Ui Layout Root - This component marks the start of a worldspace Ui-Tree. Spawn this standalone for worldspace 3D UI or spawn this as a child of camera for a HUD. For 2D UI, if your camera does not move you can spawn it standalone too.
UiLayoutTypeBoundary
Boundary - Declarative layout type that is defined by its top-left corner and bottom-right corner.
UiLayoutTypeSolid
Solid - Declarative layout type that is defined by its width and height ratio.
UiLayoutTypeWindow
Window - Declarative layout type that is defined by its size and position.
UiLunexAnimPlugin
This plugin is used for the main logic.
UiLunexDebugPlugin
This plugin is used to enable debug functionality.
UiLunexIndexPlugin
This plugin is used to register index components.
UiLunexPickingPlugin
Adds picking support for Lunex.
UiLunexPlugin
This plugin is used for the main logic.
UiLunexPlugins
Plugin group adding all necessary plugins for Lunex
UiLunexStatePlugin
This plugin is used for the main logic.
UiMeshPlane2d
Ui Mesh Plane 2d - This component is used to mark mesh entities that can be freely replaced with quad mesh on demand.
UiMeshPlane3d
Ui Mesh Plane 3d - This component is used to mark mesh entities that can be freely replaced with quad mesh on demand.
UiOutro
WORK IN PROGRESS
UiRoot3d
Ui Root 3d - This is a marker component for all entities which fall under a 3D UI. You can check through this component if a specific node is 2D or 3D without looking for its root.
UiSelected
WORK IN PROGRESS
UiSourceCamera
Ui Source Camera - Marks a Camera as a source for UiLayoutRoot with UiFetchFromCamera. They must have the same index and only one UiSourceCamera can exist for a single index.
UiState
Ui State - This component aggrages state transition values for later reference by other components. You don’t directly control or spawn this component, but use an abstraction instead. You can use the prebuilt state components or create a custom ones with a completely unique transition logic. You just have to provide transition value to this component later.
UiTextSize
Ui Text Size - This component is used to control the size of a text compared to other Ui-Nodes. It works by overwritting the attached UiLayout window size parameter to match the text bounds. The value provided is used as a scale to adjust this size, specificaly it’s height. It is recommended to use non-relative units such as Ab, Rw, Rh, Vh, Vw and Em for even values.
UiValue
Ui value - A collection of different units used for UI. They are computed at runtime when layout is being calculated (context-aware). The supported units that implement Into<UiValue> are:
Vh
Viewport Height - Represents scalable unit 0% to 100% of the root container. 120% is allowed. Proportional to a height measure even when used in a width field.
Vp
Viewport - Represents scalable unit 0% to 100% of the root container. 120% is allowed.
Vw
Viewport width - Represents scalable unit 0% to 100% of the root container. 120% is allowed. Proportional to a width measure even when used in a height field.

Enums§

GamepadCursorMode
This struct defines how should the cursor movement behave.
Scaling
Scaling - A type used to define how should a Solid node layout scale relative to a parent.
UiDepth
Ui Depth - This component overrides the default Z axis (depth) stacking order. This is useful when fixing Z order flickering. Another use can be offseting an background image for example.
UiLayoutType
Ui Layout Type - Enum holding all UI layout variants.
UiSystems
System set for UiLunexPlugins

Traits§

CameraTextureRenderConstructor
Provides utility costructor methods for Camera
ImageTextureConstructor
Provides utility constructor methods for Image
NiceDisplay
Nice display - Special trait for formatted console debug output with colors.
UiStateTrait
Trait that all states must implement before being integrated into the state machine.
UiValueEvaluate
Trait for implementing evaluation logic for (T).

Functions§

decryption_animation
Creates a decryption effect where random symbols gradually become the actual text
default_linear_curve
Default linear curve used for reflection defaults
hover_set
Utility observer that triggers the UiHoverSet event on triggered event.
observer_touch_layout_root
This observer will mutably touch UiLayoutRoot which will trigger system_layout_compute.
scrambled_reveal_animation
Reveals characters in a scrambled order
slide_in_animation
Creates a slide-in effect where characters come in from the sides
system_color
This system takes care of UiColor data and updates querried Sprite and TextColor components. and updates ColorMaterial and StandardMaterial
system_debug_draw_gizmo_2d
This system draws the outlines of UiLayout and UiLayoutRoot as gizmos.
system_debug_draw_gizmo_3d
This system draws the outlines of UiLayout and UiLayoutRoot as gizmos.
system_debug_print_data
This system traverses the hierarchy and prints the debug information.
system_embedd_resize
This system takes Dimension data and pipes them into querried Handle<Image> data to fit. This will resize the original image texture.
system_fetch_dimension_from_camera
This system takes Camera viewport data and pipes them into querried Dimension + UiLayoutRoot + UiFetchFromCamera.
system_image_size_to_layout
This system takes updated Handle<Image> data and overwrites coresponding UiLayout data to match the text size.
system_layout_compute
This system traverses the hierarchy and computes all nodes.
system_mark_3d
This system traverses the hierarchy and adds UiRoot3d component to children.
system_mesh_2d_reconstruct_from_dimension
This system takes Dimension data and constructs a plane mesh.
system_mesh_3d_reconstruct_from_dimension
This system takes Dimension data and constructs a plane mesh.
system_pipe_sprite_size_from_dimension
This system takes Dimension data and pipes them into querried Sprite.
system_recompute_on_change
system_state_base_balancer
This system controls the UiBase state. This state is decreased based on total sum of all other active states.
system_state_hover_update
This system updates the hover transition value over time
system_state_pipe_into_manager
This system pipes the attached state component data to the UiState component.
system_text_3d_size_from_dimension
This system takes Text3dDimensionOut data and pipes them into querried Transform scale.
system_text_3d_size_to_layout
This system takes updated Text3dDimensionOut data and overwrites coresponding UiLayout data to match the text size.
system_text_size_from_dimension
This system takes TextLayoutInfo data and pipes them into querried Transform scale.
system_text_size_to_layout
This system takes updated TextLayoutInfo data and overwrites coresponding UiLayout data to match the text size.
system_touch_camera_if_fetch_added
This system listens for added UiFetchFromCamera components and if it finds one, mutable accesses all Cameras to trigger fetching systems.
typing_animation_cursor
Simulates typing animation with an vertical line cursor
typing_animation_underscore
Simulates typing animation with an underscore cursor