pub struct RepeatedGridTrack { /* private fields */ }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
u16count to repeat the track N times. - A
GridTrackRepetition::AutoFitorGridTrackRepetition::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
impl RepeatedGridTrack
Sourcepub fn px<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn px<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with a fixed pixel size
Examples found in repository?
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
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}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 }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}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}Sourcepub fn percent<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn percent<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with a percentage size
Sourcepub fn em<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn em<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with size as a multiple of the grid containers’s font size.
Sourcepub fn rem<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn rem<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with size as a multiple of the root font size.
Sourcepub fn auto<T>(repetition: u16) -> Twhere
T: From<RepeatedGridTrack>,
pub fn auto<T>(repetition: u16) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with automatic size
Examples found in repository?
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
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}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}Sourcepub fn fr<T>(repetition: u16, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn fr<T>(repetition: u16, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
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?
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
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}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}Sourcepub fn flex<T>(repetition: u16, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn flex<T>(repetition: u16, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with a minmax(0, Nfr) size.
Examples found in repository?
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
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}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 }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}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}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}Sourcepub fn min_content<T>(repetition: u16) -> Twhere
T: From<RepeatedGridTrack>,
pub fn min_content<T>(repetition: u16) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with min-content size
Sourcepub fn max_content<T>(repetition: u16) -> Twhere
T: From<RepeatedGridTrack>,
pub fn max_content<T>(repetition: u16) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with max-content size
Sourcepub fn fit_content_px<T>(repetition: u16, limit: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn fit_content_px<T>(repetition: u16, limit: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of fit-content() grid tracks with fixed pixel limit
Sourcepub fn fit_content_percent<T>(repetition: u16, limit: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn fit_content_percent<T>(repetition: u16, limit: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of fit-content() grid tracks with percentage limit
Sourcepub fn minmax<T>(
repetition: impl Into<GridTrackRepetition>,
min: MinTrackSizingFunction,
max: MaxTrackSizingFunction,
) -> Twhere
T: From<RepeatedGridTrack>,
pub fn minmax<T>(
repetition: impl Into<GridTrackRepetition>,
min: MinTrackSizingFunction,
max: MaxTrackSizingFunction,
) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of minmax() grid track
Sourcepub fn vmin<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn vmin<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with the percentage size of the viewport’s smaller dimension
Sourcepub fn vmax<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn vmax<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with the percentage size of the viewport’s larger dimension
Sourcepub fn vh<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn vh<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with the percentage size of the viewport’s height dimension
Sourcepub fn vw<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
pub fn vw<T>(repetition: impl Into<GridTrackRepetition>, value: f32) -> Twhere
T: From<RepeatedGridTrack>,
Create a repeating set of grid tracks with the percentage size of the viewport’s width dimension
Sourcepub fn repeat_many<T>(
repetition: impl Into<GridTrackRepetition>,
tracks: impl Into<Vec<GridTrack>>,
) -> Twhere
T: From<RepeatedGridTrack>,
pub fn repeat_many<T>(
repetition: impl Into<GridTrackRepetition>,
tracks: impl Into<Vec<GridTrack>>,
) -> Twhere
T: From<RepeatedGridTrack>,
Create a repetition of a set of tracks
Trait Implementations§
Source§impl Clone for RepeatedGridTrack
impl Clone for RepeatedGridTrack
Source§fn clone(&self) -> RepeatedGridTrack
fn clone(&self) -> RepeatedGridTrack
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for RepeatedGridTrack
impl Debug for RepeatedGridTrack
Source§impl Default for RepeatedGridTrack
impl Default for RepeatedGridTrack
Source§fn default() -> RepeatedGridTrack
fn default() -> RepeatedGridTrack
Source§impl<'de> Deserialize<'de> for RepeatedGridTrack
impl<'de> Deserialize<'de> for RepeatedGridTrack
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<RepeatedGridTrack, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<RepeatedGridTrack, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl From<GridTrack> for RepeatedGridTrack
impl From<GridTrack> for RepeatedGridTrack
Source§fn from(track: GridTrack) -> RepeatedGridTrack
fn from(track: GridTrack) -> RepeatedGridTrack
Source§impl From<RepeatedGridTrack> for Vec<RepeatedGridTrack>
impl From<RepeatedGridTrack> for Vec<RepeatedGridTrack>
Source§fn from(track: RepeatedGridTrack) -> Vec<RepeatedGridTrack>
fn from(track: RepeatedGridTrack) -> Vec<RepeatedGridTrack>
Source§impl FromArg for RepeatedGridTrack
impl FromArg for RepeatedGridTrack
Source§impl FromReflect for RepeatedGridTrack
impl FromReflect for RepeatedGridTrack
Source§fn from_reflect(
reflect: &(dyn PartialReflect + 'static),
) -> Option<RepeatedGridTrack>
fn from_reflect( reflect: &(dyn PartialReflect + 'static), ) -> Option<RepeatedGridTrack>
Self from a reflected value.Source§fn take_from_reflect(
reflect: Box<dyn PartialReflect>,
) -> Result<Self, Box<dyn PartialReflect>>
fn take_from_reflect( reflect: Box<dyn PartialReflect>, ) -> Result<Self, Box<dyn PartialReflect>>
Self using,
constructing the value using from_reflect if that fails. Read moreSource§impl GetOwnership for RepeatedGridTrack
impl GetOwnership for RepeatedGridTrack
Source§impl GetTypeRegistration for RepeatedGridTrack
impl GetTypeRegistration for RepeatedGridTrack
Source§fn get_type_registration() -> TypeRegistration
fn get_type_registration() -> TypeRegistration
TypeRegistration for this type.Source§fn register_type_dependencies(registry: &mut TypeRegistry)
fn register_type_dependencies(registry: &mut TypeRegistry)
Source§impl IntoReturn for RepeatedGridTrack
impl IntoReturn for RepeatedGridTrack
Source§fn into_return<'into_return>(self) -> Return<'into_return>where
RepeatedGridTrack: 'into_return,
fn into_return<'into_return>(self) -> Return<'into_return>where
RepeatedGridTrack: 'into_return,
Source§impl PartialEq for RepeatedGridTrack
impl PartialEq for RepeatedGridTrack
Source§impl PartialReflect for RepeatedGridTrack
impl PartialReflect for RepeatedGridTrack
Source§fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
Source§fn try_apply(
&mut self,
value: &(dyn PartialReflect + 'static),
) -> Result<(), ApplyError>
fn try_apply( &mut self, value: &(dyn PartialReflect + 'static), ) -> Result<(), ApplyError>
Source§fn reflect_kind(&self) -> ReflectKind
fn reflect_kind(&self) -> ReflectKind
Source§fn reflect_ref(&self) -> ReflectRef<'_>
fn reflect_ref(&self) -> ReflectRef<'_>
Source§fn reflect_mut(&mut self) -> ReflectMut<'_>
fn reflect_mut(&mut self) -> ReflectMut<'_>
Source§fn reflect_owned(self: Box<RepeatedGridTrack>) -> ReflectOwned
fn reflect_owned(self: Box<RepeatedGridTrack>) -> ReflectOwned
Source§fn try_into_reflect(
self: Box<RepeatedGridTrack>,
) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
fn try_into_reflect( self: Box<RepeatedGridTrack>, ) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
Source§fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
Source§fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
Source§fn into_partial_reflect(self: Box<RepeatedGridTrack>) -> Box<dyn PartialReflect>
fn into_partial_reflect(self: Box<RepeatedGridTrack>) -> Box<dyn PartialReflect>
Source§fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
Source§fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
Source§fn reflect_partial_eq(
&self,
value: &(dyn PartialReflect + 'static),
) -> Option<bool>
fn reflect_partial_eq( &self, value: &(dyn PartialReflect + 'static), ) -> Option<bool>
Source§fn reflect_partial_cmp(
&self,
value: &(dyn PartialReflect + 'static),
) -> Option<Ordering>
fn reflect_partial_cmp( &self, value: &(dyn PartialReflect + 'static), ) -> Option<Ordering>
Source§fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
Self using reflection. Read moreSource§fn apply(&mut self, value: &(dyn PartialReflect + 'static))
fn apply(&mut self, value: &(dyn PartialReflect + 'static))
Source§fn to_dynamic(&self) -> Result<Box<dyn PartialReflect>, ReflectCloneError>
fn to_dynamic(&self) -> Result<Box<dyn PartialReflect>, ReflectCloneError>
Source§fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
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>
fn reflect_hash(&self) -> Option<u64>
Source§fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
Source§fn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
Source§impl Reflect for RepeatedGridTrack
impl Reflect for RepeatedGridTrack
Source§fn into_any(self: Box<RepeatedGridTrack>) -> Box<dyn Any>
fn into_any(self: Box<RepeatedGridTrack>) -> Box<dyn Any>
Box<dyn Any>. Read moreSource§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut dyn Any. Read moreSource§fn into_reflect(self: Box<RepeatedGridTrack>) -> Box<dyn Reflect>
fn into_reflect(self: Box<RepeatedGridTrack>) -> Box<dyn Reflect>
Source§fn as_reflect(&self) -> &(dyn Reflect + 'static)
fn as_reflect(&self) -> &(dyn Reflect + 'static)
Source§fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
Source§impl Serialize for RepeatedGridTrack
impl Serialize for RepeatedGridTrack
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Source§impl Struct for RepeatedGridTrack
impl Struct for RepeatedGridTrack
Source§fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
name as a &dyn PartialReflect.Source§fn field_mut(
&mut self,
name: &str,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_mut( &mut self, name: &str, ) -> Option<&mut (dyn PartialReflect + 'static)>
name as a
&mut dyn PartialReflect.Source§fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
index as a
&dyn PartialReflect.Source§fn field_at_mut(
&mut self,
index: usize,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_at_mut( &mut self, index: usize, ) -> Option<&mut (dyn PartialReflect + 'static)>
index
as a &mut dyn PartialReflect.Source§fn index_of_name(&self, name: &str) -> Option<usize>
fn index_of_name(&self, name: &str) -> Option<usize>
Source§fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn iter_fields(&self) -> FieldIter<'_> ⓘ
Source§fn to_dynamic_struct(&self) -> Result<DynamicStruct, ReflectCloneError>
fn to_dynamic_struct(&self) -> Result<DynamicStruct, ReflectCloneError>
DynamicStruct from this struct. Read moreSource§fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
None if TypeInfo is not available.impl StructuralPartialEq for RepeatedGridTrack
Source§impl TypePath for RepeatedGridTrack
impl TypePath for RepeatedGridTrack
Source§fn type_path() -> &'static str
fn type_path() -> &'static str
Source§fn short_type_path() -> &'static str
fn short_type_path() -> &'static str
Source§fn type_ident() -> Option<&'static str>
fn type_ident() -> Option<&'static str>
Source§fn crate_name() -> Option<&'static str>
fn crate_name() -> Option<&'static str>
Auto Trait Implementations§
impl Freeze for RepeatedGridTrack
impl RefUnwindSafe for RepeatedGridTrack
impl Send for RepeatedGridTrack
impl Sync for RepeatedGridTrack
impl Unpin for RepeatedGridTrack
impl UnsafeUnpin for RepeatedGridTrack
impl UnwindSafe for RepeatedGridTrack
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T ShaderType for self. When used in AsBindGroup
derives, it is safe to assume that all images in self exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T> Brush for T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> ConditionalSend for Twhere
T: Send,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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 Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
Source§impl<T> DynamicTypePath for Twhere
T: TypePath,
impl<T> DynamicTypePath for Twhere
T: TypePath,
Source§fn reflect_type_path(&self) -> &str
fn reflect_type_path(&self) -> &str
TypePath::type_path.Source§fn reflect_short_type_path(&self) -> &str
fn reflect_short_type_path(&self) -> &str
Source§fn reflect_type_ident(&self) -> Option<&str>
fn reflect_type_ident(&self) -> Option<&str>
TypePath::type_ident.Source§fn reflect_crate_name(&self) -> Option<&str>
fn reflect_crate_name(&self) -> Option<&str>
TypePath::crate_name.Source§fn reflect_module_path(&self) -> Option<&str>
fn reflect_module_path(&self) -> Option<&str>
Source§impl<T> DynamicTyped for Twhere
T: Typed,
impl<T> DynamicTyped for Twhere
T: Typed,
Source§fn reflect_type_info(&self) -> &'static TypeInfo
fn reflect_type_info(&self) -> &'static TypeInfo
Typed::type_info.impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> FromTemplate for T
impl<T> FromTemplate for T
Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self using default().
Source§impl<S> GetField for Swhere
S: Struct,
impl<S> GetField for Swhere
S: Struct,
Source§impl<T> GetPath for T
impl<T> GetPath for T
Source§fn reflect_path<'p>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path<'p>( &self, path: impl ReflectPath<'p>, ) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
path. Read moreSource§fn reflect_path_mut<'p>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
path. Read moreSource§fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
path. Read moreSource§fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
path. Read moreSource§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T> HitDataExtra for T
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> InitializeFromFunction<T> for T
impl<T> InitializeFromFunction<T> for T
Source§fn initialize_from_function(f: fn() -> T) -> T
fn initialize_from_function(f: fn() -> T) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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 moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<G> PatchFromTemplate for Gwhere
G: FromTemplate,
impl<G> PatchFromTemplate for Gwhere
G: FromTemplate,
Source§fn patch<F>(func: F) -> TemplatePatch<F, <G as PatchFromTemplate>::Template>
fn patch<F>(func: F) -> TemplatePatch<F, <G as PatchFromTemplate>::Template>
func, and turns it into a TemplatePatch.Source§impl<T> PatchTemplate for Twhere
T: Template,
impl<T> PatchTemplate for Twhere
T: Template,
Source§fn patch_template<F>(func: F) -> TemplatePatch<F, T>
fn patch_template<F>(func: F) -> TemplatePatch<F, T>
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
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
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
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
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().impl<T> Reflectable for T
Source§impl<T> Serialize for T
impl<T> Serialize for T
fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>
fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>
impl<T> Settings for T
Source§impl<Ret> SpawnIfAsync<(), Ret> for Ret
impl<Ret> SpawnIfAsync<(), Ret> for Ret
Source§impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
Source§fn super_from(input: T) -> O
fn super_from(input: T) -> O
Source§impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
Source§fn super_into(self) -> O
fn super_into(self) -> O
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.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
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.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
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.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
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.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
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.Source§impl<T> Template for T
impl<T> Template for T
Source§fn build_template(
&self,
_context: &mut TemplateContext<'_, '_>,
) -> Result<<T as Template>::Output, BevyError>
fn build_template( &self, _context: &mut TemplateContext<'_, '_>, ) -> Result<<T as Template>::Output, BevyError>
entity context to produce a Template::Output.Source§fn clone_template(&self) -> T
fn clone_template(&self) -> T
Clone.Source§impl<T, U> ToSample<U> for Twhere
U: FromSample<T>,
impl<T, U> ToSample<U> for Twhere
U: FromSample<T>,
fn to_sample_(self) -> U
Source§impl<T> TypeData for T
impl<T> TypeData for T
Source§fn clone_type_data(&self) -> Box<dyn TypeData>
fn clone_type_data(&self) -> Box<dyn TypeData>
self.