1use argh::FromArgs;
7use bevy::{
8 color::palettes::css::*,
9 diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
10 math::ops::sin,
11 prelude::*,
12 ui::{
13 BackgroundGradient, ColorStop, Display, Gradient, InterpolationColorSpace, LinearGradient,
14 RepeatedGridTrack,
15 },
16 window::{PresentMode, WindowResolution},
17 winit::WinitSettings,
18};
19
20const COLS: usize = 30;
21
22#[derive(FromArgs, Resource, Debug)]
23struct Args {
25 #[argh(option, default = "900")]
27 gradient_count: usize,
28
29 #[argh(switch)]
31 animate: bool,
32
33 #[argh(switch)]
35 srgb: bool,
36
37 #[argh(switch)]
39 hsl: bool,
40}
41
42fn main() {
43 #[cfg(not(target_arch = "wasm32"))]
45 let args: Args = argh::from_env();
46 #[cfg(target_arch = "wasm32")]
47 let args = Args::from_args(&[], &[]).unwrap();
48
49 let total_gradients = args.gradient_count;
50
51 println!("Gradient stress test with {total_gradients} gradients");
52 println!(
53 "Color space: {}",
54 if args.srgb {
55 "sRGB"
56 } else if args.hsl {
57 "HSL"
58 } else {
59 "OkLab (default)"
60 }
61 );
62
63 App::new()
64 .add_plugins((
65 LogDiagnosticsPlugin::default(),
66 FrameTimeDiagnosticsPlugin::default(),
67 DefaultPlugins.set(WindowPlugin {
68 primary_window: Some(Window {
69 title: "Gradient Stress Test".to_string(),
70 resolution: WindowResolution::new(1920, 1080).with_scale_factor_override(1.0),
71 present_mode: PresentMode::AutoNoVsync,
72 ..default()
73 }),
74 ..default()
75 }),
76 ))
77 .insert_resource(WinitSettings::continuous())
78 .insert_resource(args)
79 .add_systems(Startup, setup)
80 .add_systems(Update, animate_gradients)
81 .run();
82}
83
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 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}
138
139#[derive(Component)]
140struct GradientNode {
141 index: usize,
142}
143
144fn animate_gradients(
145 mut gradients: Query<(&mut BackgroundGradient, &GradientNode)>,
146 args: Res<Args>,
147 time: Res<Time>,
148) {
149 if !args.animate {
150 return;
151 }
152
153 let t = time.elapsed_secs();
154
155 for (mut bg_gradient, node) in &mut gradients {
156 let offset = node.index as f32 * 0.01;
157 let hue_shift = sin(t + offset) * 0.5 + 0.5;
158
159 if let Some(Gradient::Linear(gradient)) = bg_gradient.0.get_mut(0) {
160 let color1 = Color::hsl(hue_shift * 360.0, 1.0, 0.5);
161 let color2 = Color::hsl((hue_shift + 0.3) * 360.0 % 360.0, 1.0, 0.5);
162
163 gradient.stops = vec![
164 ColorStop::new(color1, percent(0)),
165 ColorStop::new(color2, percent(100)),
166 ColorStop::new(
167 Color::hsl((hue_shift + 0.1) * 360.0 % 360.0, 1.0, 0.5),
168 percent(20),
169 ),
170 ColorStop::new(
171 Color::hsl((hue_shift + 0.15) * 360.0 % 360.0, 1.0, 0.5),
172 percent(40),
173 ),
174 ColorStop::new(
175 Color::hsl((hue_shift + 0.2) * 360.0 % 360.0, 1.0, 0.5),
176 percent(60),
177 ),
178 ColorStop::new(
179 Color::hsl((hue_shift + 0.25) * 360.0 % 360.0, 1.0, 0.5),
180 percent(80),
181 ),
182 ColorStop::new(
183 Color::hsl((hue_shift + 0.28) * 360.0 % 360.0, 1.0, 0.5),
184 percent(90),
185 ),
186 ];
187 }
188 }
189}