overflow_transform/
overflow_transform.rs1use bevy::color::palettes::css::LIGHT_BLUE;
4use bevy::color::palettes::css::NAVY;
5use bevy::math::ops::sin;
6use bevy::prelude::*;
7
8fn main() {
9 App::new()
10 .add_plugins(DefaultPlugins)
11 .add_systems(Startup, setup)
12 .add_systems(Update, (rotate_nodes, scale_inner))
13 .run();
14}
15
16#[derive(Component)]
17struct RotatingClipLayer {
18 base_rotation: f32,
19 speed: f32,
20}
21
22fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
23 commands.spawn(Camera2d);
24
25 commands
26 .spawn(Node {
27 width: percent(100),
28 height: percent(100),
29 align_items: AlignItems::Center,
30 justify_content: JustifyContent::Center,
31 ..default()
32 })
33 .with_children(|parent| {
34 parent
35 .spawn(rotating_node(
36 400.,
37 0.35,
38 0.18,
39 Color::srgb(0.12, 0.17, 0.22),
40 ))
41 .with_children(|parent| {
42 parent
43 .spawn(rotating_node(
44 350.,
45 -0.5,
46 -0.4,
47 Color::srgb(0.24, 0.18, 0.32),
48 ))
49 .with_children(|parent| {
50 parent
51 .spawn(rotating_node(
52 300.,
53 0.65,
54 0.55,
55 Color::srgb(0.15, 0.30, 0.25),
56 ))
57 .with_children(|parent| {
58 parent.spawn((
59 Node {
60 flex_direction: FlexDirection::Column,
61 position_type: PositionType::Absolute,
62 margin: auto().all(),
63 border_radius: BorderRadius::all(percent(20.)),
64 align_items: AlignItems::Center,
65 justify_content: JustifyContent::SpaceAround,
66 border: px(5.).all(),
67 padding: px(5.).all(),
68 ..default()
69 },
70 BoxShadow::new(
71 Color::srgb(0.15, 0.30, 0.25).darker(0.05),
72 px(30),
73 px(30),
74 px(0),
75 px(4),
76 ),
77 InnerNode,
78 BackgroundColor(NAVY.into()),
79 BorderColor::all(LIGHT_BLUE),
80 UiTransform::from_rotation(Rot2::degrees(45.)),
81 children![
82 (
83 ImageNode::new(
84 asset_server
85 .load("branding/bevy_logo_dark_big.png"),
86 ),
87 Node {
88 width: px(400),
89 ..default()
90 },
91 ),
92 (
93 Text::new("transform + overflow"),
94 TextFont {
95 font: asset_server
96 .load("fonts/FiraSans-Bold.ttf")
97 .into(),
98 font_size: FontSize::Px(34.),
99 ..default()
100 },
101 TextColor(Color::WHITE),
102 )
103 ],
104 ));
105 });
106 });
107 });
108 });
109}
110
111fn rotate_nodes(time: Res<Time>, mut query: Query<(&RotatingClipLayer, &mut UiTransform)>) {
112 for (layer, mut transform) in &mut query {
113 transform.rotation = Rot2::radians(layer.base_rotation + time.elapsed_secs() * layer.speed);
114 }
115}
116
117fn rotating_node(size: f32, rotation: f32, speed: f32, color: Color) -> impl Bundle {
118 (
119 Node {
120 width: px(size),
121 height: px(size),
122 overflow: Overflow::clip(),
123 align_items: AlignItems::Center,
124 justify_content: JustifyContent::Center,
125 border: UiRect::all(px(4)),
126 ..default()
127 },
128 BackgroundColor(color),
129 BorderColor::all(Color::WHITE.with_alpha(0.7)),
130 UiTransform::from_rotation(Rot2::radians(rotation)),
131 RotatingClipLayer {
132 base_rotation: rotation,
133 speed,
134 },
135 )
136}
137
138#[derive(Component)]
139struct InnerNode;
140
141fn scale_inner(time: Res<Time>, mut query: Query<&mut UiTransform, With<InnerNode>>) {
142 for mut transform in query.iter_mut() {
143 transform.scale = Vec2::splat(1. + 0.75 * sin(0.4 * time.elapsed_secs()));
144 }
145}