Skip to main content

RepeatedGridTrack

Struct RepeatedGridTrack 

Source
pub struct RepeatedGridTrack { /* private fields */ }
Available on crate feature bevy_ui only.
Expand description

Represents a possibly repeated GridTrack.

The repetition parameter can either be:

  • The integer 1, in which case the track is non-repeated.
  • a u16 count to repeat the track N times.
  • A GridTrackRepetition::AutoFit or GridTrackRepetition::AutoFill.

Note: that in the common case you want a non-repeating track (repetition count 1), you may use the constructor methods on GridTrack to create a RepeatedGridTrack. i.e. GridTrack::px(10.0) is equivalent to RepeatedGridTrack::px(1, 10.0).

You may only use one auto-repetition per track list. And if your track list contains an auto repetition then all tracks (in and outside of the repetition) must be fixed size (px or percent). Integer repetitions are just shorthand for writing out N tracks longhand and are not subject to the same limitations.

Implementations§

Source§

impl RepeatedGridTrack

Source

pub fn px<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T

Create a repeating set of grid tracks with a fixed pixel size

Examples found in repository?
examples/ui/scroll_and_overflow/overflow_debug.rs (line 118)
76fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
77    // Camera
78
79    commands.spawn(Camera2d);
80
81    // Instructions
82
83    let text_font = TextFont::default();
84
85    commands
86        .spawn((
87            Text::new(
88                "Next Overflow Setting (O)\nNext Container Size (S)\nToggle Animation (space)\n\n",
89            ),
90            text_font.clone(),
91            Node {
92                position_type: PositionType::Absolute,
93                top: px(12),
94                left: px(12),
95                ..default()
96            },
97            Instructions,
98        ))
99        .with_child((
100            TextSpan::new(format!("{:?}", Overflow::clip())),
101            text_font.clone(),
102        ));
103
104    // Overflow Debug
105
106    commands
107        .spawn(Node {
108            width: percent(100),
109            height: percent(100),
110            justify_content: JustifyContent::Center,
111            align_items: AlignItems::Center,
112            ..default()
113        })
114        .with_children(|parent| {
115            parent
116                .spawn(Node {
117                    display: Display::Grid,
118                    grid_template_columns: RepeatedGridTrack::px(3, CONTAINER_SIZE),
119                    grid_template_rows: RepeatedGridTrack::px(2, CONTAINER_SIZE),
120                    row_gap: px(80),
121                    column_gap: px(80),
122                    ..default()
123                })
124                .with_children(|parent| {
125                    spawn_image(parent, &asset_server, Move);
126                    spawn_image(parent, &asset_server, Scale);
127                    spawn_image(parent, &asset_server, Rotate);
128
129                    spawn_text(parent, &asset_server, Move);
130                    spawn_text(parent, &asset_server, Scale);
131                    spawn_text(parent, &asset_server, Rotate);
132                });
133        });
134}
More examples
Hide additional examples
examples/ui/scroll_and_overflow/drag_to_scroll.rs (line 69)
22fn setup(mut commands: Commands) {
23    let w = 60;
24    let h = 40;
25
26    commands.spawn(Camera2d);
27    commands.insert_resource(UiScale(0.5));
28
29    commands
30        .spawn((
31            Node {
32                width: percent(100),
33                height: percent(100),
34                overflow: Overflow::scroll(),
35                ..Default::default()
36            },
37            ScrollPosition(Vec2::ZERO),
38            ScrollableNode,
39            ScrollStart(Vec2::ZERO),
40        ))
41        .observe(
42            |drag: On<PointerDrag>,
43             ui_scale: Res<UiScale>,
44             mut scroll_position_query: Query<
45                (&mut ScrollPosition, &ScrollStart),
46                With<ScrollableNode>,
47            >| {
48                if let Ok((mut scroll_position, start)) = scroll_position_query.single_mut() {
49                    scroll_position.0 = (start.0 - drag.distance / ui_scale.0).max(Vec2::ZERO);
50                }
51            },
52        )
53        .observe(
54            |_: On<PointerDragStart>,
55             mut scroll_position_query: Query<
56                (&ComputedNode, &mut ScrollStart),
57                With<ScrollableNode>,
58            >| {
59                if let Ok((computed_node, mut start)) = scroll_position_query.single_mut() {
60                    start.0 = computed_node.scroll_position * computed_node.inverse_scale_factor;
61                }
62            },
63        )
64        .with_children(|commands| {
65            commands
66                .spawn((
67                    Node {
68                        display: Display::Grid,
69                        grid_template_rows: RepeatedGridTrack::px(w as i32, 100.),
70                        grid_template_columns: RepeatedGridTrack::px(h as i32, 100.),
71                        ..default()
72                    },
73                    Pickable {
74                        is_hoverable: false,
75                        should_block_lower: true,
76                    }
77                ))
78                .with_children(|commands| {
79                    for y in 0..h {
80                        for x in 0..w {
81                            let tile_color = if (x + y) % 2 == 1 {
82                                let hue = ((x as f32 / w as f32) * 270.0)
83                                    + ((y as f32 / h as f32) * 90.0);
84                                Color::hsl(hue, 1., 0.5)
85                            } else {
86                                Color::BLACK
87                            };
88                            commands.spawn((
89                                Node {
90                                    grid_row: GridPlacement::start(y + 1),
91                                    grid_column: GridPlacement::start(x + 1),
92                                    ..default()
93                                },
94                                Pickable {
95                                    should_block_lower: false,
96                                    is_hoverable: true,
97                                },
98                                TileColor(tile_color),
99                                BackgroundColor(tile_color),
100                            ))
101                            .observe(|over: On<PointerOver>, mut query: Query<&mut BackgroundColor>,| {
102                                if let Ok(mut background_color) = query.get_mut(over.entity) {
103                                    background_color.0 = RED.into();
104                                }
105                            })
106                            .observe(|out: On<PointerOut>, mut query: Query<(&mut BackgroundColor, &TileColor)>| {
107                                if let Ok((mut background_color, tile_color)) = query.get_mut(out.entity) {
108                                    background_color.0 = tile_color.0;
109                                }
110                            });
111                        }
112                    }
113                });
114        });
115}
examples/testbed/ui.rs (lines 2278-2281)
2262    pub fn setup(mut commands: Commands) {
2263        let color_stops = vec![
2264            ColorStop::new(Color::BLACK, px(5)),
2265            ColorStop::new(Color::WHITE, px(5)),
2266            ColorStop::new(Color::WHITE, percent(100)),
2267            ColorStop::auto(RED),
2268        ];
2269
2270        commands.spawn((Camera2d, DespawnOnExit(super::Scene::RadialGradient)));
2271        commands
2272            .spawn((
2273                Node {
2274                    width: percent(100),
2275                    height: percent(100),
2276                    display: Display::Grid,
2277                    align_items: AlignItems::Start,
2278                    grid_template_columns: vec![RepeatedGridTrack::px(
2279                        GridTrackRepetition::AutoFill,
2280                        CELL_SIZE,
2281                    )],
2282                    grid_auto_flow: GridAutoFlow::Row,
2283                    row_gap: px(GAP),
2284                    column_gap: px(GAP),
2285                    padding: UiRect::all(px(GAP)),
2286                    ..default()
2287                },
2288                DespawnOnExit(super::Scene::RadialGradient),
2289            ))
2290            .with_children(|commands| {
2291                for (shape, shape_label) in [
2292                    (RadialGradientShape::ClosestSide, "ClosestSide"),
2293                    (RadialGradientShape::FarthestSide, "FarthestSide"),
2294                    (RadialGradientShape::Circle(percent(55)), "Circle(55%)"),
2295                    (RadialGradientShape::FarthestCorner, "FarthestCorner"),
2296                ] {
2297                    for (position, position_label) in [
2298                        (UiPosition::TOP_LEFT, "TOP_LEFT"),
2299                        (UiPosition::LEFT, "LEFT"),
2300                        (UiPosition::BOTTOM_LEFT, "BOTTOM_LEFT"),
2301                        (UiPosition::TOP, "TOP"),
2302                        (UiPosition::CENTER, "CENTER"),
2303                        (UiPosition::BOTTOM, "BOTTOM"),
2304                        (UiPosition::TOP_RIGHT, "TOP_RIGHT"),
2305                        (UiPosition::RIGHT, "RIGHT"),
2306                        (UiPosition::BOTTOM_RIGHT, "BOTTOM_RIGHT"),
2307                    ] {
2308                        for (w, h) in [(CELL_SIZE, CELL_SIZE), (CELL_SIZE, CELL_SIZE / 2.)] {
2309                            commands
2310                                .spawn((
2311                                    BackgroundColor(GRAY_700.into()),
2312                                    Node {
2313                                        display: Display::Grid,
2314                                        width: px(CELL_SIZE),
2315                                        ..Default::default()
2316                                    },
2317                                ))
2318                                .with_children(|commands| {
2319                                    commands.spawn((
2320                                        Node {
2321                                            margin: UiRect::all(px(2)),
2322                                            ..default()
2323                                        },
2324                                        Text(format!("{shape_label}\n{position_label}")),
2325                                        TextFont::from_font_size(9.),
2326                                    ));
2327                                    commands.spawn((
2328                                        Node {
2329                                            width: px(w),
2330                                            height: px(h),
2331                                            ..default()
2332                                        },
2333                                        BackgroundGradient::from(RadialGradient {
2334                                            stops: color_stops.clone(),
2335                                            position,
2336                                            shape,
2337                                            ..default()
2338                                        }),
2339                                    ));
2340                                });
2341                        }
2342                    }
2343                }
2344            });
2345    }
2346}
2347
2348mod transformations {
2349    use bevy::{color::palettes::css::*, prelude::*};
2350
2351    pub fn setup(mut commands: Commands) {
2352        commands.spawn((Camera2d, DespawnOnExit(super::Scene::Transformations)));
2353        commands
2354            .spawn((
2355                Node {
2356                    width: percent(100),
2357                    height: percent(100),
2358                    display: Display::Block,
2359                    ..default()
2360                },
2361                DespawnOnExit(super::Scene::Transformations),
2362            ))
2363            .with_children(|parent| {
2364                for (transformation, label, background) in [
2365                    (
2366                        UiTransform::from_rotation(Rot2::degrees(45.)),
2367                        "Rotate 45 degrees",
2368                        RED,
2369                    ),
2370                    (
2371                        UiTransform::from_scale(Vec2::new(2., 0.5)),
2372                        "Scale 2.x 0.5y",
2373                        GREEN,
2374                    ),
2375                    (
2376                        UiTransform::from_translation(Val2::px(-50., 50.)),
2377                        "Translate -50px x +50px y",
2378                        BLUE,
2379                    ),
2380                    (
2381                        UiTransform {
2382                            translation: Val2::px(50., 0.),
2383                            scale: Vec2::new(-1., 1.),
2384                            rotation: Rot2::degrees(30.),
2385                        },
2386                        "T 50px x\nS -1.x (refl)\nR 30deg",
2387                        DARK_CYAN,
2388                    ),
2389                ] {
2390                    parent
2391                        .spawn((Node {
2392                            width: percent(100),
2393                            margin: UiRect {
2394                                top: px(50),
2395                                bottom: px(50),
2396                                ..default()
2397                            },
2398                            align_items: AlignItems::Center,
2399                            justify_content: JustifyContent::SpaceAround,
2400                            ..default()
2401                        },))
2402                        .with_children(|row| {
2403                            row.spawn((
2404                                Text::new("Before Tf"),
2405                                Node {
2406                                    width: px(100),
2407                                    height: px(100),
2408                                    border_radius: BorderRadius::bottom_right(px(25.)),
2409                                    ..default()
2410                                },
2411                                BackgroundColor(background.into()),
2412                                TextFont::default(),
2413                            ));
2414                            row.spawn((
2415                                Text::new(label),
2416                                Node {
2417                                    width: px(100),
2418                                    height: px(100),
2419                                    border_radius: BorderRadius::bottom_right(px(25.)),
2420                                    ..default()
2421                                },
2422                                BackgroundColor(background.into()),
2423                                transformation,
2424                                TextFont::default(),
2425                            ));
2426                        });
2427                }
2428            });
2429    }
2430}
2431
2432#[cfg(feature = "bevy_ui_debug")]
2433mod debug_outlines {
2434    use bevy::{
2435        color::palettes::css::{BLUE, GRAY, RED},
2436        prelude::*,
2437        ui_render::UiDebugOptions,
2438    };
2439
2440    pub fn setup(mut commands: Commands, mut debug_options: ResMut<GlobalUiDebugOptions>) {
2441        debug_options.enabled = true;
2442        debug_options.line_width = 5.;
2443        debug_options.line_color_override = Some(LinearRgba::GREEN);
2444        debug_options.show_hidden = true;
2445        debug_options.show_clipped = true;
2446
2447        let debug_options: UiDebugOptions = (*debug_options.as_ref()).into();
2448
2449        commands.spawn((Camera2d, DespawnOnExit(super::Scene::DebugOutlines)));
2450        commands
2451            .spawn((
2452                Node {
2453                    width: percent(100),
2454                    height: percent(50),
2455                    align_items: AlignItems::Center,
2456                    justify_content: JustifyContent::SpaceAround,
2457                    ..default()
2458                },
2459                DespawnOnExit(super::Scene::DebugOutlines),
2460            ))
2461            .with_children(|parent| {
2462                parent.spawn((
2463                    Node {
2464                        width: px(100),
2465                        height: px(100),
2466                        ..default()
2467                    },
2468                    BackgroundColor(GRAY.into()),
2469                    UiTransform::from_rotation(Rot2::degrees(45.)),
2470                ));
2471
2472                parent.spawn((Text::new("Regular Text"), TextFont::default()));
2473
2474                parent.spawn((
2475                    Node {
2476                        width: px(100),
2477                        height: px(100),
2478                        ..default()
2479                    },
2480                    Text::new("Invisible"),
2481                    BackgroundColor(GRAY.into()),
2482                    TextFont::default(),
2483                    Visibility::Hidden,
2484                ));
2485
2486                parent
2487                    .spawn((
2488                        Node {
2489                            width: px(100),
2490                            height: px(100),
2491                            padding: UiRect {
2492                                left: px(25),
2493                                top: px(25),
2494                                ..Default::default()
2495                            },
2496                            overflow: Overflow::clip(),
2497                            ..default()
2498                        },
2499                        BackgroundColor(RED.into()),
2500                    ))
2501                    .with_children(|child| {
2502                        child.spawn((
2503                            Node {
2504                                min_width: px(100),
2505                                min_height: px(100),
2506                                ..default()
2507                            },
2508                            BackgroundColor(BLUE.into()),
2509                        ));
2510                    });
2511            });
2512
2513        commands
2514            .spawn((
2515                Node {
2516                    width: percent(100),
2517                    height: percent(50),
2518                    top: percent(50),
2519                    align_items: AlignItems::Center,
2520                    justify_content: JustifyContent::SpaceAround,
2521                    ..default()
2522                },
2523                DespawnOnExit(super::Scene::DebugOutlines),
2524            ))
2525            .with_children(|parent| {
2526                parent.spawn((
2527                    Node {
2528                        width: px(200),
2529                        height: px(200),
2530                        border: UiRect {
2531                            top: px(10),
2532                            bottom: px(20),
2533                            left: px(30),
2534                            right: px(40),
2535                        },
2536                        border_radius: BorderRadius::bottom_right(px(10)),
2537                        padding: UiRect {
2538                            top: px(40),
2539                            bottom: px(30),
2540                            left: px(20),
2541                            right: px(10),
2542                        },
2543                        ..default()
2544                    },
2545                    children![(
2546                        Text::new("border padding content outlines"),
2547                        TextFont::default(),
2548                        UiDebugOptions {
2549                            enabled: false,
2550                            ..default()
2551                        }
2552                    )],
2553                    UiDebugOptions {
2554                        outline_border_box: true,
2555                        outline_padding_box: true,
2556                        outline_content_box: true,
2557                        ignore_border_radius: false,
2558                        ..debug_options
2559                    },
2560                ));
2561
2562                // Vertical scrollbar (non-functional)
2563                parent.spawn((
2564                    Node {
2565                        flex_direction: FlexDirection::Column,
2566                        width: px(90),
2567                        height: px(230),
2568                        overflow: Overflow::scroll_y(),
2569                        scrollbar_width: 20.,
2570                        ..default()
2571                    },
2572                    ScrollPosition(Vec2::new(180., 180.)),
2573                    UiDebugOptions {
2574                        line_width: 3.,
2575                        outline_scrollbars: true,
2576                        show_hidden: false,
2577                        show_clipped: false,
2578                        ..debug_options
2579                    },
2580                    Children::spawn(SpawnIter((0..20).map(move |i| {
2581                        (
2582                            Node::default(),
2583                            children![(
2584                                Text(format!("Item {i}")),
2585                                UiDebugOptions {
2586                                    enabled: false,
2587                                    ..default()
2588                                }
2589                            )],
2590                            UiDebugOptions {
2591                                enabled: false,
2592                                ..default()
2593                            },
2594                        )
2595                    }))),
2596                ));
2597
2598                // Horizontal scrollbar (non-functional)
2599                parent.spawn((
2600                    Node {
2601                        flex_direction: FlexDirection::Row,
2602                        width: px(156),
2603                        height: px(70),
2604                        overflow: Overflow::scroll_x(),
2605                        scrollbar_width: 10.,
2606                        ..default()
2607                    },
2608                    UiDebugOptions {
2609                        line_width: 3.,
2610                        outline_scrollbars: true,
2611                        show_hidden: false,
2612                        show_clipped: false,
2613                        ..debug_options
2614                    },
2615                    Children::spawn(SpawnIter((0..20).map(move |i| {
2616                        (
2617                            Node::default(),
2618                            children![(
2619                                Text(format!("Item {i}")),
2620                                UiDebugOptions {
2621                                    enabled: false,
2622                                    ..default()
2623                                }
2624                            )],
2625                            UiDebugOptions {
2626                                enabled: false,
2627                                ..default()
2628                            },
2629                        )
2630                    }))),
2631                ));
2632
2633                // bi-directional scrollbar (non-functional)
2634                parent.spawn((
2635                    Node {
2636                        flex_direction: FlexDirection::Column,
2637                        width: px(230),
2638                        height: px(125),
2639                        overflow: Overflow::scroll(),
2640                        scrollbar_width: 20.,
2641                        ..default()
2642                    },
2643                    ScrollPosition(Vec2::new(300., 0.)),
2644                    UiDebugOptions {
2645                        line_width: 3.,
2646                        outline_scrollbars: true,
2647                        show_hidden: false,
2648                        show_clipped: false,
2649                        ..debug_options
2650                    },
2651                    Children::spawn(SpawnIter((0..6).map(move |i| {
2652                        (
2653                            Node {
2654                                flex_direction: FlexDirection::Row,
2655                                ..default()
2656                            },
2657                            Children::spawn(SpawnIter((0..6).map({
2658                                move |j| {
2659                                    (
2660                                        Text(format!("Item {}", (i * 5) + j)),
2661                                        UiDebugOptions {
2662                                            enabled: false,
2663                                            ..default()
2664                                        },
2665                                    )
2666                                }
2667                            }))),
2668                            UiDebugOptions {
2669                                enabled: false,
2670                                ..default()
2671                            },
2672                        )
2673                    }))),
2674                ));
2675            });
2676    }
2677
2678    pub fn teardown(mut debug_options: ResMut<GlobalUiDebugOptions>) {
2679        *debug_options = GlobalUiDebugOptions::default();
2680    }
2681}
2682
2683mod viewport_coords {
2684    use bevy::{color::palettes::css::*, prelude::*};
2685
2686    const PALETTE: [Srgba; 9] = [RED, WHITE, BEIGE, AQUA, CRIMSON, NAVY, AZURE, LIME, BLACK];
2687
2688    pub fn setup(mut commands: Commands) {
2689        commands.spawn((Camera2d, DespawnOnExit(super::Scene::ViewportCoords)));
2690        commands
2691            .spawn((
2692                Node {
2693                    width: vw(100),
2694                    height: vh(100),
2695                    border: UiRect::axes(vw(5), vh(5)),
2696                    flex_wrap: FlexWrap::Wrap,
2697                    ..default()
2698                },
2699                BorderColor::all(PALETTE[0]),
2700                DespawnOnExit(super::Scene::ViewportCoords),
2701            ))
2702            .with_children(|builder| {
2703                builder.spawn((
2704                    Node {
2705                        width: vw(30),
2706                        height: vh(30),
2707                        border: UiRect::all(vmin(5)),
2708                        ..default()
2709                    },
2710                    BackgroundColor(PALETTE[1].into()),
2711                    BorderColor::all(PALETTE[8]),
2712                ));
2713
2714                builder.spawn((
2715                    Node {
2716                        width: vw(60),
2717                        height: vh(30),
2718                        ..default()
2719                    },
2720                    BackgroundColor(PALETTE[2].into()),
2721                ));
2722
2723                builder.spawn((
2724                    Node {
2725                        width: vw(45),
2726                        height: vh(30),
2727                        border: UiRect::left(vmax(45. / 2.)),
2728                        ..default()
2729                    },
2730                    BackgroundColor(PALETTE[3].into()),
2731                    BorderColor::all(PALETTE[7]),
2732                ));
2733
2734                builder.spawn((
2735                    Node {
2736                        width: vw(45),
2737                        height: vh(30),
2738                        border: UiRect::right(vmax(45. / 2.)),
2739                        ..default()
2740                    },
2741                    BackgroundColor(PALETTE[4].into()),
2742                    BorderColor::all(PALETTE[7]),
2743                ));
2744
2745                builder.spawn((
2746                    Node {
2747                        width: vw(60),
2748                        height: vh(30),
2749                        ..default()
2750                    },
2751                    BackgroundColor(PALETTE[5].into()),
2752                ));
2753
2754                builder.spawn((
2755                    Node {
2756                        width: vw(30),
2757                        height: vh(30),
2758                        border: UiRect::all(vmin(5)),
2759                        ..default()
2760                    },
2761                    BackgroundColor(PALETTE[6].into()),
2762                    BorderColor::all(PALETTE[8]),
2763                ));
2764            });
2765    }
2766}
2767
2768mod viewport_node {
2769    use bevy::{
2770        camera::RenderTarget, prelude::*, render::render_resource::TextureFormat,
2771        ui::widget::ViewportNode,
2772    };
2773
2774    pub fn setup(
2775        mut commands: Commands,
2776        mut images: ResMut<Assets<Image>>,
2777        mut meshes: ResMut<Assets<Mesh>>,
2778        mut materials: ResMut<Assets<StandardMaterial>>,
2779    ) {
2780        commands.spawn((
2781            Camera3d::default(),
2782            DespawnOnExit(super::Scene::ViewportNode),
2783        ));
2784
2785        let image = Image::new_target_texture(0, 0, TextureFormat::Bgra8UnormSrgb, None);
2786        let image_handle = images.add(image);
2787
2788        let camera = commands
2789            .spawn((
2790                Camera3d::default(),
2791                Camera {
2792                    order: -1,
2793                    ..default()
2794                },
2795                RenderTarget::Image(image_handle.into()),
2796                DespawnOnExit(super::Scene::ViewportNode),
2797            ))
2798            .id();
2799
2800        commands.spawn((
2801            Mesh3d(meshes.add(Cuboid::new(5.0, 5.0, 5.0))),
2802            MeshMaterial3d(materials.add(Color::WHITE)),
2803            Transform {
2804                translation: Vec3::new(0.0, 0.0, -10.0),
2805                rotation: Quat::from_euler(EulerRot::XYZ, 0.4, 0.7, 0.1),
2806                ..default()
2807            },
2808            DespawnOnExit(super::Scene::ViewportNode),
2809        ));
2810
2811        commands.spawn((
2812            Node {
2813                position_type: PositionType::Absolute,
2814                top: px(50),
2815                left: px(50),
2816                width: px(200),
2817                height: px(200),
2818                border: UiRect::all(px(5)),
2819                ..default()
2820            },
2821            BorderColor::all(Color::WHITE),
2822            ViewportNode::new(camera),
2823            DespawnOnExit(super::Scene::ViewportNode),
2824        ));
2825    }
2826}
2827
2828mod outer_color {
2829    use bevy::prelude::*;
2830
2831    pub fn setup(mut commands: Commands) {
2832        let radius = CornerRadius::from(percent(33.));
2833        let width = px(10.);
2834
2835        commands.spawn((Camera2d, DespawnOnExit(super::Scene::OuterColor)));
2836        commands
2837            .spawn((
2838                Node {
2839                    display: Display::Grid,
2840                    grid_template_columns: RepeatedGridTrack::px(3, 200.),
2841                    grid_template_rows: RepeatedGridTrack::px(3, 200.),
2842                    margin: UiRect::AUTO,
2843                    ..default()
2844                },
2845                DespawnOnExit(super::Scene::OuterColor),
2846            ))
2847            .with_children(|builder| {
2848                for (border, border_radius, invert) in [
2849                    (UiRect::ZERO, BorderRadius::bottom_right(radius), true),
2850                    (UiRect::top(width), BorderRadius::top(radius), false),
2851                    (UiRect::ZERO, BorderRadius::bottom_left(radius), true),
2852                    (UiRect::left(width), BorderRadius::left(radius), false),
2853                    (UiRect::all(width), BorderRadius::all(radius.x), true),
2854                    (UiRect::right(width), BorderRadius::right(radius), false),
2855                    (UiRect::ZERO, BorderRadius::top_right(radius), true),
2856                    (UiRect::bottom(width), BorderRadius::bottom(radius), false),
2857                    (UiRect::ZERO, BorderRadius::top_left(radius), true),
2858                ] {
2859                    builder
2860                        .spawn((
2861                            Node {
2862                                width: px(200.),
2863                                height: px(200.),
2864                                border_radius,
2865                                border,
2866                                ..default()
2867                            },
2868                            BorderColor::all(bevy::color::palettes::css::RED),
2869                        ))
2870                        .insert_if(BackgroundColor(Color::WHITE), || !invert)
2871                        .insert_if(OuterColor(Color::WHITE), || invert);
2872                }
2873            });
2874    }
examples/showcase/mines.rs (lines 276-279)
257fn rebuild_game_ui(commands: &mut Commands, root: Entity, game: &Game, assets: &AssetServer) {
258    commands.entity(root).despawn_related::<Children>();
259
260    commands.entity(root).with_children(|parent| {
261        parent
262            .spawn(Node {
263                flex_direction: FlexDirection::Column,
264                row_gap: px(20),
265                ..default()
266            })
267            .with_children(|parent| {
268                parent
269                    .spawn((
270                        Node {
271                            display: Display::Grid,
272                            padding: UiRect::all(px(BOARD_PADDING)),
273                            border_radius: BorderRadius::all(px(25)),
274                            row_gap: px(TILE_GAP),
275                            column_gap: px(TILE_GAP),
276                            grid_template_columns: RepeatedGridTrack::px(
277                                game.field.width,
278                                TILE_SIZE,
279                            ),
280                            grid_template_rows: RepeatedGridTrack::px(game.field.height, TILE_SIZE),
281                            ..default()
282                        },
283                        BackgroundColor(BACKGROUND_COLOR),
284                    ))
285                    .with_children(|parent| {
286                        for (position, tile) in game.field.iter() {
287                            let tile_node = Node {
288                                grid_column: GridPlacement::start((position.x + 1) as i16),
289                                grid_row: GridPlacement::start((position.y + 1) as i16),
290                                border: px(4).all(),
291                                border_radius: px(8).into(),
292                                justify_content: JustifyContent::Center,
293                                align_items: AlignItems::Center,
294                                ..default()
295                            };
296
297                            if game.game_over && tile.mined {
298                                parent.spawn((
299                                    tile_node,
300                                    BackgroundColor(BACKGROUND_COLOR),
301                                    BorderColor::all(Color::NONE),
302                                    Pickable::IGNORE,
303                                    children![(
304                                        Text::new("*"),
305                                        TextFont::from_font_size(24.0),
306                                        TextColor(MOST_DANGER_COLOR),
307                                    )],
308                                ));
309                            } else if game.game_over || tile.revealed {
310                                let mine_count = game.field.count_adjacent_mines(position);
311                                let color = match mine_count {
312                                    0 => continue,
313                                    1 => MILD_DANGER_COLOR,
314                                    2 => SOME_DANGER_COLOR,
315                                    3 => VERY_DANGER_COLOR,
316                                    _ => MOST_DANGER_COLOR,
317                                };
318                                parent.spawn((
319                                    tile_node,
320                                    BackgroundColor(BACKGROUND_COLOR),
321                                    BorderColor::all(color),
322                                    Pickable::IGNORE,
323                                    children![(
324                                        Text::new(mine_count.to_string()),
325                                        TextFont::from_font_size(20.0),
326                                        TextColor(color),
327                                    )],
328                                ));
329                            } else {
330                                parent
331                                    .spawn((
332                                        tile_node,
333                                        TileCell(position),
334                                        BackgroundColor(BACKGROUND_COLOR),
335                                        BorderColor::all(TILE_BORDER_COLOR),
336                                    ))
337                                    .with_children(|parent| {
338                                        if tile.flagged {
339                                            parent.spawn((
340                                                ImageNode::new(assets.load("textures/flag.png")),
341                                                Node {
342                                                    width: px(20),
343                                                    height: px(20),
344                                                    ..default()
345                                                },
346                                                Pickable::IGNORE,
347                                            ));
348                                        }
349                                    });
350                            }
351                        }
352                    });
353
354                parent
355                    .spawn(Node {
356                        width: percent(100),
357                        height: px(50),
358                        margin: px(15).vertical(),
359                        justify_content: JustifyContent::SpaceBetween,
360                        align_items: AlignItems::Center,
361                        ..default()
362                    })
363                    .with_children(|parent| {
364                        parent.spawn((
365                            Node {
366                                align_items: AlignItems::Center,
367                                column_gap: px(3),
368                                ..default()
369                            },
370                            children![
371                                (
372                                    ImageNode::new(assets.load("textures/flag.png")),
373                                    Node {
374                                        width: px(28),
375                                        height: px(28),
376                                        ..default()
377                                    },
378                                    Pickable::IGNORE,
379                                ),
380                                (
381                                    Text::new(
382                                        (game.field.mine_count() - game.field.flag_count())
383                                            .to_string()
384                                    ),
385                                    TextFont::from_font_size(24.0),
386                                )
387                            ],
388                        ));
389
390                        if game.field.is_cleared() || game.game_over {
391                            parent.spawn((
392                                Node {
393                                    width: percent(100),
394                                    height: percent(100),
395                                    position_type: PositionType::Absolute,
396                                    justify_content: JustifyContent::Center,
397                                    align_items: AlignItems::Center,
398                                    ..default()
399                                },
400                                Pickable::IGNORE,
401                                children![(
402                                    Text::new(if game.field.is_cleared() {
403                                        "mines cleared!"
404                                    } else {
405                                        "boom!"
406                                    }),
407                                    TextFont::from_font_size(24.0),
408                                )],
409                            ));
410
411                            parent.spawn(text_button("new game", ButtonAction::Menu));
412                        }
413                    });
414            });
415    });
416}
examples/ui/text/multiple_text_inputs.rs (line 56)
39fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
40    commands.spawn(Camera2d);
41
42    let font = TextFont {
43        font: asset_server.load("fonts/FiraMono-Medium.ttf").into(),
44        font_size: FontSize::Px(24.),
45        ..default()
46    };
47
48    commands
49        .spawn((
50            Node {
51                width: percent(100.),
52                height: percent(100.),
53                display: Display::Grid,
54                justify_content: JustifyContent::Center,
55                align_content: AlignContent::Center,
56                grid_template_columns: vec![GridTrack::px(160.), RepeatedGridTrack::px(3, 320.)],
57                row_gap: px(8.),
58                column_gap: px(8.),
59                ..default()
60            },
61            TabGroup::default(),
62        ))
63        .with_children(|parent| {
64            parent.spawn((
65                Text::new("Multiple Text Inputs Example"),
66                Node {
67                    grid_column: GridPlacement::span(4),
68                    justify_self: JustifySelf::Center,
69                    margin: px(16).bottom(),
70                    ..default()
71                },
72                TextColor::WHITE,
73                font.clone(),
74            ));
75
76            let label_font = font.clone().with_font_size(14.);
77            for label in ["Justify", "EditableText", "value", "submission"] {
78                parent.spawn((
79                    Text::new(label),
80                    label_font.clone(),
81                    Node {
82                        justify_self: JustifySelf::Center,
83                        margin: px(-4).bottom(),
84                        ..default()
85                    },
86                ));
87            }
88
89            for (row, justify) in [
90                Justify::Left,
91                Justify::Center,
92                Justify::Right,
93                Justify::Justified,
94                Justify::Start,
95                Justify::End,
96            ]
97            .into_iter()
98            .enumerate()
99            {
100                parent.spawn((
101                    Node {
102                        border: px(4).all(),
103                        justify_content: JustifyContent::Center,
104                        align_items: AlignItems::Center,
105                        ..default()
106                    },
107                    BorderColor::all(Color::WHITE),
108                    children![(Text::new(format!("{justify:?}")), font.clone(),)],
109                ));
110
111                let mut input = parent.spawn((
112                    Node {
113                        border: px(4.).all(),
114                        padding: px(4.).all(),
115                        ..default()
116                    },
117                    TextInput,
118                    EditableText::new(format!("Initial text {row}")),
119                    TextCursorStyle::default(),
120                    font.clone(),
121                    BackgroundColor(bevy::color::palettes::css::DARK_GREY.into()),
122                    TextInputRow(row),
123                    TextLayout::no_wrap().with_justify(justify),
124                    TabIndex(row as i32),
125                    BorderColor::all(SLATE_300),
126                ));
127                if row == 0 {
128                    input.insert(AutoFocus);
129                }
130
131                parent.spawn((
132                    Node {
133                        border: px(4.).all(),
134                        padding: px(4.).all(),
135                        overflow: Overflow::clip_x(),
136                        overflow_clip_margin: OverflowClipMargin {
137                            visual_box: VisualBox::ContentBox,
138                            ..default()
139                        },
140                        ..default()
141                    },
142                    BackgroundColor(bevy::color::palettes::css::DARK_SLATE_BLUE.into()),
143                    BorderColor::all(Color::WHITE),
144                    children![(
145                        Text::default(),
146                        TextLayout::no_wrap(),
147                        font.clone(),
148                        BackgroundColor(bevy::color::palettes::css::DARK_SLATE_GRAY.into()),
149                        BorderColor::all(Color::WHITE),
150                        TextInputRow(row),
151                        TextOutput,
152                    )],
153                ));
154
155                parent.spawn((
156                    Node {
157                        border: px(4.).all(),
158                        padding: px(4.).all(),
159                        overflow: Overflow::clip_x(),
160                        overflow_clip_margin: OverflowClipMargin {
161                            visual_box: VisualBox::ContentBox,
162                            ..default()
163                        },
164
165                        ..default()
166                    },
167                    BackgroundColor(bevy::color::palettes::css::DARK_SLATE_BLUE.into()),
168                    BorderColor::all(Color::WHITE),
169                    children![(
170                        Text::default(),
171                        TextLayout::no_wrap(),
172                        font.clone(),
173                        TextInputRow(row),
174                        SubmitOutput,
175                    )],
176                ));
177            }
178
179            let label_font = font.clone().with_font_size(14.);
180            for label in ["ReadWrite", "EditableText", "value", "submission"] {
181                parent.spawn((
182                    Text::new(label),
183                    label_font.clone(),
184                    Node {
185                        justify_self: JustifySelf::Center,
186                        margin: px(-4).bottom(),
187                        ..default()
188                    },
189                ));
190            }
191
192            for (row, rwmode) in [
193                TextReadWriteMode::Editable,
194                TextReadWriteMode::ReadOnly,
195                TextReadWriteMode::Static,
196            ]
197            .into_iter()
198            .enumerate()
199            {
200                parent.spawn((
201                    Node {
202                        border: px(4).all(),
203                        justify_content: JustifyContent::Center,
204                        align_items: AlignItems::Center,
205                        ..default()
206                    },
207                    BorderColor::all(Color::WHITE),
208                    children![(Text::new(format!("{rwmode:?}")), font.clone(),)],
209                ));
210
211                let mut input = parent.spawn((
212                    Node {
213                        border: px(4.).all(),
214                        padding: px(4.).all(),
215                        ..default()
216                    },
217                    TextInput,
218                    EditableText::new(format!("Initial text {row}")),
219                    TextCursorStyle::default(),
220                    font.clone(),
221                    BackgroundColor(bevy::color::palettes::css::DARK_GREY.into()),
222                    TextInputRow(row + 100),
223                    rwmode,
224                    TabIndex(row as i32 + 100),
225                    BorderColor::all(SLATE_300),
226                ));
227                if row == 0 {
228                    input.insert(AutoFocus);
229                }
230
231                parent.spawn((
232                    Node {
233                        border: px(4.).all(),
234                        padding: px(4.).all(),
235                        overflow: Overflow::clip_x(),
236                        overflow_clip_margin: OverflowClipMargin {
237                            visual_box: VisualBox::ContentBox,
238                            ..default()
239                        },
240                        ..default()
241                    },
242                    BackgroundColor(bevy::color::palettes::css::DARK_SLATE_BLUE.into()),
243                    BorderColor::all(Color::WHITE),
244                    children![(
245                        Text::default(),
246                        TextLayout::no_wrap(),
247                        font.clone(),
248                        BackgroundColor(bevy::color::palettes::css::DARK_SLATE_GRAY.into()),
249                        BorderColor::all(Color::WHITE),
250                        TextInputRow(row + 100),
251                        TextOutput,
252                    )],
253                ));
254
255                parent.spawn((
256                    Node {
257                        border: px(4.).all(),
258                        padding: px(4.).all(),
259                        overflow: Overflow::clip_x(),
260                        overflow_clip_margin: OverflowClipMargin {
261                            visual_box: VisualBox::ContentBox,
262                            ..default()
263                        },
264
265                        ..default()
266                    },
267                    BackgroundColor(bevy::color::palettes::css::DARK_SLATE_BLUE.into()),
268                    BorderColor::all(Color::WHITE),
269                    children![(
270                        Text::default(),
271                        TextLayout::no_wrap(),
272                        font.clone(),
273                        TextInputRow(row + 100),
274                        SubmitOutput,
275                    )],
276                ));
277            }
278
279            parent.spawn((
280                Text::new("Press Enter to submit"),
281                Node {
282                    grid_column: GridPlacement::span(4),
283                    justify_self: JustifySelf::Center,
284                    margin: px(16).top(),
285                    ..default()
286                },
287                font.clone(),
288            ));
289        });
290}
Source

