FyroxEngine / Fyrox

3D and 2D game engine written in Rust
https://fyrox.rs
MIT License
7.61k stars 340 forks source link

Suggestion: root widgets should use horizontal/vertical_alignment #407

Closed bolshoytoster closed 1 year ago

bolshoytoster commented 1 year ago

I'm not sure if this is intended behaviour, but root widgets (no parents) ignore horizontal_alignment and vertical_alignment.

To modify an example from the book:

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::pool::Handle,
    event_loop::ControlFlow,
    gui::{
        button::{ButtonBuilder, ButtonMessage},
        message::UiMessage,
        text::TextBuilder,
        widget::WidgetBuilder,
        UiNode, UserInterface,
        HorizontalAlignment,
        VerticalAlignment,
    },
    plugin::PluginContext,
};

struct Game {
    quit_button_handle: Handle<UiNode>,
}

fn create_button(ui: &mut UserInterface) -> Handle<UiNode> {
    ButtonBuilder::new(WidgetBuilder::new()
        .with_horizontal_alignment(HorizontalAlignment::Right) // <--- Here
        .with_vertical_alignment(VerticalAlignment::Bottom)
    )
        .with_content(
            TextBuilder::new(WidgetBuilder::new())
                .with_text("Quit")
                .build(&mut ui.build_ctx()),
        )
        .build(&mut ui.build_ctx())
}

impl Game {
    fn new(ctx: PluginContext) -> Self {
        Self {
            quit_button_handle: create_button(ctx.user_interface),
        }
    }

    fn on_ui_message(
        &mut self,
        context: &mut PluginContext,
        message: &UiMessage,
        control_flow: &mut ControlFlow,
    ) {
        if let Some(ButtonMessage::Click) = message.data() {
            if message.destination() == self.quit_button_handle {
                *control_flow = ControlFlow::Exit;
            }
        }
    }
}
}

Even though alignment is set to Bottom Right:

        .with_horizontal_alignment(HorizontalAlingment::Right)
        .with_vertical_alignment(VerticalAlignment::Bottom)

The button still appears in the top-left, since it has no parent to align itself with.


I think, in this situation, it should be aligned by with whole screen (i.e. the example it would be in the bottom right).

mrDIMAS commented 1 year ago

Hi! This is intended behavior, because root widget is Canvas. Canvas has infinite bounds and allows setting arbitrary positions for widgets. Because of infinite bounds, there's no way to set alignments - it simply has no meaning in this case. Standard approach to make alignment work is to create a Grid widget and set its width and height explicitly to match application window bounds. Since it has well known size, alignment will work as intended.

Root must be Canvas, just because every UI's windows/popup can be dragged and positioned at arbitrary positions.

bolshoytoster commented 1 year ago

@mrDIMAS fair enough, i'll check out the grids.