Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/template.rs
30635 views
1
//! Functionality that relates to the [`Template`] trait.
2
3
use core::{hash::Hash, ops::Deref};
4
5
pub use bevy_ecs_macros::FromTemplate;
6
use bevy_platform::{collections::hash_map::RawEntryMut, hash::Hashed};
7
use bevy_utils::PreHashMap;
8
use indexmap::Equivalent;
9
10
use crate::{
11
component::Mutable,
12
entity::Entity,
13
error::{BevyError, Result},
14
resource::Resource,
15
world::{EntityWorldMut, Mut, World},
16
};
17
use alloc::vec::Vec;
18
use variadics_please::all_tuples;
19
20
/// A [`Template`] is something that, given a spawn context (target [`Entity`], [`World`], etc), can produce a [`Template::Output`].
21
///
22
/// [`Template`] is the cornerstone of scene systems. It enables define types (and hierarchies) that require no [`World`] or [`Entity`] context to define,
23
/// but can _use_ that context to produce the final runtime state. A [`Template`] is notably:
24
/// * **Repeatable**: Building a [`Template`] does not consume it. This enables reusing "baked" scenes / avoids rebuilding scenes each time we want to spawn one.
25
/// * **Clone-able**: Templates can be duplicated via [`Template::clone_template`], enabling scenes to be duplicated, supporting copy-on-write behaviors, etc.
26
/// * **(Often) Serializable**: Templates are intended to be easily serialized and deserialized, as they are typically composed of raw data.
27
///
28
/// Asset handles and [`Entity`] are two commonly [`Template`]-ed types. Asset handles are often "loaded" from an "asset path". The "asset path" would be the [`Template`].
29
/// Likewise [`Entity`] on its own has no reasonable default. A type with an [`Entity`] reference could use an "entity path" template to point to a specific entity, relative
30
/// to the current spawn context.
31
///
32
/// See [`FromTemplate`], which defines the canonical [`Template`] for a type. This can be derived, which will generate a [`Template`] for the deriving type.
33
pub trait Template {
34
/// The type of value produced by this [`Template`].
35
type Output;
36
37
/// Uses this template and the given `entity` context to produce a [`Template::Output`].
38
fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output>;
39
40
/// Clones this template. See [`Clone`].
41
fn clone_template(&self) -> Self;
42
}
43
44
/// The context used to apply the current [`Template`]. This contains a reference to the entity that the template is being
45
/// applied to (via an [`EntityWorldMut`]).
46
pub struct TemplateContext<'a, 'w> {
47
/// The current entity the template is being applied to
48
pub entity: &'a mut EntityWorldMut<'w>,
49
/// A mapping of [`SceneEntityReference`] to [`Entity`] used for resolving `#Name` entity references
50
pub entity_references: &'a mut SceneEntityReferences,
51
}
52
53
impl<'a, 'w> TemplateContext<'a, 'w> {
54
/// Creates a new [`TemplateContext`].
55
pub fn new(
56
entity: &'a mut EntityWorldMut<'w>,
57
entity_references: &'a mut SceneEntityReferences,
58
) -> Self {
59
Self {
60
entity,
61
entity_references,
62
}
63
}
64
/// Get the entity associated with the [`SceneEntityReference`], spawning a new one
65
/// if this is the first call with this index.
66
pub fn get_entity(&mut self, reference: SceneEntityReference) -> Entity {
67
self.entity_references.get(
68
reference,
69
// Safety: only used to create a new Entity
70
unsafe { self.entity.world_mut() },
71
)
72
}
73
74
/// Retrieves a reference to the given resource `R`.
75
#[inline]
76
pub fn resource<R: Resource>(&self) -> &R {
77
self.entity.resource()
78
}
79
80
/// Retrieves a mutable reference to the given resource `R`.
81
#[inline]
82
pub fn resource_mut<R: Resource<Mutability = Mutable>>(&mut self) -> Mut<'_, R> {
83
self.entity.resource_mut()
84
}
85
86
/// Retrieves the entity associated with the given resource `R`, if it exists.
87
#[inline]
88
pub fn resource_entity<R: Resource>(&self) -> Option<Entity> {
89
self.entity.resource_entity::<R>()
90
}
91
}
92
93
/// Struct to store a mapping from [`SceneEntityReference`] to [`Entity`]
94
/// which are used for resolving `#Name` entity references in bsn! macros
95
#[derive(Default)]
96
pub struct SceneEntityReferences(PreHashMap<InnerSceneEntityReference, Entity>);
97
98
impl SceneEntityReferences {
99
/// Get the [`Entity`] associated with this [`SceneEntityReference`]
100
/// If the index is unknown, spawn a new empty [`Entity`] and store it
101
pub fn get(&mut self, reference: SceneEntityReference, world: &mut World) -> Entity {
102
let inner = reference.0;
103
let entry = self
104
.0
105
.raw_entry_mut()
106
.from_key_hashed_nocheck(inner.hash(), &inner);
107
match entry {
108
RawEntryMut::Occupied(entry) => *entry.get(),
109
RawEntryMut::Vacant(view) => {
110
let entity = world.spawn_empty().id();
111
view.insert_hashed_nocheck(inner.hash(), inner, entity);
112
entity
113
}
114
}
115
}
116
117
/// Set the [`Entity`] associated with a [`SceneEntityReference`]
118
pub fn set(&mut self, reference: SceneEntityReference, entity: Entity) {
119
let inner = reference.0;
120
match self
121
.0
122
.raw_entry_mut()
123
.from_key_hashed_nocheck(inner.hash(), &inner)
124
{
125
RawEntryMut::Occupied(_) => {}
126
RawEntryMut::Vacant(view) => {
127
view.insert_hashed_nocheck(inner.hash(), inner, entity);
128
}
129
};
130
}
131
}
132
133
/// A unique reference for a named entity in a scene.
134
/// Usually used by `bevy_scene` in generated code
135
///
136
/// Hashed here should allow implementing compile-time hashing in the future, and
137
/// encourage constant-folding until then
138
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
139
pub struct SceneEntityReference(Hashed<InnerSceneEntityReference>);
140
141
/// The inner struct actually storing the unique index
142
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
143
pub struct InnerSceneEntityReference {
144
file: &'static str,
145
line: usize,
146
column: usize,
147
local: usize,
148
}
149
150
impl SceneEntityReference {
151
/// Create a new [`SceneEntityReference`] from the invocation location and a local (per-macro) counter for names
152
pub fn new((file, line, column): (&'static str, usize, usize), local: usize) -> Self {
153
Self(Hashed::new(InnerSceneEntityReference {
154
file,
155
line,
156
column,
157
local,
158
}))
159
}
160
}
161
162
impl core::fmt::Display for SceneEntityReference {
163
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
164
f.write_fmt(format_args!(
165
"global={}:{}:{} local={}",
166
self.file, self.line, self.column, self.local
167
))
168
}
169
}
170
171
impl Deref for SceneEntityReference {
172
type Target = Hashed<InnerSceneEntityReference>;
173
174
#[inline]
175
fn deref(&self) -> &Self::Target {
176
&self.0
177
}
178
}
179
180
impl Equivalent<Hashed<InnerSceneEntityReference>> for SceneEntityReference {
181
#[inline]
182
fn equivalent(&self, key: &Hashed<InnerSceneEntityReference>) -> bool {
183
&self.0 == key
184
}
185
}
186
187
/// [`FromTemplate`] is implemented for types that can be produced by a specific, canonical [`Template`]. This creates a way to correlate to the [`Template`] using the
188
/// desired template output type. This is used by Bevy's scene system.
189
///
190
/// Both [`FromTemplate`] and [`Template`] are blanket implemented for types that implement [`Default`] and [`Clone`], meaning most types you would want to use
191
/// _already have templates_.
192
///
193
/// It is best to think of [`FromTemplate`] as an alternative to [`Default`] for types that require world/spawn context to instantiate. Note that because of the blanket
194
/// impl, you cannot implement [`FromTemplate`], [`Default`], and [`Clone`] together on the same type, as it would result in two conflicting [`FromTemplate`] impls.
195
/// This is also why [`Template`] has its own [`Template::clone_template`] method (to avoid using the [`Clone`] impl, which would pull in the auto-impl).
196
///
197
/// You can _and should_ prefer deriving [`Default`] and [`Clone`] instead of an explicit [`FromTemplate`] impl, unless your type uses something that requires (or uses)
198
/// a [`Template`]. Handles in an asset system or [`Entity`] are examples of "templated" types. If you want your type to support templates of them, you probably want
199
/// to derive [`FromTemplate`].
200
///
201
/// [`FromTemplate`] can be derived for types whose fields _also_ implement [`FromTemplate`]:
202
/// ```
203
/// # use bevy_ecs::prelude::*;
204
/// # #[derive(Default, Clone)]
205
/// # struct Handle<T>(core::marker::PhantomData<T>);
206
/// # #[derive(Default, Clone)]
207
/// # struct Image;
208
/// #[derive(FromTemplate)]
209
/// struct Player {
210
/// image: Handle<Image>
211
/// }
212
/// ```
213
///
214
/// Deriving [`FromTemplate`] will generate a [`Template`] type for the deriving type. The example above would generate a `PlayerTemplate` like this:
215
/// ```
216
/// # use bevy_ecs::{prelude::*, template::TemplateContext};
217
/// # #[derive(FromTemplate)]
218
/// # struct Handle<T: core::marker::Unpin>(core::marker::PhantomData<T>);
219
/// # #[derive(Default, Clone)]
220
/// # struct Image;
221
/// struct Player {
222
/// image: Handle<Image>
223
/// }
224
///
225
/// impl FromTemplate for Player {
226
/// type Template = PlayerTemplate;
227
/// }
228
///
229
/// struct PlayerTemplate {
230
/// image: HandleTemplate<Image>,
231
/// }
232
///
233
/// impl Template for PlayerTemplate {
234
/// type Output = Player;
235
/// fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
236
/// Ok(Player {
237
/// image: self.image.build_template(context)?,
238
/// })
239
/// }
240
///
241
/// fn clone_template(&self) -> Self {
242
/// PlayerTemplate {
243
/// image: self.image.clone_template(),
244
/// }
245
/// }
246
/// }
247
/// ```
248
///
249
/// [`FromTemplate`] derives can specify custom templates to use instead of a canonical [`FromTemplate`]:
250
/// ```
251
/// # use bevy_ecs::{prelude::*, template::TemplateContext};
252
/// # struct Image;
253
/// #[derive(FromTemplate)]
254
/// struct Counter {
255
/// #[template(Always10)]
256
/// count: usize
257
/// }
258
///
259
/// #[derive(Default)]
260
/// struct Always10;
261
///
262
/// impl Template for Always10 {
263
/// type Output = usize;
264
///
265
/// fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
266
/// Ok(10)
267
/// }
268
///
269
/// fn clone_template(&self) -> Self {
270
/// Always10
271
/// }
272
/// }
273
/// ```
274
///
275
/// [`FromTemplate`] is automatically implemented for anything that is [`Default`] and [`Clone`]. "Built in" collection types like
276
/// [`Option`] and [`Vec`] pick up this "blanket" implementation, which is generally a good thing because it means these collection
277
/// types work with [`FromTemplate`] derives by default. However if the items in the collection have a custom [`FromTemplate`] impl
278
/// (ex: a manual implementation like `Handle<T>` for assets or an explicit [`FromTemplate`] derive), then relying on a [`Default`] /
279
/// [`Clone`] implementation doesn't work, as that won't run the template logic!
280
///
281
/// Therefore, cases like [`Option<Handle<T>>`] need something other than [`FromTemplate`] to determine the type. One option is to specify
282
/// the template manually:
283
///
284
/// ```
285
/// # use bevy_ecs::{prelude::*, template::{TemplateContext, OptionTemplate}};
286
/// # use core::marker::PhantomData;
287
/// # struct Handle<T>(PhantomData<T>);
288
/// # struct HandleTemplate<T>(PhantomData<T>);
289
/// # struct Image;
290
/// # impl<T> FromTemplate for Handle<T> {
291
/// # type Template = HandleTemplate<T>;
292
/// # }
293
/// # impl<T> Template for HandleTemplate<T> {
294
/// # type Output = Handle<T>;
295
/// # fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
296
/// # unimplemented!()
297
/// # }
298
/// # fn clone_template(&self) -> Self {
299
/// # unimplemented!()
300
/// # }
301
/// # }
302
/// #[derive(FromTemplate)]
303
/// struct Widget {
304
/// #[template(OptionTemplate<HandleTemplate<Image>>)]
305
/// image: Option<Handle<Image>>
306
/// }
307
/// ```
308
///
309
/// However that is a bit of a mouthful! This is where [`BuiltInTemplate`] comes in. It fills the same role
310
/// as [`FromTemplate`], but has no blanket implementation for [`Default`] and [`Clone`], meaning we can have
311
/// custom implementations for types like [`Option`] and [`Vec`].
312
///
313
/// If you are deriving [`FromTemplate`] and you have a "built in" type like [`Option<Handle<T>>`] which has custom template logic,
314
/// annotate it with the `template(built_in)` attribute to use [`BuiltInTemplate`] instead of [`FromTemplate`]:
315
///
316
/// ```
317
/// # use bevy_ecs::{prelude::*, template::TemplateContext};
318
/// # use core::marker::PhantomData;
319
/// # struct Handle<T>(PhantomData<T>);
320
/// # struct HandleTemplate<T>(PhantomData<T>);
321
/// # struct Image;
322
/// # impl<T> FromTemplate for Handle<T> {
323
/// # type Template = HandleTemplate<T>;
324
/// # }
325
/// # impl<T> Template for HandleTemplate<T> {
326
/// # type Output = Handle<T>;
327
/// # fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
328
/// # unimplemented!()
329
/// # }
330
/// # fn clone_template(&self) -> Self {
331
/// # unimplemented!()
332
/// # }
333
/// # }
334
/// #[derive(FromTemplate)]
335
/// struct Widget {
336
/// #[template(built_in)]
337
/// image: Option<Handle<Image>>
338
/// }
339
/// ```
340
pub trait FromTemplate: Sized {
341
/// The [`Template`] for this type.
342
type Template: Template<Output = Self>;
343
}
344
345
macro_rules! template_impl {
346
($($template: ident),*) => {
347
#[expect(
348
clippy::allow_attributes,
349
reason = "This is a tuple-related macro; as such, the lints below may not always apply."
350
)]
351
impl<$($template: Template),*> Template for TemplateTuple<($($template,)*)> {
352
type Output = ($($template::Output,)*);
353
fn build_template(&self, _context: &mut TemplateContext) -> Result<Self::Output> {
354
#[allow(
355
non_snake_case,
356
reason = "The names of these variables are provided by the caller, not by us."
357
)]
358
let ($($template,)*) = &self.0;
359
Ok(($($template.build_template(_context)?,)*))
360
}
361
362
fn clone_template(&self) -> Self {
363
#[allow(
364
non_snake_case,
365
reason = "The names of these variables are provided by the caller, not by us."
366
)]
367
let ($($template,)*) = &self.0;
368
TemplateTuple(($($template.clone_template(),)*))
369
}
370
}
371
}
372
}
373
374
/// A wrapper over a tuple of [`Template`] implementations, which also implements [`Template`]. This exists because [`Template`] cannot
375
/// be directly implemented for tuples of [`Template`] implementations.
376
pub struct TemplateTuple<T>(pub T);
377
378
all_tuples!(template_impl, 0, 12, T);
379
380
// This includes `Unpin` to enable specialization for Templates that also implement Default, by using the
381
// ["auto trait specialization" trick](https://github.com/coolcatcoder/rust_techniques/issues/1)
382
impl<T: Clone + Default + Unpin> Template for T {
383
type Output = T;
384
385
fn build_template(&self, _context: &mut TemplateContext) -> Result<Self::Output> {
386
Ok(self.clone())
387
}
388
389
fn clone_template(&self) -> Self {
390
self.clone()
391
}
392
}
393
394
// This includes `Unpin` to enable specialization for Templates that also implement Default, by using the
395
// ["auto trait specialization" trick](https://github.com/coolcatcoder/rust_techniques/issues/1)
396
impl<T: Clone + Default + Unpin> FromTemplate for T {
397
type Template = T;
398
}
399
400
/// This is used to help improve error messages related to [`FromTemplate`] specialization. Developers should generally just ignore
401
/// this trait and read the error message when they encounter it.
402
#[diagnostic::on_unimplemented(
403
message = "This type does not manually implement FromTemplate, and it must. If you are deriving FromTemplate and you see this, it is likely because \
404
a field does not have a FromTemplate impl. This can usually be fixed by using a custom template for that field. \
405
Ex: for an Option<Handle<Image>> field, annotate the field with `#[template(OptionTemplate<HandleTemplate<Image>>)]`",
406
note = "FromTemplate currently uses pseudo-specialization to enable FromTemplate to override Default. This error message is a consequence of t."
407
)]
408
pub trait SpecializeFromTemplate: Sized {}
409
410
/// A [`Template`] reference to an [`Entity`].
411
#[derive(Copy, Clone, Default, Debug)]
412
pub enum EntityTemplate {
413
/// A reference to a specific [`Entity`]
414
Entity(Entity),
415
/// A reference to an entity via a unique reference
416
SceneEntityReference(SceneEntityReference),
417
/// An entity has not been specified. Building a template with this variant will result in an error.
418
#[default]
419
None,
420
}
421
impl Unpin for EntityTemplate where for<'a> [()]: SpecializeFromTemplate {}
422
423
impl From<Entity> for EntityTemplate {
424
fn from(entity: Entity) -> Self {
425
Self::Entity(entity)
426
}
427
}
428
429
impl Template for EntityTemplate {
430
type Output = Entity;
431
432
fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
433
Ok(match self {
434
Self::Entity(entity) => *entity,
435
Self::SceneEntityReference(reference) => context.get_entity(*reference),
436
Self::None => {
437
return Err(BevyError::error(
438
"Failed to specify an entity for this EntityTemplate",
439
))
440
}
441
})
442
}
443
444
fn clone_template(&self) -> Self {
445
match self {
446
Self::Entity(entity) => Self::Entity(*entity),
447
Self::SceneEntityReference(reference) => Self::SceneEntityReference(*reference),
448
Self::None => Self::None,
449
}
450
}
451
}
452
453
impl FromTemplate for Entity {
454
type Template = EntityTemplate;
455
}
456
457
/// A [`Template`] driven by a function that returns an output. This is used to create "free floating" templates without
458
/// defining a new type. See [`template`] for usage.
459
pub struct FnTemplate<F: Fn(&mut TemplateContext) -> Result<O>, O>(pub F);
460
461
impl<F: Fn(&mut TemplateContext) -> Result<O> + Clone, O> Template for FnTemplate<F, O> {
462
type Output = O;
463
464
fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
465
(self.0)(context)
466
}
467
468
fn clone_template(&self) -> Self {
469
Self(self.0.clone())
470
}
471
}
472
473
/// Returns a "free floating" template for a given `func`. This prevents the need to define a custom type for one-off templates.
474
pub fn template<F: Fn(&mut TemplateContext) -> Result<O>, O>(func: F) -> FnTemplate<F, O> {
475
FnTemplate(func)
476
}
477
478
/// Roughly equivalent to [`FromTemplate`], but does not have a blanket implementation for [`Default`] + [`Clone`] types.
479
/// This is generally used for common generic collection types like [`Option`] and [`Vec`], which have [`Default`] + [`Clone`] impls and
480
/// therefore also pick up the [`FromTemplate`] behavior. This is fine when the `T` in [`Option<T>`] is not "templated"
481
/// (ex: does not have an explicit [`FromTemplate`] derive). But if `T` is "templated", such as [`Option<Handle<T>>`], then it would require
482
/// a manual `#[template(OptionTemplate<HandleTemplate<T>>)]` field annotation. This isn't fun to type out.
483
///
484
/// [`BuiltInTemplate`] enables equivalent "template type inference", by annotating a field with a type that implements [`BuiltInTemplate`] with
485
/// `#[template(built_in)]`.
486
pub trait BuiltInTemplate: Sized {
487
/// The template to consider the "built in" template for this type.
488
type Template: Template;
489
}
490
491
impl<T: FromTemplate> BuiltInTemplate for Option<T> {
492
type Template = OptionTemplate<T::Template>;
493
}
494
495
impl<T: FromTemplate> BuiltInTemplate for Vec<T> {
496
type Template = VecTemplate<T::Template>;
497
}
498
499
/// A [`Template`] for [`Option`].
500
#[derive(Default)]
501
pub enum OptionTemplate<T> {
502
/// Template of [`Option::Some`].
503
Some(T),
504
/// Template of [`Option::None`].
505
#[default]
506
None,
507
}
508
509
impl<T> From<Option<T>> for OptionTemplate<T> {
510
fn from(value: Option<T>) -> Self {
511
match value {
512
Some(value) => OptionTemplate::Some(value),
513
None => OptionTemplate::None,
514
}
515
}
516
}
517
518
impl<T> From<T> for OptionTemplate<T> {
519
fn from(value: T) -> Self {
520
OptionTemplate::Some(value)
521
}
522
}
523
524
impl<T: Template> Template for OptionTemplate<T> {
525
type Output = Option<T::Output>;
526
527
fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
528
Ok(match &self {
529
OptionTemplate::Some(template) => Some(template.build_template(context)?),
530
OptionTemplate::None => None,
531
})
532
}
533
534
fn clone_template(&self) -> Self {
535
match self {
536
OptionTemplate::Some(value) => OptionTemplate::Some(value.clone_template()),
537
OptionTemplate::None => OptionTemplate::None,
538
}
539
}
540
}
541
542
/// A [`Template`] for [`Vec`].
543
pub struct VecTemplate<T>(pub Vec<T>);
544
545
impl<T> Default for VecTemplate<T> {
546
fn default() -> Self {
547
Self(Vec::new())
548
}
549
}
550
551
impl<T: Template> Template for VecTemplate<T> {
552
type Output = Vec<T::Output>;
553
554
fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
555
let mut output = Vec::with_capacity(self.0.len());
556
for value in &self.0 {
557
output.push(value.build_template(context)?);
558
}
559
Ok(output)
560
}
561
562
fn clone_template(&self) -> Self {
563
VecTemplate(self.0.iter().map(Template::clone_template).collect())
564
}
565
}
566
567
#[cfg(test)]
568
mod tests {
569
use crate::prelude::*;
570
use alloc::string::{String, ToString};
571
572
#[test]
573
fn option_template() {
574
#[derive(FromTemplate)]
575
struct Handle(String);
576
577
#[derive(FromTemplate)]
578
struct Foo {
579
#[template(built_in)]
580
handle: Option<Handle>,
581
}
582
583
let mut world = World::new();
584
let foo_template = FooTemplate {
585
handle: Some(HandleTemplate("handle_path".to_string())).into(),
586
};
587
let foo = world.spawn_empty().build_template(&foo_template).unwrap();
588
assert_eq!(foo.handle.unwrap().0, "handle_path".to_string());
589
}
590
}
591
592