pub fn percent<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T

Create a repeating set of grid tracks with a percentage size

Source

pub fn em<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T

Create a repeating set of grid tracks with size as a multiple of the grid containers’s font size.

Source

pub fn rem<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T

Create a repeating set of grid tracks with size as a multiple of the root font size.

Source

pub fn auto<T>(repetition: u16) -> T

Create a repeating set of grid tracks with automatic size

Examples found in repository?
examples/ui/scroll_and_overflow/scroll.rs (line 349)
324fn bidirectional_scrolling_list_with_sticky(font_handle: Handle<Font>) -> impl Bundle {
325    (
326        Node {
327            flex_direction: FlexDirection::Column,
328            justify_content: JustifyContent::Center,
329            align_items: AlignItems::Center,
330            width: px(200),
331            ..default()
332        },
333        children![
334            (
335                Text::new("Bidirectionally Scrolling List With Sticky Nodes"),
336                TextFont {
337                    font: font_handle.clone().into(),
338                    font_size: FONT_SIZE,
339                    ..default()
340                },
341                Label,
342            ),
343            (
344                Node {
345                    display: Display::Grid,
346                    align_self: AlignSelf::Stretch,
347                    height: percent(50),
348                    overflow: Overflow::scroll(), // n.b.
349                    grid_template_columns: RepeatedGridTrack::auto(30),
350                    ..default()
351                },
352                Children::spawn(SpawnIter(
353                    (0..30)
354                        .flat_map(|y| (0..30).map(move |x| (y, x)))
355                        .map(move |(y, x)| {
356                            let value = font_handle.clone();
357                            // Simple sticky nodes at top and left sides of UI node
358                            // can be achieved by combining such effects as
359                            // IgnoreScroll, ZIndex, BackgroundColor for child UI nodes.
360                            let ignore_scroll = BVec2 {
361                                x: x == 0,
362                                y: y == 0,
363                            };
364                            let (z_index, background_color, role) = match (x == 0, y == 0) {
365                                (true, true) => (2, RED, Role::RowHeader),
366                                (true, false) => (1, BLUE, Role::RowHeader),
367                                (false, true) => (1, BLUE, Role::ColumnHeader),
368                                (false, false) => (0, BLACK, Role::Cell),
369                            };
370                            (
371                                Text(format!("|{},{}|", y, x)),
372                                TextFont::from(value.clone()),
373                                TextLayout {
374                                    linebreak: LineBreak::NoWrap,
375                                    ..default()
376                                },
377                                Label,
378                                AccessibilityNode(Accessible::new(role)),
379                                IgnoreScroll(ignore_scroll),
380                                ZIndex(z_index),
381                                BackgroundColor(Color::Srgba(background_color)),
382                            )
383                        })
384                ))
385            )
386        ],
387    )
388}
More examples
Hide additional examples
examples/ui/scroll_and_overflow/scrollbars.rs (line 58)
51fn scroll_area_demo() -> impl Bundle {
52    (
53        // Frame element which contains the scroll area and scrollbars.
54        Node {
55            display: Display::Grid,
56            width: px(200),
57            height: px(150),
58            grid_template_columns: vec![RepeatedGridTrack::flex(1, 1.), RepeatedGridTrack::auto(1)],
59            grid_template_rows: vec![RepeatedGridTrack::flex(1, 1.), RepeatedGridTrack::auto(1)],
60            row_gap: px(2),
61            column_gap: px(2),
62            ..default()
63        },
64        Children::spawn((SpawnWith(|parent: &mut RelatedSpawner<ChildOf>| {
65            // The actual scrolling area.
66            // Note that we're using `SpawnWith` here because we need to get the entity id of the
67            // scroll area in order to set the target of the scrollbars.
68            let scroll_area_id = parent
69                .spawn((
70                    Node {
71                        display: Display::Flex,
72                        flex_direction: FlexDirection::Column,
73                        padding: UiRect::all(px(4)),
74                        overflow: Overflow::scroll(),
75                        ..default()
76                    },
77                    BackgroundColor(colors::GRAY1.into()),
78                    ScrollPosition(Vec2::new(0.0, 10.0)),
79                    Children::spawn((
80                        // The actual content of the scrolling area
81                        Spawn(text_row("Alpha Wolf")),
82                        Spawn(text_row("Beta Blocker")),
83                        Spawn(text_row("Delta Sleep")),
84                        Spawn(text_row("Gamma Ray")),
85                        Spawn(text_row("Epsilon Eridani")),
86                        Spawn(text_row("Zeta Function")),
87                        Spawn(text_row("Lambda Calculus")),
88                        Spawn(text_row("Nu Metal")),
89                        Spawn(text_row("Pi Day")),
90                        Spawn(text_row("Chi Pants")),
91                        Spawn(text_row("Psi Powers")),
92                        Spawn(text_row("Omega Fatty Acid")),
93                    )),
94                ))
95                .id();
96
97            // Vertical scrollbar
98            parent.spawn((
99                Node {
100                    min_width: px(8),
101                    grid_row: GridPlacement::start(1),
102                    grid_column: GridPlacement::start(2),
103                    ..default()
104                },
105                Scrollbar {
106                    orientation: ControlOrientation::Vertical,
107                    target: scroll_area_id,
108                    min_thumb_length: 8.0,
109                },
110                Children::spawn(Spawn((
111                    Hovered::default(),
112                    BackgroundColor(colors::GRAY2.into()),
113                    BorderColor::all(colors::GRAY3),
114                    ScrollbarThumb {
115                        border_radius: BorderRadius::all(px(4)),
116                        border: px(1).all(),
117                    },
118                ))),
119            ));
120
121            // Horizontal scrollbar
122            parent.spawn((
123                Node {
124                    min_height: px(8),
125                    grid_row: GridPlacement::start(2),
126                    grid_column: GridPlacement::start(1),
127                    ..default()
128                },
129                Scrollbar {
130                    orientation: ControlOrientation::Horizontal,
131                    target: scroll_area_id,
132                    min_thumb_length: 8.0,
133                },
134                Children::spawn(Spawn((
135                    Hovered::default(),
136                    BackgroundColor(colors::GRAY2.into()),
137                    BorderColor::all(colors::GRAY3),
138                    ScrollbarThumb {
139                        border_radius: BorderRadius::all(px(4)),
140                        border: px(1).all(),
141                    },
142                ))),
143            ));
144        }),)),
145    )
146}
examples/ui/text/multiline_text_input.rs (line 82)
55fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
56    commands.spawn(Camera2d);
57
58    commands
59        .spawn(Node {
60            width: percent(100.),
61            height: percent(100.),
62            justify_content: JustifyContent::Center,
63            align_items: AlignItems::Center,
64            ..default()
65        })
66        .with_children(|parent| {
67            parent
68                .spawn((
69                    Node {
70                        flex_direction: FlexDirection::Column,
71                        align_items: AlignItems::End,
72                        row_gap: px(10.),
73                        ..default()
74                    },
75                    TabGroup::default(),
76                ))
77                .with_children(|parent| {
78                    parent
79                        .spawn(Node {
80                            display: Display::Grid,
81                            grid_template_columns: vec![
82                                RepeatedGridTrack::auto(1),
83                                RepeatedGridTrack::auto(1),
84                            ],
85                            column_gap: px(4.),
86                            ..default()
87                        })
88                        .with_children(|parent| {
89                            parent
90                                .spawn((
91                                    Node {
92                                        width: px(450.),
93                                        border: px(2.).all(),
94                                        padding: px(8.).all(),
95                                        ..default()
96                                    },
97                                    TextInput,
98                                    EditableText {
99                                        visible_lines: Some(8.),
100                                        allow_newlines: true,
101                                        ..default()
102                                    },
103                                    TextLayout {
104                                        linebreak: LineBreak::WordOrCharacter,
105                                        ..default()
106                                    },
107                                    TextCursorStyle {
108                                        color: Color::WHITE,
109                                        selected_text_color: Some(Color::BLACK),
110                                        ..default()
111                                    },
112                                    TextFont {
113                                        font: asset_server.load("fonts/FiraMono-Medium.ttf").into(),
114                                        font_size: FontSize::Px(30.),
115                                        ..default()
116                                    },
117                                    BackgroundColor(DARK_SLATE_GRAY.into()),
118                                    BorderColor::all(SLATE_300),
119                                    MultilineInput,
120                                    TabIndex(0),
121                                    AutoFocus,
122                                ))
123                                .observe(
124                                    |on: On<FocusedInput<KeyboardInput>>,
125                                     keys: Res<ButtonInput<Key>>,
126                                     input_query: Query<&EditableText, With<MultilineInput>>| {
127                                        if !(on.input.state.is_pressed()
128                                            && on.input.logical_key == Key::Enter
129                                            && keys.pressed(Key::Control))
130                                        {
131                                            return;
132                                        }
133                                        let Ok(input) = input_query.get(on.focused_entity) else {
134                                            return;
135                                        };
136
137                                        let mut output = String::new();
138                                        output
139                                            .reserve(input.value().into_iter().map(str::len).sum());
140                                        for sub_str in input.value() {
141                                            output.push_str(sub_str);
142                                        }
143
144                                        info!("{output}");
145                                    },
146                                );
147
148                            // Vertical scrollbar for the multiline input above. Not part of the
149                            // input's tab group and has no `TabIndex`, so it's unreachable via
150                            // Tab navigation and can't take input focus.
151                            parent
152                                .spawn((
153                                    Node {
154                                        min_width: px(10.),
155                                        ..default()
156                                    },
157                                    BackgroundColor(DARK_SLATE_GRAY.into()),
158                                ))
159                                .with_children(|parent| {
160                                    parent
161                                        .spawn((
162                                            Node {
163                                                position_type: PositionType::Absolute,
164                                                width: percent(100.),
165                                                left: px(0.),
166                                                border_radius: BorderRadius::all(px(4.)),
167                                                ..default()
168                                            },
169                                            BackgroundColor(SLATE_300.into()),
170                                            Visibility::Hidden,
171                                            InputScrollThumb,
172                                            InputScrollDragState::default(),
173                                        ))
174                                        .observe(on_thumb_drag_start)
175                                        .observe(on_thumb_drag)
176                                        .observe(on_thumb_drag_end);
177                                });
178                        });
179
180                    parent
181                        .spawn((
182                            Node {
183                                flex_direction: FlexDirection::Row,
184                                column_gap: px(10.),
185                                ..default()
186                            },
187                            children![
188                                (
189                                    Text::new("visible lines:"),
190                                    TextFont {
191                                        font: asset_server.load("fonts/FiraMono-Medium.ttf").into(),
192                                        font_size: FontSize::Px(30.),
193                                        ..default()
194                                    },
195                                ),
196                                (
197                                    Node {
198                                        width: px(100.),
199                                        border: px(2.).all(),
200                                        ..default()
201                                    },
202                                    TextFont {
203                                        font: asset_server.load("fonts/FiraMono-Medium.ttf").into(),
204                                        font_size: FontSize::Px(30.),
205                                        ..default()
206                                    },
207                                    TextLayout {
208                                        justify: Justify::End,
209                                        ..default()
210                                    },
211                                    BackgroundColor(DARK_SLATE_GRAY.into()),
212                                    BorderColor::all(SLATE_300),
213                                    TextInput,
214                                    EditableText::new("8"),
215                                    EditableTextFilter::new(|c| c.is_ascii_digit() || c == '.'),
216                                    TextCursorStyle {
217                                        color: Color::WHITE,
218                                        selected_text_color: Some(Color::BLACK),
219                                        unfocused_selection_color: Color::NONE,
220                                        ..default()
221                                    },
222                                    SelectAllOnFocus,
223                                    VisibleLinesInput,
224                                    TabIndex(1),
225                                )
226                            ],
227                        ))
228                        .observe(
229                            |on: On<FocusedInput<KeyboardInput>>,
230                             mut query_set: ParamSet<(
231                                Query<&EditableText, With<VisibleLinesInput>>,
232                                Query<&mut EditableText, With<MultilineInput>>,
233                            )>| {
234                                if !(on.input.state.is_pressed()
235                                    && on.input.logical_key == Key::Enter)
236                                {
237                                    return;
238                                }
239
240                                let visible_lines_query = query_set.p0();
241                                let Ok(input) = visible_lines_query.get(on.original_event_target())
242                                else {
243                                    return;
244                                };
245
246                                let mut output = String::new();
247                                output.reserve(input.value().into_iter().map(str::len).sum());
248                                for sub_str in input.value() {
249                                    output.push_str(sub_str);
250                                }
251
252                                let Ok(lines) = output.parse::<f32>() else {
253                                    return;
254                                };
255
256                                let mut multiline_query = query_set.p1();
257                                let Ok(mut multiline_input) = multiline_query.single_mut() else {
258                                    return;
259                                };
260
261                                multiline_input.visible_lines = Some(lines.clamp(1., 10.));
262                            },
263                        );
264
265                    parent
266                        .spawn((
267                            Node {
268                                flex_direction: FlexDirection::Row,
269                                column_gap: px(10.),
270                                ..default()
271                            },
272                            children![
273                                (
274                                    Text::new("font size:"),
275                                    TextFont {
276                                        font: asset_server.load("fonts/FiraMono-Medium.ttf").into(),
277                                        font_size: FontSize::Px(30.),
278                                        ..default()
279                                    },
280                                ),
281                                (
282                                    Node {
283                                        width: px(100.),
284                                        border: px(2.).all(),
285                                        ..default()
286                                    },
287                                    TextFont {
288                                        font: asset_server.load("fonts/FiraMono-Medium.ttf").into(),
289                                        font_size: FontSize::Px(30.),
290                                        ..default()
291                                    },
292                                    TextLayout {
293                                        justify: Justify::End,
294                                        ..default()
295                                    },
296                                    BackgroundColor(DARK_SLATE_GRAY.into()),
297                                    BorderColor::all(SLATE_300),
298                                    TextInput,
299                                    EditableText::new("30"),
300                                    EditableTextFilter::new(|c| c.is_ascii_digit()),
301                                    TextCursorStyle {
302                                        color: Color::WHITE,
303                                        selected_text_color: Some(Color::BLACK),
304                                        unfocused_selection_color: Color::NONE,
305                                        ..default()
306                                    },
307                                    SelectAllOnFocus,
308                                    FontSizeInput,
309                                    TabIndex(2),
310                                )
311                            ],
312                        ))
313                        .observe(
314                            |on: On<FocusedInput<KeyboardInput>>,
315                             font_size_input_query: Query<&EditableText, With<FontSizeInput>>,
316                             mut multiline_input_font: Single<
317                                &mut TextFont,
318                                With<MultilineInput>,
319                            >| {
320                                if !(on.input.state.is_pressed()
321                                    && on.input.logical_key == Key::Enter)
322                                {
323                                    return;
324                                }
325
326                                let Ok(input) =
327                                    font_size_input_query.get(on.original_event_target())
328                                else {
329                                    return;
330                                };
331
332                                let mut output = String::new();
333                                output.reserve(input.value().into_iter().map(str::len).sum());
334                                for sub_str in input.value() {
335                                    output.push_str(sub_str);
336                                }
337
338                                let Ok(font_size) = output.parse::<f32>() else {
339                                    return;
340                                };
341
342                                multiline_input_font.font_size =
343                                    FontSize::Px(font_size.clamp(5., 50.));
344                            },
345                        );
346
347                    parent
348                        .spawn((
349                            Node {
350                                flex_direction: FlexDirection::Row,
351                                column_gap: px(10.),
352                                ..default()
353                            },
354                            children![
355                                (
356                                    Text::new("corner radius:"),
357                                    TextFont {
358                                        font: asset_server.load("fonts/FiraMono-Medium.ttf").into(),
359                                        font_size: FontSize::Px(30.),
360                                        ..default()
361                                    },
362                                ),
363                                (
364                                    Node {
365                                        width: px(100.),
366                                        border: px(2.).all(),
367                                        ..default()
368                                    },
369                                    TextFont {
370                                        font: asset_server.load("fonts/FiraMono-Medium.ttf").into(),
371                                        font_size: FontSize::Px(30.),
372                                        ..default()
373                                    },
374                                    TextLayout {
375                                        justify: Justify::End,
376                                        ..default()
377                                    },
378                                    BackgroundColor(DARK_SLATE_GRAY.into()),
379                                    BorderColor::all(SLATE_300),
380                                    TextInput,
381                                    EditableText::new("0"),
382                                    EditableTextFilter::new(|c| c.is_ascii_digit() || c == '.'),
383                                    TextCursorStyle {
384                                        color: Color::WHITE,
385                                        selected_text_color: Some(Color::BLACK),
386                                        ..default()
387                                    },
388                                    SelectionRadiusInput,
389                                    TabIndex(2),
390                                )
391                            ],
392                        ))
393                        .observe(
394                            |on: On<FocusedInput<KeyboardInput>>,
395                             radius_input_query: Query<
396                                &EditableText,
397                                With<SelectionRadiusInput>,
398                            >,
399                             mut cursor_style: Single<
400                                &mut TextCursorStyle,
401                                With<MultilineInput>,
402                            >| {
403                                if !(on.input.state.is_pressed()
404                                    && on.input.logical_key == Key::Enter)
405                                {
406                                    return;
407                                }
408
409                                let Ok(input) = radius_input_query.get(on.original_event_target())
410                                else {
411                                    return;
412                                };
413
414                                let mut output = String::new();
415                                output.reserve(input.value().into_iter().map(str::len).sum());
416                                for sub_str in input.value() {
417                                    output.push_str(sub_str);
418                                }
419
420                                let Ok(radius) = output.parse::<f32>() else {
421                                    return;
422                                };
423
424                                cursor_style.selection_radius = radius.clamp(0., 0.5);
425                            },
426                        );
427
428                    parent
429                        .spawn(Node::default())
430                        .observe(
431                            |on: On<MenuEvent>,
432                             mut popup: Single<
433                                (&mut Node, &mut MenuFocusState),
434                                With<MenuPopup>,
435                            >,
436                             button: Single<Entity, With<MenuButton>>,
437                             mut focus: ResMut<InputFocus>| {
438                                match on.action {
439                                    MenuAction::Open(direction) => {
440                                        popup.0.display = Display::Flex;
441                                        *popup.1 = MenuFocusState::Opening(direction);
442                                    }
443                                    MenuAction::Toggle => {
444                                        if popup.0.display == Display::None {
445                                            popup.0.display = Display::Flex;
446                                            *popup.1 = MenuFocusState::Opening(
447                                                bevy::input_focus::tab_navigation::NavAction::First,
448                                            );
449                                        } else {
450                                            popup.0.display = Display::None;
451                                        }
452                                    }
453                                    MenuAction::CloseAll => {
454                                        popup.0.display = Display::None;
455                                    }
456                                    MenuAction::FocusRoot => {
457                                        focus.set(*button, FocusCause::Navigated);
458                                    }
459                                }
460                            },
461                        )
462                        .with_children(|parent| {
463                            parent.spawn((
464                                Node {
465                                    border: px(2.).all(),
466                                    padding: px(8.).horizontal(),
467                                    ..default()
468                                },
469                                Button,
470                                MenuButton,
471                                TabIndex(4),
472                                BackgroundColor(DARK_SLATE_GRAY.into()),
473                                BorderColor::all(SLATE_300),
474                                children![(
475                                    Text::new("Justify::Left"),
476                                    TextFont {
477                                        font: asset_server.load("fonts/FiraMono-Medium.ttf").into(),
478                                        font_size: FontSize::Px(24.),
479                                        ..default()
480                                    },
481                                    JustifyLabel,
482                                )],
483                            ));
484
485                            parent
486                                .spawn((
487                                    Node {
488                                        display: Display::None,
489                                        flex_direction: FlexDirection::Column,
490                                        min_width: percent(100.),
491                                        border: px(2.).all(),
492                                        position_type: PositionType::Absolute,
493                                        ..default()
494                                    },
495                                    MenuPopup::default(),
496                                    Popover {
497                                        positions: vec![PopoverPlacement {
498                                            side: PopoverSide::Top,
499                                            align: PopoverAlign::End,
500                                            gap: 2.,
501                                        }],
502                                        ..default()
503                                    },
504                                    GlobalZIndex(1),
505                                    BackgroundColor(DARK_SLATE_GRAY.into()),
506                                    BorderColor::all(SLATE_300),
507                                ))
508                                .with_children(|parent| {
509                                    for (label, justify) in [
510                                        ("Justify::Left", Justify::Left),
511                                        ("Justify::Center", Justify::Center),
512                                        ("Justify::Right", Justify::Right),
513                                        ("Justify::Justified", Justify::Justified),
514                                        ("Justify::Start", Justify::Start),
515                                        ("Justify::End", Justify::End),
516                                    ] {
517                                        parent
518                                            .spawn((
519                                                Node {
520                                                    padding: px(8.).horizontal(),
521                                                    ..default()
522                                                },
523                                                MenuItem,
524                                                TabIndex(0),
525                                                children![(
526                                                    Text::new(label),
527                                                    TextFont {
528                                                        font: asset_server
529                                                            .load("fonts/FiraMono-Medium.ttf",)
530                                                            .into(),
531                                                        font_size: FontSize::Px(24.),
532                                                        ..default()
533                                                    },
534                                                )],
535                                            ))
536                                            .observe(
537                                                move |_: On<Activate>,
538                                                      mut layout: Single<
539                                                    &mut TextLayout,
540                                                    With<MultilineInput>,
541                                                >,
542                                                      mut selected: Single<
543                                                    &mut Text,
544                                                    With<JustifyLabel>,
545                                                >| {
546                                                    layout.justify = justify;
547                                                    selected.0 = label.into();
548                                                },
549                                            );
550                                    }
551                                });
552                        });
553                });
554        });
555}
Source

