Skip to content

Commit 45b8bde

Browse files
committed
Create a plugin that can be added to automatically dump all schedules.
1 parent 20147d5 commit 45b8bde

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

crates/bevy_dev_tools/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ webgl = ["bevy_render/webgl"]
1616
webgpu = ["bevy_render/webgpu"]
1717
schedule_data = [
1818
"dep:serde",
19+
"dep:ron",
1920
"dep:bevy_platform",
2021
"dep:bevy_utils",
2122
"dep:thiserror",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Tools for extracting schedule data from an app, and interpretting that data for use with
22
//! visualization tools (for example).
33
4+
pub mod plugin;
45
pub mod serde;
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//! Convenience plugin for automatically performing serialization of schedules on boot.
2+
use std::{fs::File, io::Write, path::PathBuf};
3+
4+
use bevy_app::{App, Main, Plugin};
5+
use bevy_ecs::{
6+
error::BevyError,
7+
intern::Interned,
8+
resource::Resource,
9+
schedule::{
10+
common_conditions::run_once, IntoScheduleConfigs, ScheduleLabel, Schedules, SystemSet,
11+
},
12+
world::World,
13+
};
14+
use ron::ser::PrettyConfig;
15+
16+
use crate::schedule_data::serde::AppData;
17+
18+
/// A plugin to automatically collect and write all schedule data on boot to a file that can later
19+
/// be parsed.
20+
pub struct SerializeSchedulesPlugin {
21+
/// The schedule that systems will be added to.
22+
///
23+
/// Usually, this will be set using [`Self::in_schedule`].
24+
pub schedule: Interned<dyn ScheduleLabel>,
25+
}
26+
27+
impl Default for SerializeSchedulesPlugin {
28+
fn default() -> Self {
29+
Self {
30+
schedule: Main.intern(),
31+
}
32+
}
33+
}
34+
35+
impl SerializeSchedulesPlugin {
36+
/// Creates an instance of [`Self`] that inserts into the specified schedule.
37+
pub fn in_schedule(label: impl ScheduleLabel) -> Self {
38+
Self {
39+
schedule: label.intern(),
40+
}
41+
}
42+
}
43+
44+
impl Plugin for SerializeSchedulesPlugin {
45+
fn build(&self, app: &mut App) {
46+
app.init_resource::<SerializeSchedulesFilePath>()
47+
.add_systems(
48+
Main,
49+
collect_system_data
50+
.run_if(run_once)
51+
.in_set(SerializeSchedulesSystems)
52+
.before(Main::run_main),
53+
);
54+
}
55+
}
56+
57+
/// A system set for allowing users to configure scheduling properties of systems in
58+
/// [`SerializeSchedulesPlugin`].
59+
#[derive(SystemSet, Hash, PartialEq, Eq, Debug, Clone)]
60+
pub struct SerializeSchedulesSystems;
61+
62+
/// The file path where schedules will be written to after collected by
63+
/// [`SerializeSchedulesPlugin`].
64+
#[derive(Resource)]
65+
pub struct SerializeSchedulesFilePath(pub PathBuf);
66+
67+
impl Default for SerializeSchedulesFilePath {
68+
fn default() -> Self {
69+
Self("app_data.ron".into())
70+
}
71+
}
72+
73+
fn collect_system_data(world: &mut World) -> Result<(), BevyError> {
74+
let schedules = world.resource::<Schedules>();
75+
let labels = schedules
76+
.iter()
77+
.map(|schedule| schedule.1.label())
78+
.collect::<Vec<_>>();
79+
for label in labels {
80+
let mut schedules = world.resource_mut::<Schedules>();
81+
let mut schedule = schedules.remove(label).unwrap();
82+
schedule.initialize(world)?;
83+
84+
let mut schedules = world.resource_mut::<Schedules>();
85+
schedules.insert(schedule);
86+
}
87+
88+
let schedules = world.resource::<Schedules>();
89+
let app_data = AppData::from_schedules(schedules, world.components())?;
90+
91+
let file_path = world
92+
.get_resource::<SerializeSchedulesFilePath>()
93+
.ok_or_else(|| "Missing SerializeSchedulesFilePath resource")?;
94+
let mut file = File::create(&file_path.0)?;
95+
// Use \n unconditionally so that Windows formatting is predictable.
96+
let serialized = ron::ser::to_string_pretty(&app_data, PrettyConfig::default().new_line("\n"))?;
97+
file.write_all(serialized.as_bytes())?;
98+
99+
Ok(())
100+
}

0 commit comments

Comments
 (0)