bytestring-net / bevy_lunex

Blazingly fast path based retained layout engine for Bevy entities, built around vanilla Bevy ECS.
https://bytestring-net.github.io/bevy_lunex/
Apache License 2.0
438 stars 17 forks source link

FillPortion/Flex Unit [feature request] #53

Open badcodecat opened 6 days ago

badcodecat commented 6 days ago

Proposal

FillPortion units are a way to specify a portion of the total available space that an element should take up. For example, if you have a container with a width 100px and you have 3 children with widths of 1 fill portion, 2 fill portions, and 1 fill portion, the children will take up 25px, 50px, and 25px respectively. Right now there is support for relative units and absolute units, but no way to specify a portion of the available space. This would be a useful feature for creating flexible layouts.

Out in the wild

To better explain the proposal, here are some examples of how this works in other libraries: In the rust GUI library iced, there is a FillPortion unit that works exactly as described above:

Column::new()
    .push(Space::with_width(Length::FillPortion(1))) // Will take up 1/3 of the available space
    .push(Space::with_width(Length::FillPortion(2))) // Will take up 2/3 of the available space

In HTML/CSS, you can achieve a similar effect using flexbox:

<div style="display: flex; width: 100px;">
    <div style="flex: 1;"> 
        <!-- Will take up 1/3 of the available space -->
    </div>
    <div style="flex: 2;"> 
        <!-- Will take up 2/3 of the available space -->
    </div>
</div>

(note that the above HTML/CSS example can be somewhat replicated using bevy's own UI system)

How it could look in bevy_lunex

A new unit could be added, perhaps called Fp for FillPortion to match the naming of other units in bevy_lunex.

// A FillPortion of 3
let fill_portion = Fp(3);
// A FillPortion of 1
let fill_portion = Fp(1);

Considerations

In order for this to work, there are a few things that need to be considered:

IDEDARY commented 6 days ago

This feature request is a bit more complicated than it seems and it is a part of a bigger problem.

No Flexbox

Lunex currently has an absence of flex-like layout, making dynamic layouts not possible and encapsulating text bothersome. It also makes it hard to make grid-like layouts.

Current state

The Fp<T>(Fill portion) unit type you are proposing seems to me like exactly what I planned Sp<T> (Space) type unit to be. You can find mentions of it in the docs, but they are currently unimplemented.

The reason for that is that I already tried tackling this problem by creating a new layout type, Div which compared to Window for example is "context aware" of other elements (UI flow). This happened between version 0.0.11 and 0.1.0. But I soon realized that it is more complex than it seems and decided to postpone it in favor of finishing the rewrite before 0.14.0 lands.

You can still find the code from my attempt commented out in lunex_engine crate.

Moving forward

This feature is of high importance to me and it is a blocker for Lunex to be used in desktop applications. For that reason I created a concept draft for the implementation specifics that I want to implement in the future.

stack_draft

What now?

I will try to implement in in the future, but I have yet to see if I can gather time and courage to tackle this again. It's quite taxing mental overhead issue. But to answer your feature request, I want to implement this.

Any help is always welcome :)