pub fn fr<T>(repetition: u16, value: f32) -> T

Create a repeating set of grid tracks with an fr size. Note that this will give the track a content-based minimum size. Usually you are best off using GridTrack::flex instead which uses a zero minimum size.

Examples found in repository?
examples/testbed/ui.rs (line 2094)
2085    pub fn setup(mut commands: Commands) {
2086        commands.spawn((Camera2d, DespawnOnExit(super::Scene::LayoutRounding)));
2087
2088        commands
2089            .spawn((
2090                Node {
2091                    display: Display::Grid,
2092                    width: percent(100),
2093                    height: percent(100),
2094                    grid_template_rows: vec![RepeatedGridTrack::fr(10, 1.)],
2095                    ..Default::default()
2096                },
2097                BackgroundColor(Color::WHITE),
2098                DespawnOnExit(super::Scene::LayoutRounding),
2099            ))
2100            .with_children(|commands| {
2101                for i in 2..12 {
2102                    commands
2103                        .spawn(Node {
2104                            display: Display::Grid,
2105                            grid_template_columns: vec![RepeatedGridTrack::fr(i, 1.)],
2106                            ..Default::default()
2107                        })
2108                        .with_children(|commands| {
2109                            for _ in 0..i {
2110                                commands.spawn((
2111                                    Node {
2112                                        border: UiRect::all(px(5)),
2113                                        ..Default::default()
2114                                    },
2115                                    BackgroundColor(MAROON.into()),
2116                                    BorderColor::all(DARK_BLUE),
2117                                ));
2118                            }
2119                        });
2120                }
2121            });
2122    }
More examples
Hide additional examples
examples/ui/text/generic_font_families.rs (line 40)
33fn setup(mut commands: Commands, mut font_system: ResMut<FontCx>) {
34    // UI camera
35    commands.spawn(Camera2d);
36
37    commands
38        .spawn((Node {
39            display: Display::Grid,
40            grid_template_columns: vec![RepeatedGridTrack::fr(3, 1.)],
41            margin: UiRect::AUTO,
42            row_gap: px(25),
43            column_gap: px(15),
44            ..Default::default()
45        },))
46        .with_children(|builder| {
47            builder.spawn((
48                Node {
49                    justify_self: JustifySelf::Center,
50                    grid_column: GridPlacement::span(3),
51                    margin: UiRect::bottom(px(15)),
52                    ..default()
53                },
54                Text::new("Generic Font Families"),
55                TextFont::from_font_size(FONT_SIZE),
56                Underline,
57            ));
58
59            let outline = Outline {
60                color: ZINC_600.into(),
61                width: px(2.),
62                offset: px(4.),
63            };
64
65            for (source, description) in [
66                (FontSource::sans_serif(), "generic sans serif font"),
67                (FontSource::serif(), "generic serif font"),
68                (FontSource::fantasy(), "generic fantasy font"),
69                (FontSource::cursive(), "generic cursive font"),
70                (FontSource::monospace(), "generic monospace font"),
71            ] {
72                builder.spawn((
73                    Text::new(description),
74                    TextFont::from(source.clone()).with_font_size(FONT_SIZE),
75                    TextColor(WHEAT.into()),
76                    TextLayout::justify(Justify::Center),
77                    outline,
78                ));
79
80                builder.spawn((
81                    Text::new(format!("FontSource::{source:?}")),
82                    TextFont::from_font_size(FONT_SIZE),
83                    TextColor(YELLOW.into()),
84                    TextLayout::justify(Justify::Center),
85                    outline,
86                ));
87
88                // Get the family name for the `FontSource` from `FontCx`.
89                // `get_family` only returns `None` for `FontSource::Handle`.
90                let family_name = font_system.get_family(&source).unwrap();
91                builder.spawn((
92                    Text::new(family_name),
93                    TextFont::from_font_size(FONT_SIZE),
94                    TextLayout::justify(Justify::Center),
95                    outline,
96                ));
97            }
98        });
99}
examples/ui/layout/anchor_layout.rs (line 107)
19fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
20    let font = asset_server.load("fonts/FiraSans-Bold.ttf");
21    commands.spawn(Camera2d);
22
23    let rows = [
24        (
25            "left: 10px\ntop: 10px",
26            Node {
27                left: px(10),
28                top: px(10),
29                ..default()
30            },
31        ),
32        (
33            "center: 10px\ntop: 10px",
34            Node {
35                margin: auto().horizontal(),
36                top: px(10),
37                ..default()
38            },
39        ),
40        (
41            "right: 10px\ntop: 10px",
42            Node {
43                right: px(10),
44                top: px(10),
45                ..default()
46            },
47        ),
48        (
49            "left: 10px\ncenter: 10px",
50            Node {
51                left: px(10),
52                margin: UiRect::vertical(auto()),
53                ..default()
54            },
55        ),
56        (
57            "center: 10px\ncenter: 10px",
58            Node {
59                margin: UiRect::all(auto()),
60                ..default()
61            },
62        ),
63        (
64            "right: 10px\ncenter: 10px",
65            Node {
66                right: px(10),
67                margin: UiRect::vertical(auto()),
68                ..default()
69            },
70        ),
71        (
72            "left: 10px\nbottom: 10px",
73            Node {
74                left: px(10),
75                bottom: px(10),
76                ..default()
77            },
78        ),
79        (
80            "center: 10px\nbottom: 10px",
81            Node {
82                margin: UiRect::horizontal(auto()),
83                bottom: px(10),
84                ..default()
85            },
86        ),
87        (
88            "right: 10px\nbottom: 10px",
89            Node {
90                right: px(10),
91                bottom: px(10),
92                ..default()
93            },
94        ),
95    ];
96
97    // let font = font.clone();
98    commands.spawn((
99        Node {
100            // fill the entire window
101            width: percent(100),
102            height: percent(100),
103            padding: MARGIN.all(),
104            row_gap: MARGIN,
105            column_gap: MARGIN,
106            display: Display::Grid,
107            grid_template_columns: RepeatedGridTrack::fr(3, 1.),
108            grid_template_rows: RepeatedGridTrack::fr(3, 1.),
109            ..default()
110        },
111        BackgroundColor(Color::BLACK),
112        Children::spawn(SpawnIter(
113            rows.into_iter()
114                .map(move |v| anchored_node(font.clone(), v.1, v.0)),
115        )),
116    ));
117}
Source

