Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_scene/src/scene_list.rs
30635 views
1
use crate::{
2
ResolveContext, ResolveSceneError, ResolvedScene, Scene, SceneDependencies, SceneScope,
3
};
4
use variadics_please::all_tuples;
5
6
/// This behaves like a list of [`Scene`], where each entry in the list is a new entity (see [`Scene`] for more details).
7
///
8
/// [`Scene`] is to [`Entity`] as [`SceneList`] is to [`Vec<Entity>`].
9
///
10
/// [`Entity`]: bevy_ecs::entity::Entity
11
pub trait SceneList: SceneListBox {
12
/// This will apply the changes described in this [`SceneList`] to the given [`Vec<ResolvedScene>`]. This should not be called until all of
13
/// the dependencies in [`Scene::register_dependencies`] have been loaded.
14
fn resolve_list(
15
self,
16
context: &mut ResolveContext,
17
scenes: &mut Vec<ResolvedScene>,
18
) -> Result<(), ResolveSceneError>;
19
20
/// [`SceneList`] can have [`Asset`] dependencies, which _must_ be loaded before calling [`SceneList::resolve_list`] or it might return a
21
/// [`ResolveSceneError`]!
22
///
23
/// [`Asset`]: bevy_asset::Asset
24
fn register_dependencies(&self, dependencies: &mut SceneDependencies);
25
}
26
27
/// Boxed version of [`SceneList`], which enables implementing [`SceneList`] for [`Box<dyn SceneList>`].
28
/// Most developers do not need to think about or use this trait.
29
///
30
/// Related: [`SceneBox`].
31
///
32
/// ## Why does this exist?
33
///
34
/// [`SceneList::resolve_list`] consumes `self`, which by default is not something that
35
/// [`Box<dyn SceneList>`] can do in Rust, as `dyn Scene` is "unsized". The "way out" is to have
36
/// every [`Scene`] type _also_ know how to resolve itself for `self: Box<Self>`. [`SceneListBox`]
37
/// has a blanket impl for `SceneList + Sized` (which can just rely on the [`SceneList`] impl).
38
/// Then [`Box<dyn SceneList>`] has a manual [`SceneListBox`] impl that relies on the _stored_
39
/// [`SceneListBox::resolve_list_box`] impl.
40
///
41
/// [`SceneBox`]: crate::SceneBox
42
pub trait SceneListBox: Send + Sync + 'static {
43
/// See [`SceneList::resolve_list`].
44
fn resolve_list_box(
45
self: Box<Self>,
46
context: &mut ResolveContext,
47
scenes: &mut Vec<ResolvedScene>,
48
) -> Result<(), ResolveSceneError>;
49
50
/// See [`SceneList::register_dependencies`].
51
fn register_dependencies_box(&self, dependencies: &mut SceneDependencies);
52
}
53
54
impl<L: SceneList> SceneListBox for L {
55
#[inline]
56
fn resolve_list_box(
57
self: Box<Self>,
58
context: &mut ResolveContext,
59
scenes: &mut Vec<ResolvedScene>,
60
) -> Result<(), ResolveSceneError> {
61
(*self).resolve_list(context, scenes)
62
}
63
64
#[inline]
65
fn register_dependencies_box(&self, dependencies: &mut SceneDependencies) {
66
self.register_dependencies(dependencies);
67
}
68
}
69
70
impl<T: ?Sized + SceneListBox> SceneList for Box<T> {
71
fn resolve_list(
72
self,
73
context: &mut ResolveContext,
74
scenes: &mut Vec<ResolvedScene>,
75
) -> Result<(), ResolveSceneError> {
76
self.resolve_list_box(context, scenes)
77
}
78
79
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
80
(**self).register_dependencies_box(dependencies);
81
}
82
}
83
84
/// Corresponds to a single member of a [`SceneList`] (an [`Entity`] with an `S` [`Scene`]).
85
///
86
/// [`Entity`]: bevy_ecs::entity::Entity
87
pub struct EntityScene<S>(pub S);
88
89
impl<S: Scene> SceneList for EntityScene<S> {
90
fn resolve_list(
91
self,
92
context: &mut ResolveContext,
93
scenes: &mut Vec<ResolvedScene>,
94
) -> Result<(), ResolveSceneError> {
95
let mut resolved_scene = ResolvedScene::default();
96
self.0.resolve(context, &mut resolved_scene)?;
97
scenes.push(resolved_scene);
98
Ok(())
99
}
100
101
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
102
self.0.register_dependencies(dependencies);
103
}
104
}
105
106
macro_rules! scene_list_impl {
107
($($list: ident),*) => {
108
impl<$($list: SceneList),*> SceneList for ($($list,)*) {
109
fn resolve_list(self, _context: &mut ResolveContext, _scenes: &mut Vec<ResolvedScene>) -> Result<(), ResolveSceneError> {
110
#[expect(
111
clippy::allow_attributes,
112
reason = "This is inside a macro, and as such, may not trigger in all cases."
113
)]
114
#[allow(
115
non_snake_case,
116
reason = "The names of these variables are provided by the caller, not by us."
117
)]
118
let ($($list,)*) = self;
119
$($list.resolve_list(_context, _scenes)?;)*
120
Ok(())
121
}
122
123
fn register_dependencies(&self, _dependencies: &mut SceneDependencies) {
124
#[expect(
125
clippy::allow_attributes,
126
reason = "This is inside a macro, and as such, may not trigger in all cases."
127
)]
128
#[allow(
129
non_snake_case,
130
reason = "The names of these variables are provided by the caller, not by us."
131
)]
132
let ($($list,)*) = self;
133
$($list.register_dependencies(_dependencies);)*
134
}
135
}
136
}
137
}
138
139
all_tuples!(scene_list_impl, 0, 12, P);
140
141
impl<S: Scene> SceneList for Vec<S> {
142
fn resolve_list(
143
self,
144
context: &mut ResolveContext,
145
scenes: &mut Vec<ResolvedScene>,
146
) -> Result<(), ResolveSceneError> {
147
for scene in self {
148
let mut resolved_scene = ResolvedScene::default();
149
scene.resolve(context, &mut resolved_scene)?;
150
scenes.push(resolved_scene);
151
}
152
Ok(())
153
}
154
155
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
156
for scene in self {
157
scene.register_dependencies(dependencies);
158
}
159
}
160
}
161
162
impl SceneList for Vec<Box<dyn SceneList>> {
163
fn resolve_list(
164
self,
165
context: &mut ResolveContext,
166
scenes: &mut Vec<ResolvedScene>,
167
) -> Result<(), ResolveSceneError> {
168
for scene_list in self {
169
scene_list.resolve_list(context, scenes)?;
170
}
171
Ok(())
172
}
173
174
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
175
for scene_list in self {
176
scene_list.register_dependencies(dependencies);
177
}
178
}
179
}
180
181
impl<S: Scene> SceneList for SceneScope<S> {
182
fn resolve_list(
183
self,
184
context: &mut ResolveContext,
185
scenes: &mut Vec<ResolvedScene>,
186
) -> Result<(), ResolveSceneError> {
187
let mut resolved_scene = ResolvedScene::default();
188
self.resolve(context, &mut resolved_scene)?;
189
scenes.push(resolved_scene);
190
Ok(())
191
}
192
193
fn register_dependencies(&self, dependencies: &mut SceneDependencies) {
194
Scene::register_dependencies(self, dependencies);
195
}
196
}
197
198