{"id":13794639,"url":"https://github.com/bytestring-net/bevy_lunex","last_synced_at":"2025-05-15T08:11:39.608Z","repository":{"id":176644675,"uuid":"658948045","full_name":"bytestring-net/bevy_lunex","owner":"bytestring-net","description":"Blazingly fast retained layout engine for Bevy ECS.","archived":false,"fork":false,"pushed_at":"2025-04-25T18:32:05.000Z","size":86557,"stargazers_count":716,"open_issues_count":8,"forks_count":33,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-05-06T03:18:41.971Z","etag":null,"topics":["bevy","bevy-lunex","framework","layout","lunex","rust","ui"],"latest_commit_sha":null,"homepage":"https://bytestring-net.github.io/bevy_lunex/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bytestring-net.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-26T20:44:39.000Z","updated_at":"2025-05-06T00:45:27.000Z","dependencies_parsed_at":"2025-03-01T10:27:24.888Z","dependency_job_id":"ad5bf643-980e-4cfd-b74c-f5bca078b562","html_url":"https://github.com/bytestring-net/bevy_lunex","commit_stats":{"total_commits":402,"total_committers":8,"mean_commits":50.25,"dds":0.04975124378109452,"last_synced_commit":"6e4ff0516277fcd9ac49e1b97e4b00e95c105d73"},"previous_names":["bytestring-net/bevy_lunex","bytestring-net/bevy-lunex"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytestring-net%2Fbevy_lunex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytestring-net%2Fbevy_lunex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytestring-net%2Fbevy_lunex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytestring-net%2Fbevy_lunex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bytestring-net","download_url":"https://codeload.github.com/bytestring-net/bevy_lunex/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254301613,"owners_count":22047905,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bevy","bevy-lunex","framework","layout","lunex","rust","ui"],"created_at":"2024-08-03T23:00:45.182Z","updated_at":"2025-05-15T08:11:39.571Z","avatar_url":"https://github.com/bytestring-net.png","language":"Rust","funding_links":[],"categories":["UI","Rust"],"sub_categories":[],"readme":"![image](https://github.com/bytestring-net/bevy_lunex/blob/main/promo/bevy_lunex.png?raw=true)\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://crates.io/crates/bevy_lunex\"\u003e\u003cimg src=\"https://img.shields.io/crates/v/bevy_lunex?label=version\u0026color=d69039\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://crates.io/crates/bevy\"\u003e\u003cimg src=\"https://img.shields.io/badge/v0.16-white.svg?label=bevy\u0026color=bb86a5\"\u003e\u003c/a\u003e\n  \u003ca href=\"./LICENSE-MIT\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-Apache/MIT-white.svg?label=license\u0026color=9fcec4\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://deps.rs/crate/bevy_lunex\"\u003e\u003cimg src=\"https://img.shields.io/badge/check-white.svg?label=deps\u0026color=a0f6b9\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://docs.rs/bevy_lunex\"\u003e\u003cimg src=\"https://img.shields.io/docsrs/bevy_lunex/latest?color=8df7cb\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n#\n\nBlazingly 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.\n\n* **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.\n\n* **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.\n\n* **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.\n\n* **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.\n\n##\n\n![image](https://github.com/bytestring-net/bevy_lunex/blob/main/promo/bevypunk_1.png?raw=true)\n\n\u003e *Try out the live WASM demo on [`Itch.io`](https://idedary.itch.io/bevypunk) (Limited performance \u0026 stutter due to running on a single thread). For best experience compile the project natively.*\n\n## Syntax Example\n\nThis is an example of a clickable Button created from scratch using provided components.\nThanks to ECS, the syntax is highly modular with strong emphasis on components-per-functionality.\nAs you can see, it is no different from vanilla Bevy ECS.\n\n```rust\n// Create UI\ncommands.spawn((\n    // Initialize the UI root for 2D\n    UiLayoutRoot::new_2d(),\n    // Make the UI synchronized with camera viewport size\n    UiFetchFromCamera::\u003c0\u003e,\n)).with_children(|ui| {\n\n    // Spawn a button in the middle of the screen\n    ui.spawn((\n        Name::new(\"My Button\"),\n        // Specify the position and size of the button\n        UiLayout::window().pos(Rl((50.0, 50.0))).size((200.0, 50.0)).pack(),\n        // When hovered, it will request the cursor icon to be changed\n        OnHoverSetCursor::new(SystemCursorIcon::Pointer),\n    )).with_children(|ui| {\n        \n        // Spawn a child node but with a background\n        ui.spawn((\n            // You can define layouts for multiple states\n            UiLayout::new(vec![\n                // The default state, just fill the parent\n                (UiBase::id(), UiLayout::window().full()),\n                // The hover state, grow to 105% of the parent from center\n                (UiHover::id(), UiLayout::window().anchor(Anchor::Center).size(Rl(105.0)))\n            ]),\n            // Enable the hover state and give it some properties\n            UiHover::new().forward_speed(20.0).backward_speed(4.0),\n            // You can specify colors for multiple states\n            UiColor::new(vec![\n                (UiBase::id(), Color::BEVYPUNK_RED.with_alpha(0.15)),\n                (UiHover::id(), Color::BEVYPUNK_YELLOW.with_alpha(1.2))\n            ]),\n            // You can attach any form of rendering to the node, be it sprite, mesh or something custom\n            Sprite {\n                image: asset_server.load(\"images/button.png\"),\n                // Here we enable sprite slicing\n                image_mode: SpriteImageMode::Sliced(TextureSlicer { border: BorderRect::all(32.0), ..default() }),\n                ..default()\n            },\n            // Make sure it does not cover the bounding zone of parent\n            Pickable::IGNORE,\n        )).with_children(|ui| {\n\n            // Spawn a text child node\n            ui.spawn((\n                // For text we always use window layout to position it. The size is computed at runtime from text bounds\n                UiLayout::window().pos((Rh(40.0), Rl(50.0))).anchor(Anchor::CenterLeft).pack(),\n                UiColor::new(vec![\n                    (UiBase::id(), Color::BEVYPUNK_RED),\n                    (UiHover::id(), Color::BEVYPUNK_YELLOW.with_alpha(1.2))\n                ]),\n                UiHover::new().forward_speed(20.0).backward_speed(4.0),\n                // Here we specify the text height proportional to the parent node\n                UiTextSize::from(Rh(60.0)),\n                // You can attach text like this\n                Text2d::new(\"Click me!\"),\n                TextFont {\n                    font: asset_server.load(\"fonts/semibold.ttf\"),\n                    font_size: 64.0,\n                    ..default()\n                },\n                // Make sure it does not cover the bounding zone of parent\n                Pickable::IGNORE,\n            ));\n        });\n    })\n    // Utility observers that enable the hover state on trigger\n    .observe(hover_set::\u003cPointer\u003cOver\u003e, true\u003e)\n    .observe(hover_set::\u003cPointer\u003cOut\u003e, false\u003e)\n    // Interactivity is done through observers, you can query anything here\n    .observe(|_: Trigger\u003cPointer\u003cClick\u003e\u003e| {\n        println!(\"I was clicked!\");\n    });\n});\n```\n\n## Documentation\n\n- The Lunex Book: [`Bevy Lunex book`](https://bytestring-net.github.io/bevy_lunex/).\n\n- Highly documented source code on Docs.rs: [`Docs.rs`](https://docs.rs/bevy_lunex/latest/bevy_lunex/).\n\n- Highly documented production-ready example: [`Bevypunk example`](https://github.com/IDEDARY/Bevypunk).\n\n## Contributing\n\nAny 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.\n\n## Licensing\n\nReleased under both [APACHE](./LICENSE-APACHE) and [MIT](./LICENSE-MIT) licenses. Pick one that suits you the most!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbytestring-net%2Fbevy_lunex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbytestring-net%2Fbevy_lunex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbytestring-net%2Fbevy_lunex/lists"}