pub fn flex<T>(repetition: u16, value: f32) -> T

Create a repeating set of grid tracks with a minmax(0, Nfr) size.

Examples found in repository?
examples/stress_tests/many_buttons.rs (line 240)
213fn setup_grid(mut commands: Commands, asset_server: Res<AssetServer>, args: Res<Args>) {
214    let images = if 0 < args.image_freq {
215        Some(vec![
216            asset_server.load("branding/icon.png"),
217            asset_server.load("textures/Game Icons/wrench.png"),
218        ])
219    } else {
220        None
221    };
222
223    let buttons_f = args.buttons as f32;
224    let border = if args.no_borders {
225        UiRect::ZERO
226    } else {
227        UiRect::all(vmin(0.05 * 90. / buttons_f))
228    };
229
230    let as_rainbow = |i: usize| Color::hsl((i as f32 / buttons_f) * 360.0, 0.9, 0.8);
231    commands
232        .spawn(Node {
233            display: if args.display_none {
234                Display::None
235            } else {
236                Display::Grid
237            },
238            width: percent(100),
239            height: percent(100),
240            grid_template_columns: RepeatedGridTrack::flex(args.buttons as u16, 1.0),
241            grid_template_rows: RepeatedGridTrack::flex(args.buttons as u16, 1.0),
242            ..default()
243        })
244        .with_children(|commands| {
245            for column in 0..args.buttons {
246                for row in 0..args.buttons {
247                    let color = as_rainbow(row % column.max(1));
248                    let border_color = Color::WHITE.with_alpha(0.5).into();
249                    spawn_button(
250                        commands,
251                        color,
252                        buttons_f,
253                        column,
254                        row,
255                        args.text,
256                        border,
257                        border_color,
258                        images.as_ref().map(|images| {
259                            images[((column + row) / args.image_freq) % images.len()].clone()
260                        }),
261                        args.overflow_clip,
262                    );
263                }
264            }
265        });
266}
More examples
Hide additional examples
examples/stress_tests/many_gradients.rs (line 97)
84fn setup(mut commands: Commands, args: Res<Args>) {
85    warn!(include_str!("warning_string.txt"));
86
87    commands.spawn(Camera2d);
88
89    let rows_to_spawn = args.gradient_count.div_ceil(COLS);
90
91    // Create a grid of gradients
92    commands
93        .spawn(Node {
94            width: percent(100),
95            height: percent(100),
96            display: Display::Grid,
97            grid_template_columns: RepeatedGridTrack::flex(COLS as u16, 1.0),
98            grid_template_rows: RepeatedGridTrack::flex(rows_to_spawn as u16, 1.0),
99            ..default()
100        })
101        .with_children(|parent| {
102            for i in 0..args.gradient_count {
103                let angle = (i as f32 * 10.0) % 360.0;
104
105                let mut gradient = LinearGradient::new(
106                    angle,
107                    vec![
108                        ColorStop::new(RED, percent(0)),
109                        ColorStop::new(BLUE, percent(100)),
110                        ColorStop::new(GREEN, percent(20)),
111                        ColorStop::new(YELLOW, percent(40)),
112                        ColorStop::new(ORANGE, percent(60)),
113                        ColorStop::new(LIME, percent(80)),
114                        ColorStop::new(DARK_CYAN, percent(90)),
115                    ],
116                );
117
118                gradient.color_space = if args.srgb {
119                    InterpolationColorSpace::Srgba
120                } else if args.hsl {
121                    InterpolationColorSpace::Hsla
122                } else {
123                    InterpolationColorSpace::Oklaba
124                };
125
126                parent.spawn((
127                    Node {
128                        width: percent(100),
129                        height: percent(100),
130                        ..default()
131                    },
132                    BackgroundGradient(vec![Gradient::Linear(gradient)]),
133                    GradientNode { index: i },
134                ));
135            }
136        });
137}
examples/testbed/ui.rs (line 1170)
1135    pub fn setup(mut commands: Commands) {
1136        commands.spawn((Camera2d, DespawnOnExit(super::Scene::Grid)));
1137        // Top-level grid (app frame)
1138        commands.spawn((
1139            Node {
1140                display: Display::Grid,
1141                width: percent(100),
1142                height: percent(100),
1143                grid_template_columns: vec![GridTrack::min_content(), GridTrack::flex(1.0)],
1144                grid_template_rows: vec![
1145                    GridTrack::auto(),
1146                    GridTrack::flex(1.0),
1147                    GridTrack::px(40.),
1148                ],
1149                ..default()
1150            },
1151            BackgroundColor(Color::WHITE),
1152            DespawnOnExit(super::Scene::Grid),
1153            children![
1154                // Header
1155                (
1156                    Node {
1157                        display: Display::Grid,
1158                        grid_column: GridPlacement::span(2),
1159                        padding: UiRect::all(px(40)),
1160                        ..default()
1161                    },
1162                    BackgroundColor(RED.into()),
1163                ),
1164                // Main content grid (auto placed in row 2, column 1)
1165                (
1166                    Node {
1167                        height: percent(100),
1168                        aspect_ratio: Some(1.0),
1169                        display: Display::Grid,
1170                        grid_template_columns: RepeatedGridTrack::flex(3, 1.0),
1171                        grid_template_rows: RepeatedGridTrack::flex(2, 1.0),
1172                        row_gap: px(12),
1173                        column_gap: px(12),
1174                        ..default()
1175                    },
1176                    BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
1177                    children![
1178                        (Node::default(), BackgroundColor(ORANGE.into())),
1179                        (Node::default(), BackgroundColor(BISQUE.into())),
1180                        (Node::default(), BackgroundColor(BLUE.into())),
1181                        (Node::default(), BackgroundColor(CRIMSON.into())),
1182                        (Node::default(), BackgroundColor(AQUA.into())),
1183                    ]
1184                ),
1185                // Right side bar (auto placed in row 2, column 2)
1186                (Node::DEFAULT, BackgroundColor(BLACK.into())),
1187            ],
1188        ));
1189    }
examples/ui/scroll_and_overflow/scrollbars.rs (line 58)
51fn scroll_area_demo() -> impl Bundle {
52    (
53        // Frame element which contains the scroll area and scrollbars.
54        Node {
55            display: Display::Grid,
56            width: px(200),
57            height: px(150),
58            grid_template_columns: vec![RepeatedGridTrack::flex(1, 1.), RepeatedGridTrack::auto(1)],
59            grid_template_rows: vec![RepeatedGridTrack::flex(1, 1.), RepeatedGridTrack::auto(1)],
60            row_gap: px(2),
61            column_gap: px(2),
62            ..default()
63        },
64        Children::spawn((SpawnWith(|parent: &mut RelatedSpawner<ChildOf>| {
65            // The actual scrolling area.
66            // Note that we're using `SpawnWith` here because we need to get the entity id of the
67            // scroll area in order to set the target of the scrollbars.
68            let scroll_area_id = parent
69                .spawn((
70                    Node {
71                        display: Display::Flex,
72                        flex_direction: FlexDirection::Column,
73                        padding: UiRect::all(px(4)),
74                        overflow: Overflow::scroll(),
75                        ..default()
76                    },
77                    BackgroundColor(colors::GRAY1.into()),
78                    ScrollPosition(Vec2::new(0.0, 10.0)),
79                    Children::spawn((
80                        // The actual content of the scrolling area
81                        Spawn(text_row("Alpha Wolf")),
82                        Spawn(text_row("Beta Blocker")),
83                        Spawn(text_row("Delta Sleep")),
84                        Spawn(text_row("Gamma Ray")),
85                        Spawn(text_row("Epsilon Eridani")),
86                        Spawn(text_row("Zeta Function")),
87                        Spawn(text_row("Lambda Calculus")),
88                        Spawn(text_row("Nu Metal")),
89                        Spawn(text_row("Pi Day")),
90                        Spawn(text_row("Chi Pants")),
91                        Spawn(text_row("Psi Powers")),
92                        Spawn(text_row("Omega Fatty Acid")),
93                    )),
94                ))
95                .id();
96
97            // Vertical scrollbar
98            parent.spawn((
99                Node {
100                    min_width: px(8),
101                    grid_row: GridPlacement::start(1),
102                    grid_column: GridPlacement::start(2),
103                    ..default()
104                },
105                Scrollbar {
106                    orientation: ControlOrientation::Vertical,
107                    target: scroll_area_id,
108                    min_thumb_length: 8.0,
109                },
110                Children::spawn(Spawn((
111                    Hovered::default(),
112                    BackgroundColor(colors::GRAY2.into()),
113                    BorderColor::all(colors::GRAY3),
114                    ScrollbarThumb {
115                        border_radius: BorderRadius::all(px(4)),
116                        border: px(1).all(),
117                    },
118                ))),
119            ));
120
121            // Horizontal scrollbar
122            parent.spawn((
123                Node {
124                    min_height: px(8),
125                    grid_row: GridPlacement::start(2),
126                    grid_column: GridPlacement::start(1),
127                    ..default()
128                },
129                Scrollbar {
130                    orientation: ControlOrientation::Horizontal,
131                    target: scroll_area_id,
132                    min_thumb_length: 8.0,
133                },
134                Children::spawn(Spawn((
135                    Hovered::default(),
136                    BackgroundColor(colors::GRAY2.into()),
137                    BorderColor::all(colors::GRAY3),
138                    ScrollbarThumb {
139                        border_radius: BorderRadius::all(px(4)),
140                        border: px(1).all(),
141                    },
142                ))),
143            ));
144        }),)),
145    )
146}
examples/stress_tests/many_text.rs (line 102)
97fn setup_text(mut commands: Commands, asset_server: Res<AssetServer>) {
98    commands
99        .spawn((
100            Node {
101                display: Display::Grid,
102                grid_template_columns: RepeatedGridTrack::flex(4, 1.0),
103                width: percent(100),
104                height: percent(100),
105                column_gap: px(2.),
106                ..default()
107            },
108            ManyTextRoot,
109        ))
110        .with_children(|parent| {
111            for font_path in [
112                "fonts/EBGaramond12-Regular.otf",
113                "fonts/FiraMono-Medium.ttf",
114                "fonts/FiraSans-Bold.ttf",
115                "fonts/MonaSans-VariableFont.ttf",
116            ] {
117                let font = asset_server.load(font_path);
118                let text_font = TextFont {
119                    font: font.into(),
120                    font_size: px(10).into(),
121                    ..default()
122                };
123                parent
124                    .spawn((
125                        Node {
126                            flex_direction: FlexDirection::Column,
127                            border: px(1.).all(),
128                            padding: px(1.).all(),
129                            row_gap: px(2.),
130                            ..default()
131                        },
132                        BorderColor::all(Color::WHITE),
133                    ))
134                    .with_children(|parent| {
135                        parent.spawn((Text(font_path.to_string()), text_font.clone()));
136                        for justify in [
137                            Justify::Left,
138                            Justify::Center,
139                            Justify::Right,
140                            Justify::Justified,
141                        ] {
142                            for linebreak in [LineBreak::AnyCharacter, LineBreak::WordBoundary] {
143                                parent.spawn((
144                                    Text(format!("Justify::{justify:?}, LineBreak::{linebreak:?}")),
145                                    text_font.clone(),
146                                    TextColor::from(bevy::color::palettes::css::YELLOW),
147                                ));
148                                let layout = TextLayout { justify, linebreak };
149                                parent.spawn((
150                                    Text::new(LOREM_TEXT_1),
151                                    Lorem(false),
152                                    layout,
153                                    text_font.clone().with_font_size(10.),
154                                    TextColor::from(bevy::color::palettes::css::NAVY),
155                                ));
156                                parent.spawn((
157                                    Text::new(LOREM_TEXT_2),
158                                    Lorem(true),
159                                    layout,
160                                    text_font.clone().with_font_size(11.),
161                                    TextColor::from(bevy::color::palettes::css::PALE_GREEN),
162                                ));
163                            }
164                        }
165
166                        parent
167                            .spawn((
168                                Text::new(LOREM_TEXT_1),
169                                Lorem(false),
170                                text_font.clone().with_font_size(12.),
171                                TextColor::from(bevy::color::palettes::css::MISTY_ROSE),
172                            ))
173                            .with_child((TextSpan::new(" "), text_font.clone().with_font_size(13.)))
174                            .with_child((
175                                TextSpan::new(LOREM_TEXT_2),
176                                Lorem(true),
177                                text_font.clone().with_font_size(13.),
178                                TextColor::from(bevy::color::palettes::css::MAROON),
179                            ));
180
181                        parent
182                            .spawn((
183                                Text::default(),
184                                TextLayout::linebreak(LineBreak::AnyCharacter),
185                            ))
186                            .with_children(|parent| {
187                                for i in (0..10).cycle().take(100) {
188                                    parent.spawn((
189                                        TextSpan(i.to_string()),
190                                        text_font.clone().with_font_size((6 + i) as f32),
191                                        NumberSpan,
192                                    ));
193                                }
194                            });
195                    });
196            }
197        });
198}
examples/ui/layout/grid.rs (line 79)
18fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
19    let font = asset_server.load("fonts/FiraSans-Bold.ttf");
20    commands.spawn(Camera2d);
21
22    // Top-level grid (app frame)
23    commands
24        .spawn((
25            Node {
26                // Use the CSS Grid algorithm for laying out this node
27                display: Display::Grid,
28                // Make node fill the entirety of its parent (in this case the window)
29                width: percent(100),
30                height: percent(100),
31                // Set the grid to have 2 columns with sizes [min-content, minmax(0, 1fr)]
32                //   - The first column will size to the size of its contents
33                //   - The second column will take up the remaining available space
34                grid_template_columns: vec![GridTrack::min_content(), GridTrack::flex(1.0)],
35                // Set the grid to have 3 rows with sizes [auto, minmax(0, 1fr), 20px]
36                //  - The first row will size to the size of its contents
37                //  - The second row take up remaining available space (after rows 1 and 3 have both been sized)
38                //  - The third row will be exactly 20px high
39                grid_template_rows: vec![
40                    GridTrack::auto(),
41                    GridTrack::flex(1.0),
42                    GridTrack::px(20.),
43                ],
44                ..default()
45            },
46            BackgroundColor(Color::WHITE),
47        ))
48        .with_children(|builder| {
49            // Header
50            builder
51                .spawn(
52                    Node {
53                        display: Display::Grid,
54                        // Make this node span two grid columns so that it takes up the entire top tow
55                        grid_column: GridPlacement::span(2),
56                        padding: UiRect::all(px(6)),
57                        ..default()
58                    },
59                )
60                .with_children(|builder| {
61                    spawn_nested_text_bundle(builder, font.clone(), "Bevy CSS Grid Layout Example");
62                });
63
64            // Main content grid (auto placed in row 2, column 1)
65            builder
66                .spawn((
67                    Node {
68                        // Make the height of the node fill its parent
69                        height: percent(100),
70                        // Make the grid have a 1:1 aspect ratio meaning it will scale as an exact square
71                        // As the height is set explicitly, this means the width will adjust to match the height
72                        aspect_ratio: Some(1.0),
73                        // Use grid layout for this node
74                        display: Display::Grid,
75                        // Add 24px of padding around the grid
76                        padding: UiRect::all(px(24)),
77                        // Set the grid to have 4 columns all with sizes minmax(0, 1fr)
78                        // This creates 4 exactly evenly sized columns
79                        grid_template_columns: RepeatedGridTrack::flex(4, 1.0),
80                        // Set the grid to have 4 rows all with sizes minmax(0, 1fr)
81                        // This creates 4 exactly evenly sized rows
82                        grid_template_rows: RepeatedGridTrack::flex(4, 1.0),
83                        // Set a 12px gap/gutter between rows and columns
84                        row_gap: px(12),
85                        column_gap: px(12),
86                        ..default()
87                    },
88                    BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
89                ))
90                .with_children(|builder| {
91                    // Note there is no need to specify the position for each grid item. Grid items that are
92                    // not given an explicit position will be automatically positioned into the next available
93                    // grid cell. The order in which this is performed can be controlled using the grid_auto_flow
94                    // style property.
95
96                    item_rect(builder, ORANGE);
97                    item_rect(builder, BISQUE);
98                    item_rect(builder, BLUE);
99                    item_rect(builder, CRIMSON);
100                    item_rect(builder, AQUA);
101                    item_rect(builder, ORANGE_RED);
102                    item_rect(builder, DARK_GREEN);
103                    item_rect(builder, FUCHSIA);
104                    item_rect(builder, TEAL);
105                    item_rect(builder, ALICE_BLUE);
106                    item_rect(builder, CRIMSON);
107                    item_rect(builder, ANTIQUE_WHITE);
108                    item_rect(builder, YELLOW);
109                    item_rect(builder, DEEP_PINK);
110                    item_rect(builder, YELLOW_GREEN);
111                    item_rect(builder, SALMON);
112                });
113
114            // Right side bar (auto placed in row 2, column 2)
115            builder
116                .spawn((
117                    Node {
118                        display: Display::Grid,
119                        // Align content towards the start (top) in the vertical axis
120                        align_items: AlignItems::Start,
121                        // Align content towards the center in the horizontal axis
122                        justify_items: JustifyItems::Center,
123                        // Add 10px padding
124                        padding: UiRect::all(px(10)),
125                        // Add an fr track to take up all the available space at the bottom of the column so that the text nodes
126                        // can be top-aligned. Normally you'd use flexbox for this, but this is the CSS Grid example so we're using grid.
127                        grid_template_rows: vec![GridTrack::auto(), GridTrack::auto(), GridTrack::fr(1.0)],
128                        // Add a 10px gap between rows
129                        row_gap: px(10),
130                        ..default()
131                    },
132                    BackgroundColor(BLACK.into()),
133                ))
134                .with_children(|builder| {
135                    builder.spawn((Text::new("Sidebar"),
136                        TextFont::from(font.clone()),
137                    ));
138                    builder.spawn((Text::new("A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely."),
139                        TextFont {
140                            font: font.clone().into(),
141                            font_size: FontSize::Px(13.0),
142                            ..default()
143                        },
144                    ));
145                    builder.spawn(Node::default());
146                });
147
148            // Footer / status bar
149            builder.spawn((
150                Node {
151                    // Make this node span two grid column so that it takes up the entire bottom row
152                    grid_column: GridPlacement::span(2),
153                    ..default()
154                },
155                BackgroundColor(WHITE.into()),
156            ));
157
158            // Modal (absolutely positioned on top of content - currently hidden: to view it, change its visibility)
159            builder.spawn((
160                Node {
161                    position_type: PositionType::Absolute,
162                    margin: UiRect {
163                        top: px(100),
164                        bottom: auto(),
165                        left: auto(),
166                        right: auto(),
167                    },
168                    width: percent(60),
169                    height: px(300),
170                    max_width: px(600),
171                    ..default()
172                },
173                Visibility::Hidden,
174                BackgroundColor(Color::WHITE.with_alpha(0.8)),
175            ));
176        });
177}
Source

