/
basic.rs
94 lines (81 loc) · 3.18 KB
/
basic.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
#![allow(unused_doc_comments)]
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
use bevy_proto_typetag::prelude::*;
/// This is the component we will use with our prototype
/// It must impl/derive Serialize, Clone, and Deserialize from serde in order to compile
#[derive(Clone, Serialize, Deserialize, Component)]
struct Person {
pub name: String,
}
/// This is where we implement the [`ProtoComponent`] trait.
///
/// Note that we must apply the `#[typetag::serde]` attribute
#[typetag::serde]
impl ProtoComponent for Person {
fn insert_self(&self, commands: &mut ProtoCommands, _asset_server: &Res<AssetServer>) {
/// Here, we create the component we're going to insert.
/// This can really be any valid Bevy component type, but we'll
/// use `Person` since it's so simple
let component = Self {
name: self.name.clone(),
};
// Attach the component(s) to the entity
commands.insert(component);
}
}
/// For simple types, deriving [`ProtoComponent`] can be used to automatically
/// generate the required `impl` block.
///
/// The [`Person`] component defined above could have simply been written as:
/// ```
/// #[derive(Clone, Serialize, Deserialize, Component, ProtoComponent)]
/// struct Person {
/// pub name: String,
/// }
/// ```
#[derive(Copy, Clone, Serialize, Deserialize, ProtoComponent, Component)]
struct Ordered {
pub order: i32,
}
/// Spawn in the person.
///
/// This system also demonstrates the minimum requirements for using the prototype system
fn spawn_person(mut commands: Commands, data: Res<ProtoData>, asset_server: Res<AssetServer>) {
/// Here, we attempt to get our prototype by name.
/// We'll raise an exception if it's not found, just so we can fail fast.
/// In reality, you'll likely want to handle this prototype not existing.
let proto = data.get_prototype("Person Test 1").expect("Should exist!");
// Spawn in the prototype!
proto.spawn(&mut commands, &data, &asset_server);
// Spawn it again!
proto.spawn(&mut commands, &data, &asset_server);
// Insert on an existing entity!
let entity = commands.spawn_empty().id();
let entity_cmds = commands.entity(entity);
proto.insert(entity_cmds, &data, &asset_server);
// Spawn in others!
for i in 2..=3 {
data.get_prototype(format!("Person Test {}", i).as_str())
.unwrap()
.spawn(&mut commands, &data, &asset_server);
}
}
/// A system to test our spawner. This makes each entity introduce itself when spawned in
fn introduce(query: Query<(&Person, &Ordered), Added<Person>>) {
for (person, ordered) in query.iter() {
println!("{}. Hello! My name is {}", ordered.order, person.name);
}
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// This plugin should come AFTER any others that it might rely on
// In this case, we need access to what's added by [`DefaultPlugins`]
// so we place this line after that one
.add_plugin(ProtoPlugin::default())
// Add our spawner system (this one only runs once at startup)
.add_startup_system(spawn_person)
.add_system(introduce)
.run();
}