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
//! Editor ECS schedule sets.
use bevy::prelude::{App, IntoScheduleConfigs, Startup, SystemSet, Update};
/// Ordered startup stages for editor entity construction.
#[derive(SystemSet, Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum EditorStartupSet {
/// Creates authoritative editor buffer entities.
Buffer,
/// Creates editor scene/view entities that consume buffers.
Scene,
/// Creates chrome and other UI entities.
Chrome,
}
/// Ordered dataflow stages for editor systems.
#[derive(SystemSet, Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum EditorSet {
/// Reads raw platform or Bevy input into editor-facing input state.
Input,
/// Interprets input as high-level editor or Vim intent.
Intent,
/// Runs plugin guests and drains plugin-proposed editor effects.
PluginIntent,
/// Applies edits and command side effects to authoritative domain state.
Edit,
/// Derives visible layout state from buffer, cursor, and viewport data.
Layout,
/// Converts layout into shaped text or glyph-facing presentation data.
Shape,
/// Synchronizes derived presentation data into Bevy render/UI entities.
Render,
}
/// Configures the ordered editor dataflow pipeline for the Bevy `Update` schedule.
pub fn configure_editor_sets(app: &mut App) {
let _app = app
.configure_sets(
Startup,
(
EditorStartupSet::Buffer,
EditorStartupSet::Scene.after(EditorStartupSet::Buffer),
EditorStartupSet::Chrome.after(EditorStartupSet::Scene),
),
)
.configure_sets(
Update,
(
EditorSet::Input,
EditorSet::Intent.after(EditorSet::Input),
EditorSet::PluginIntent.after(EditorSet::Intent),
EditorSet::Edit.after(EditorSet::PluginIntent),
EditorSet::Layout.after(EditorSet::Edit),
EditorSet::Shape.after(EditorSet::Layout),
EditorSet::Render.after(EditorSet::Shape),
),
);
}
#[cfg(test)]
mod tests {
use super::{EditorSet, configure_editor_sets};
use bevy::prelude::{App, IntoScheduleConfigs, ResMut, Resource, Update};
/// Execution order observed by the schedule-order regression test.
#[derive(Default, Resource)]
struct ObservedOrder {
/// Names pushed by systems as they run.
stages: Vec<&'static str>,
}
/// Records that the input stage ran.
fn input_stage(mut order: ResMut<ObservedOrder>) {
order.stages.push("input");
}
/// Records that the intent stage ran.
fn intent_stage(mut order: ResMut<ObservedOrder>) {
order.stages.push("intent");
}
/// Records that the edit stage ran.
fn edit_stage(mut order: ResMut<ObservedOrder>) {
order.stages.push("edit");
}
/// Records that the plugin intent stage ran.
fn plugin_intent_stage(mut order: ResMut<ObservedOrder>) {
order.stages.push("plugin_intent");
}
/// Records that the layout stage ran.
fn layout_stage(mut order: ResMut<ObservedOrder>) {
order.stages.push("layout");
}
/// Records that the shape stage ran.
fn shape_stage(mut order: ResMut<ObservedOrder>) {
order.stages.push("shape");
}
/// Records that the render stage ran.
fn render_stage(mut order: ResMut<ObservedOrder>) {
order.stages.push("render");
}
#[test]
fn editor_sets_run_in_dataflow_order() {
let mut app = App::new();
configure_editor_sets(&mut app);
let _app = app
.init_resource::<ObservedOrder>()
.add_systems(Update, input_stage.in_set(EditorSet::Input))
.add_systems(Update, intent_stage.in_set(EditorSet::Intent))
.add_systems(Update, plugin_intent_stage.in_set(EditorSet::PluginIntent))
.add_systems(Update, edit_stage.in_set(EditorSet::Edit))
.add_systems(Update, layout_stage.in_set(EditorSet::Layout))
.add_systems(Update, shape_stage.in_set(EditorSet::Shape))
.add_systems(Update, render_stage.in_set(EditorSet::Render));
app.update();
let order = app.world().resource::<ObservedOrder>();
assert_eq!(
order.stages,
[
"input",
"intent",
"plugin_intent",
"edit",
"layout",
"shape",
"render"
]
);
}
}