pub fn min_content<T>(repetition: u16) -> T

Create a repeating set of grid tracks with min-content size

Source

pub fn max_content<T>(repetition: u16) -> T

Create a repeating set of grid tracks with max-content size

Source

pub fn fit_content_px<T>(repetition: u16, limit: f32) -> T

Create a repeating set of fit-content() grid tracks with fixed pixel limit

Source

pub fn fit_content_percent<T>(repetition: u16, limit: f32) -> T

Create a repeating set of fit-content() grid tracks with percentage limit

Source

pub fn minmax<T>( repetition: impl Into<GridTrackRepetition>, min: MinTrackSizingFunction, max: MaxTrackSizingFunction, ) -> T

Create a repeating set of minmax() grid track

Source

pub fn vmin<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T

Create a repeating set of grid tracks with the percentage size of the viewport’s smaller dimension

Source

pub fn vmax<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T

Create a repeating set of grid tracks with the percentage size of the viewport’s larger dimension

Source

pub fn vh<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T

Create a repeating set of grid tracks with the percentage size of the viewport’s height dimension

Source

pub fn vw<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T

Create a repeating set of grid tracks with the percentage size of the viewport’s width dimension

Source

pub fn repeat_many<T>( repetition: impl Into<GridTrackRepetition>, tracks: impl Into<Vec<GridTrack>>, ) -> T

