Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/ecs/entity_disabling.rs
6592 views
1
//! Disabling entities is a powerful feature that allows you to hide entities from the ECS without deleting them.
2
//!
3
//! This can be useful for implementing features like "sleeping" objects that are offscreen
4
//! or managing networked entities.
5
//!
6
//! While disabling entities *will* make them invisible,
7
//! that's not its primary purpose!
8
//! [`Visibility`] should be used to hide entities;
9
//! disabled entities are skipped entirely, which can lead to subtle bugs.
10
//!
11
//! # Default query filters
12
//!
13
//! Under the hood, Bevy uses a "default query filter" that skips entities with the
14
//! the [`Disabled`] component.
15
//! These filters act as a by-default exclusion list for all queries,
16
//! and can be bypassed by explicitly including these components in your queries.
17
//! For example, `Query<&A, With<Disabled>`, `Query<(Entity, Has<Disabled>>)` or
18
//! `Query<&A, Or<(With<Disabled>, With<B>)>>` will include disabled entities.
19
20
use bevy::ecs::entity_disabling::Disabled;
21
use bevy::prelude::*;
22
23
fn main() {
24
App::new()
25
.add_plugins((DefaultPlugins, MeshPickingPlugin))
26
.add_observer(disable_entities_on_click)
27
.add_systems(
28
Update,
29
(list_all_named_entities, reenable_entities_on_space),
30
)
31
.add_systems(Startup, (setup_scene, display_instructions))
32
.run();
33
}
34
35
#[derive(Component)]
36
struct DisableOnClick;
37
38
fn disable_entities_on_click(
39
event: On<Pointer<Click>>,
40
valid_query: Query<&DisableOnClick>,
41
mut commands: Commands,
42
) {
43
let clicked_entity = event.entity();
44
// Windows and text are entities and can be clicked!
45
// We definitely don't want to disable the window itself,
46
// because that would cause the app to close!
47
if valid_query.contains(clicked_entity) {
48
// Just add the `Disabled` component to the entity to disable it.
49
// Note that the `Disabled` component is *only* added to the entity,
50
// its children are not affected.
51
commands.entity(clicked_entity).insert(Disabled);
52
}
53
}
54
55
#[derive(Component)]
56
struct EntityNameText;
57
58
// The query here will not find entities with the `Disabled` component,
59
// because it does not explicitly include it.
60
fn list_all_named_entities(
61
query: Query<&Name>,
62
mut name_text_query: Query<&mut Text, With<EntityNameText>>,
63
mut commands: Commands,
64
) {
65
let mut text_string = String::from("Named entities found:\n");
66
// Query iteration order is not guaranteed, so we sort the names
67
// to ensure the output is consistent.
68
for name in query.iter().sort::<&Name>() {
69
text_string.push_str(&format!("{name:?}\n"));
70
}
71
72
if let Ok(mut text) = name_text_query.single_mut() {
73
*text = Text::new(text_string);
74
} else {
75
commands.spawn((
76
EntityNameText,
77
Text::default(),
78
Node {
79
position_type: PositionType::Absolute,
80
top: px(12),
81
right: px(12),
82
..default()
83
},
84
));
85
}
86
}
87
88
fn reenable_entities_on_space(
89
mut commands: Commands,
90
// This query can find disabled entities,
91
// because it explicitly includes the `Disabled` component.
92
disabled_entities: Query<Entity, With<Disabled>>,
93
input: Res<ButtonInput<KeyCode>>,
94
) {
95
if input.just_pressed(KeyCode::Space) {
96
for entity in disabled_entities.iter() {
97
// To re-enable an entity, just remove the `Disabled` component.
98
commands.entity(entity).remove::<Disabled>();
99
}
100
}
101
}
102
103
const X_EXTENT: f32 = 900.;
104
105
fn setup_scene(
106
mut commands: Commands,
107
mut meshes: ResMut<Assets<Mesh>>,
108
mut materials: ResMut<Assets<ColorMaterial>>,
109
) {
110
commands.spawn(Camera2d);
111
112
let named_shapes = [
113
(Name::new("Annulus"), meshes.add(Annulus::new(25.0, 50.0))),
114
(
115
Name::new("Bestagon"),
116
meshes.add(RegularPolygon::new(50.0, 6)),
117
),
118
(Name::new("Rhombus"), meshes.add(Rhombus::new(75.0, 100.0))),
119
];
120
let num_shapes = named_shapes.len();
121
122
for (i, (name, shape)) in named_shapes.into_iter().enumerate() {
123
// Distribute colors evenly across the rainbow.
124
let color = Color::hsl(360. * i as f32 / num_shapes as f32, 0.95, 0.7);
125
126
commands.spawn((
127
name,
128
DisableOnClick,
129
Mesh2d(shape),
130
MeshMaterial2d(materials.add(color)),
131
Transform::from_xyz(
132
// Distribute shapes from -X_EXTENT/2 to +X_EXTENT/2.
133
-X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * X_EXTENT,
134
0.0,
135
0.0,
136
),
137
));
138
}
139
}
140
141
fn display_instructions(mut commands: Commands) {
142
commands.spawn((
143
Text::new(
144
"Click an entity to disable it.\n\nPress Space to re-enable all disabled entities.",
145
),
146
Node {
147
position_type: PositionType::Absolute,
148
top: px(12),
149
left: px(12),
150
..default()
151
},
152
));
153
}
154
155