Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/ecs/entity_disabling.rs
6849 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
click: On<Pointer<Click>>,
40
valid_query: Query<&DisableOnClick>,
41
mut commands: Commands,
42
) {
43
// Windows and text are entities and can be clicked!
44
// We definitely don't want to disable the window itself,
45
// because that would cause the app to close!
46
if valid_query.contains(click.entity) {
47
// Just add the `Disabled` component to the entity to disable it.
48
// Note that the `Disabled` component is *only* added to the entity,
49
// its children are not affected.
50
commands.entity(click.entity).insert(Disabled);
51
}
52
}
53
54
#[derive(Component)]
55
struct EntityNameText;
56
57
// The query here will not find entities with the `Disabled` component,
58
// because it does not explicitly include it.
59
fn list_all_named_entities(
60
query: Query<&Name>,
61
mut name_text_query: Query<&mut Text, With<EntityNameText>>,
62
mut commands: Commands,
63
) {
64
let mut text_string = String::from("Named entities found:\n");
65
// Query iteration order is not guaranteed, so we sort the names
66
// to ensure the output is consistent.
67
for name in query.iter().sort::<&Name>() {
68
text_string.push_str(&format!("{name:?}\n"));
69
}
70
71
if let Ok(mut text) = name_text_query.single_mut() {
72
*text = Text::new(text_string);
73
} else {
74
commands.spawn((
75
EntityNameText,
76
Text::default(),
77
Node {
78
position_type: PositionType::Absolute,
79
top: px(12),
80
right: px(12),
81
..default()
82
},
83
));
84
}
85
}
86
87
fn reenable_entities_on_space(
88
mut commands: Commands,
89
// This query can find disabled entities,
90
// because it explicitly includes the `Disabled` component.
91
disabled_entities: Query<Entity, With<Disabled>>,
92
input: Res<ButtonInput<KeyCode>>,
93
) {
94
if input.just_pressed(KeyCode::Space) {
95
for entity in disabled_entities.iter() {
96
// To re-enable an entity, just remove the `Disabled` component.
97
commands.entity(entity).remove::<Disabled>();
98
}
99
}
100
}
101
102
const X_EXTENT: f32 = 900.;
103
104
fn setup_scene(
105
mut commands: Commands,
106
mut meshes: ResMut<Assets<Mesh>>,
107
mut materials: ResMut<Assets<ColorMaterial>>,
108
) {
109
commands.spawn(Camera2d);
110
111
let named_shapes = [
112
(Name::new("Annulus"), meshes.add(Annulus::new(25.0, 50.0))),
113
(
114
Name::new("Bestagon"),
115
meshes.add(RegularPolygon::new(50.0, 6)),
116
),
117
(Name::new("Rhombus"), meshes.add(Rhombus::new(75.0, 100.0))),
118
];
119
let num_shapes = named_shapes.len();
120
121
for (i, (name, shape)) in named_shapes.into_iter().enumerate() {
122
// Distribute colors evenly across the rainbow.
123
let color = Color::hsl(360. * i as f32 / num_shapes as f32, 0.95, 0.7);
124
125
commands.spawn((
126
name,
127
DisableOnClick,
128
Mesh2d(shape),
129
MeshMaterial2d(materials.add(color)),
130
Transform::from_xyz(
131
// Distribute shapes from -X_EXTENT/2 to +X_EXTENT/2.
132
-X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * X_EXTENT,
133
0.0,
134
0.0,
135
),
136
));
137
}
138
}
139
140
fn display_instructions(mut commands: Commands) {
141
commands.spawn((
142
Text::new(
143
"Click an entity to disable it.\n\nPress Space to re-enable all disabled entities.",
144
),
145
Node {
146
position_type: PositionType::Absolute,
147
top: px(12),
148
left: px(12),
149
..default()
150
},
151
));
152
}
153
154