Create a repetition of a set of tracks

Trait Implementations§

Source§

impl Clone for RepeatedGridTrack

Source§

fn clone(&self) -> RepeatedGridTrack

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RepeatedGridTrack

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for RepeatedGridTrack

Source§

fn default() -> RepeatedGridTrack

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for RepeatedGridTrack

Source§

fn deserialize<__D>( __deserializer: __D, ) -> Result<RepeatedGridTrack, <__D as Deserializer<'de>>::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl From<GridTrack> for RepeatedGridTrack

Source§

fn from(track: GridTrack) -> RepeatedGridTrack

Converts to this type from the input type.
Source§

impl From<RepeatedGridTrack> for Vec<RepeatedGridTrack>

Source§

fn from(track: RepeatedGridTrack) -> Vec<RepeatedGridTrack>

Converts to this type from the input type.
Source§

impl FromArg for RepeatedGridTrack

Source§

type This<'from_arg> = RepeatedGridTrack

The type to convert into. Read more
Source§

fn from_arg( arg: Arg<'_>, ) -> Result<<RepeatedGridTrack as FromArg>::This<'_>, ArgError>

Creates an item from an argument. Read more
Source§

impl FromReflect for RepeatedGridTrack

Source§

fn from_reflect( reflect: &(dyn PartialReflect + 'static), ) -> Option<RepeatedGridTrack>

Constructs a concrete instance of Self from a reflected value.
Source§

fn take_from_reflect( reflect: Box<dyn PartialReflect>, ) -> Result<Self, Box<dyn PartialReflect>>

Attempts to downcast the given value to Self using, constructing the value using from_reflect if that fails. Read more
Source§

impl GetOwnership for RepeatedGridTrack

Source§

fn ownership() -> Ownership

Returns the ownership of Self.
Source§

impl GetTypeRegistration for RepeatedGridTrack

Source§

fn get_type_registration() -> TypeRegistration

Returns the default TypeRegistration for this type.
Source§

fn register_type_dependencies(registry: &mut TypeRegistry)

Registers other types needed by this type. Read more
Source§

impl IntoReturn for RepeatedGridTrack

Source§

fn into_return<'into_return>(self) -> Return<'into_return>
where RepeatedGridTrack: 'into_return,

Converts Self into a Return value.
Source§

impl PartialEq for RepeatedGridTrack

Source§

fn eq(&self, other: &RepeatedGridTrack) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl PartialReflect for RepeatedGridTrack

Source§

fn get_represented_type_info(&self) -> Option<&'static TypeInfo>

Returns the TypeInfo of the type represented by this value. Read more
Source§

fn try_apply( &mut self, value: &(dyn PartialReflect + 'static), ) -> Result<(), ApplyError>

Tries to apply a reflected value to this value. Read more
Source§

fn reflect_kind(&self) -> ReflectKind

Returns a zero-sized enumeration of “kinds” of type. Read more
Source§

fn reflect_ref(&self) -> ReflectRef<'_>

Returns an immutable enumeration of “kinds” of type. Read more
Source§

fn reflect_mut(&mut self) -> ReflectMut<'_>

Returns a mutable enumeration of “kinds” of type. Read more
Source§

fn reflect_owned(self: Box<RepeatedGridTrack>) -> ReflectOwned

Returns an owned enumeration of “kinds” of type. Read more
Source§

fn try_into_reflect( self: Box<RepeatedGridTrack>, ) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>

Attempts to cast this type to a boxed, fully-reflected value.
Source§

fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>

Attempts to cast this type to a fully-reflected value.
Source§

fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>

Attempts to cast this type to a mutable, fully-reflected value.
Source§

fn into_partial_reflect(self: Box<RepeatedGridTrack>) -> Box<dyn PartialReflect>

Casts this type to a boxed, reflected value. Read more
Source§

fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)

Casts this type to a reflected value. Read more
Source§

fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)

Casts this type to a mutable, reflected value. Read more
Source§

fn reflect_partial_eq( &self, value: &(dyn PartialReflect + 'static), ) -> Option<bool>

Returns a “partial equality” comparison result. Read more
Source§

fn reflect_partial_cmp( &self, value: &(dyn PartialReflect + 'static), ) -> Option<Ordering>

Returns a “partial comparison” result. Read more
Source§

fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>

Attempts to clone Self using reflection. Read more
Source§

fn apply(&mut self, value: &(dyn PartialReflect + 'static))

Applies a reflected value to this value. Read more
Source§

fn to_dynamic(&self) -> Result<Box<dyn PartialReflect>, ReflectCloneError>

Converts this reflected value into its dynamic representation based on its kind. Read more
Source§

fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
where T: 'static, Self: Sized + TypePath,

For a type implementing PartialReflect, combines reflect_clone and take in a useful fashion, automatically constructing an appropriate ReflectCloneError if the downcast fails.
Source§

fn reflect_hash(&self) -> Option<u64>

Returns a hash of the value (which includes the type). Read more
Source§

fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Debug formatter for the value. Read more
Source§

fn is_dynamic(&self) -> bool

Indicates whether or not this type is a dynamic type. Read more
Source§

impl Reflect for RepeatedGridTrack

Source§

fn into_any(self: Box<RepeatedGridTrack>) -> Box<dyn Any>

Returns the value as a Box<dyn Any>. Read more
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Returns the value as a &dyn Any. Read more
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Returns the value as a &mut dyn Any. Read more
Source§

fn into_reflect(self: Box<RepeatedGridTrack>) -> Box<dyn Reflect>

Casts this type to a boxed, fully-reflected value.
Source§

fn as_reflect(&self) -> &(dyn Reflect + 'static)

Casts this type to a fully-reflected value.
Source§

fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)

Casts this type to a mutable, fully-reflected value.
Source§

fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>

Performs a type-checked assignment of a reflected value to this value. Read more
Source§

impl Serialize for RepeatedGridTrack

Source§

fn serialize<__S>( &self, __serializer: __S, ) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Struct for RepeatedGridTrack

Source§

fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>

Gets a reference to the value of the field named name as a &dyn PartialReflect.
Source§

fn field_mut( &mut self, name: &str, ) -> Option<&mut (dyn PartialReflect + 'static)>

Gets a mutable reference to the value of the field named name as a &mut dyn PartialReflect.
Source§

fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>

Gets a reference to the value of the field with index index as a &dyn PartialReflect.
Source§

fn field_at_mut( &mut self, index: usize, ) -> Option<&mut (dyn PartialReflect + 'static)>

Gets a mutable reference to the value of the field with index index as a &mut dyn PartialReflect.
Source§

fn name_at(&self, index: usize) -> Option<&str>

Gets the name of the field with index index.
Source§

fn index_of_name(&self, name: &str) -> Option<usize>

Gets the index of the field with the given name.
Source§

fn field_len(&self) -> usize

Returns the number of fields in the struct.
Source§

fn iter_fields(&self) -> FieldIter<'_> ⓘ

Returns an iterator over the values of the reflectable fields for this struct.
Source§

fn to_dynamic_struct(&self) -> Result<DynamicStruct, ReflectCloneError>

Creates a new DynamicStruct from this struct. Read more
Source§

fn get_represented_struct_info(&self) -> Option<&'static StructInfo>

Will return None if TypeInfo is not available.
Source§

impl StructuralPartialEq for RepeatedGridTrack

Source§

impl TypePath for RepeatedGridTrack

Source§

fn type_path() -> &'static str

Returns the fully qualified path of the underlying type. Read more
Source§

fn short_type_path() -> &'static str

Returns a short, pretty-print enabled path to the type. Read more
Source§

fn type_ident() -> Option<&'static str>

Returns the name of the type, or None if it is anonymous. Read more
Source§

fn crate_name() -> Option<&'static str>

Returns the name of the crate the type is in, or None if it is anonymous. Read more
Source§

fn module_path() -> Option<&'static str>

Returns the path to the module the type is in, or None if it is anonymous. Read more
Source§

impl Typed for RepeatedGridTrack

Source§

fn type_info() -> &'static TypeInfo

Returns the compile-time info for the underlying type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

Source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Brush for T
where T: Clone + PartialEq + Default + Debug,

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> DynamicTypePath for T
where T: TypePath,

Source§

impl<T> DynamicTyped for T
where T: Typed,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> FromTemplate for T
where T: Clone + Default + Unpin,

Source§

type Template = T

The Template for this type.
Source§

impl<T> FromWorld for T
where T: Default,

Source§

fn from_world(_world: &mut World) -> T

Creates Self using default().

Source§

impl<S> GetField for S
where S: Struct,

Source§

fn get_field<T>(&self, name: &str) -> Option<&T>
where T: Reflect,

Gets a reference to the value of the field named name, downcast to T.
Source§

fn get_field_mut<T>(&mut self, name: &str) -> Option<&mut T>
where T: Reflect,

Gets a mutable reference to the value of the field named name, downcast to T.
Source§

impl<T> GetPath for T
where T: Reflect + ?Sized,

Source§

fn reflect_path<'p>( &self, path: impl ReflectPath<'p>, ) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>

Returns a reference to the value specified by path. Read more
Source§

fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>

Returns a mutable reference to the value specified by path. Read more
Source§

fn path<'p, T>( &self, path: impl ReflectPath<'p>, ) -> Result<&T, ReflectPathError<'p>>
where T: Reflect,

Returns a statically typed reference to the value specified by path. Read more
Source§

fn path_mut<'p, T>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut T, ReflectPathError<'p>>
where T: Reflect,

Returns a statically typed mutable reference to the value specified by path. Read more
Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> HitDataExtra for T
where T: Send + Sync + Debug + Any + 'static,

Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> InitializeFromFunction<T> for T

Source§

fn initialize_from_function(f: fn() -> T) -> T

Create an instance of this type from an initialization function
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<T> NoneValue for T
where T: Default,

Source§

type NoneType = T

Source§

fn null_value() -> T

The none-equivalent value.
Source§

impl<G> PatchFromTemplate for G
where G: FromTemplate,

Source§

type Template = <G as FromTemplate>::Template

The Template that will be patched.
Source§

fn patch<F>(func: F) -> TemplatePatch<F, <G as PatchFromTemplate>::Template>
where F: FnOnce(&mut <G as PatchFromTemplate>::Template, &mut ResolveContext<'_>),

Takes a “patch function” func, and turns it into a TemplatePatch.
Source§

impl<T> PatchTemplate for T
where T: Template,

Source§

fn patch_template<F>(func: F) -> TemplatePatch<F, T>
where F: FnOnce(&mut T, &mut ResolveContext<'_>),

Takes a “patch function” func that patches this Template, and turns it into a TemplatePatch.
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<R, P> ReadPrimitive<R> for P
where R: Read + ReadEndian<P>, P: Default,

Source§

fn read_from_little_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_little_endian().
Source§

fn read_from_big_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_big_endian().
Source§

fn read_from_native_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_native_endian().
Source§

impl<T> Reflectable for T

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<T> Settings for T
where T: 'static + Send + Sync,

Source§

impl<Ret> SpawnIfAsync<(), Ret> for Ret

Source§

fn spawn(self) -> Ret

Spawn the value into the dioxus runtime if it is an async block
Source§

impl<T, O> SuperFrom<T> for O
where O: From<T>,

Source§

fn super_from(input: T) -> O

Convert from a type to another type.
Source§

impl<T, O, M> SuperInto<O, M> for T
where O: SuperFrom<T, M>,

Source§

fn super_into(self) -> O

Convert from a type to another type.
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> Template for T
where T: Clone + Unpin,

Source§

type Output = T

The type of value produced by this Template.
Source§

fn build_template( &self, _context: &mut TemplateContext<'_, '_>, ) -> Result<<T as Template>::Output, BevyError>

Uses this template and the given entity context to produce a Template::Output.
Source§

fn clone_template(&self) -> T

Clones this template. See Clone.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

Source§

fn clone_type_data(&self) -> Box<dyn TypeData>

Creates a type-erased clone of self.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more