-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathstress.rs
151 lines (124 loc) · 3.96 KB
/
stress.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// A stress test with thousands of animated 3D sprites
//
// CLI:
//
// Pass "2d" for 2D sprites (default)
// Pass "3d" for 3D sprites
//
// Pass --sprites X to render X sprites (default is 100 000)
//
// Best executed in --release mode!
#[path = "./common/mod.rs"]
pub mod common;
use bevy::prelude::*;
use bevy_spritesheet_animation::prelude::*;
use clap::{Parser, ValueEnum};
use common::random_position;
use iyes_perf_ui::prelude::*;
use rand::{seq::SliceRandom, Rng};
#[derive(ValueEnum, Clone)]
enum Mode {
#[clap(name = "2d")]
TwoD,
#[clap(name = "3d")]
ThreeD,
}
#[derive(Parser, Resource)]
struct Cli {
#[arg(value_enum, default_value_t=Mode::TwoD)]
mode: Mode,
#[arg(long, default_value_t = 100_000)]
sprites: usize,
}
fn main() {
let cli = Cli::parse();
App::new()
.add_plugins((
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin::default(),
bevy::diagnostic::FrameTimeDiagnosticsPlugin,
PerfUiPlugin,
))
.insert_resource(cli)
.add_systems(Startup, spawn_sprites)
.run();
}
fn spawn_sprites(
mut commands: Commands,
mut library: ResMut<AnimationLibrary>,
mut atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
cli: Res<Cli>,
assets: Res<AssetServer>,
) {
// Spawn a camera
match cli.mode {
Mode::TwoD => commands.spawn(Camera2d),
Mode::ThreeD => commands.spawn((
Camera3d::default(),
Transform::from_xyz(0.0, 1000.0, 4000.0).looking_at(Vec3::ZERO, Dir3::Y),
)),
};
// Create clips from a spritesheet
let spritesheet = Spritesheet::new(8, 8);
let clip_frames = [
spritesheet.row_partial(0, ..5),
spritesheet.row_partial(1, ..5),
spritesheet.row(2),
spritesheet.row(3),
spritesheet.row_partial(4, ..5),
spritesheet.row_partial(5, ..5),
spritesheet.row(6),
spritesheet.row(7),
];
let clip_ids = clip_frames.map(|frames| {
let clip = Clip::from_frames(frames);
library.register_clip(clip)
});
// Create 100 animations from those clips, each with random parameters
let mut rng = rand::thread_rng();
let animation_directions = [
AnimationDirection::Forwards,
AnimationDirection::Backwards,
AnimationDirection::PingPong,
];
let animation_ids: Vec<AnimationId> = (0..100)
.map(|_| {
let clip_id = clip_ids.choose(&mut rng).unwrap().clone();
let animation = Animation::from_clip(clip_id)
.with_duration(AnimationDuration::PerFrame(rng.gen_range(100..1000)))
.with_direction(animation_directions.choose(&mut rng).unwrap().clone());
library.register_animation(animation)
})
.collect();
// Spawn a lot of sprites, each with a random animation assigned
let image = assets.load("character.png");
let atlas = TextureAtlas {
layout: atlas_layouts.add(Spritesheet::new(8, 8).atlas_layout(96, 96)),
..default()
};
for _ in 0..cli.sprites {
let animation = animation_ids.choose(&mut rng).unwrap();
let transform = Transform::from_translation(random_position());
match cli.mode {
Mode::TwoD => commands.spawn((
Sprite::from_atlas_image(image.clone(), atlas.clone()),
SpritesheetAnimation::from_id(*animation),
transform,
)),
Mode::ThreeD => commands.spawn((
Sprite3d::from_atlas_image(image.clone(), atlas.clone()),
SpritesheetAnimation::from_id(*animation),
transform,
)),
};
}
// UI
commands.spawn((
PerfUiRoot {
// Set a fixed width to make all the bars line up
values_col_width: Some(160.0),
..Default::default()
},
PerfUiWidgetBar::new(PerfUiEntryFPS::default()),
));
}