Skip to content

Commit a9b09fc

Browse files
committed
Merge pull request #106739 from timothyqiu/particles-selection
Fix heap-use-after-free when closing a scene with 2D particle nodes selected
2 parents 274ed34 + f16378a commit a9b09fc

File tree

2 files changed

+43
-16
lines changed

2 files changed

+43
-16
lines changed

editor/plugins/particles_editor_plugin.cpp

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -293,33 +293,58 @@ Particles2DEditorPlugin::Particles2DEditorPlugin() {
293293
emission_mask->connect(SceneStringName(confirmed), callable_mp(this, &Particles2DEditorPlugin::_generate_emission_mask));
294294
}
295295

296+
void Particles2DEditorPlugin::_set_show_gizmos(Node *p_node, bool p_show) {
297+
GPUParticles2D *gpu_particles = Object::cast_to<GPUParticles2D>(p_node);
298+
if (gpu_particles) {
299+
gpu_particles->set_show_gizmos(p_show);
300+
}
301+
CPUParticles2D *cpu_particles = Object::cast_to<CPUParticles2D>(p_node);
302+
if (cpu_particles) {
303+
cpu_particles->set_show_gizmos(p_show);
304+
}
305+
306+
// The `selection_changed` signal is deferred. A node could be deleted before the signal is emitted.
307+
if (p_show) {
308+
p_node->connect(SceneStringName(tree_exiting), callable_mp(this, &Particles2DEditorPlugin::_node_removed).bind(p_node));
309+
} else {
310+
p_node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Particles2DEditorPlugin::_node_removed));
311+
}
312+
}
313+
296314
void Particles2DEditorPlugin::_selection_changed() {
297-
List<Node *> selected_nodes = EditorNode::get_singleton()->get_editor_selection()->get_top_selected_node_list();
298-
if (selected_particles.is_empty() && selected_nodes.is_empty()) {
315+
List<Node *> current_selection = EditorNode::get_singleton()->get_editor_selection()->get_top_selected_node_list();
316+
if (selected_particles.is_empty() && current_selection.is_empty()) {
299317
return;
300318
}
301319

302-
for (Node *particles : selected_particles) {
303-
if (GPUParticles2D *gpu_particles = Object::cast_to<GPUParticles2D>(particles)) {
304-
gpu_particles->set_show_gizmos(false);
305-
} else if (CPUParticles2D *cpu_particles = Object::cast_to<CPUParticles2D>(particles)) {
306-
cpu_particles->set_show_gizmos(false);
320+
// Turn gizmos off for nodes that are no longer selected.
321+
for (List<Node *>::Element *E = selected_particles.front(); E;) {
322+
Node *node = E->get();
323+
List<Node *>::Element *N = E->next();
324+
if (current_selection.find(node) == nullptr) {
325+
_set_show_gizmos(node, false);
326+
selected_particles.erase(E);
307327
}
328+
E = N;
308329
}
309330

310-
selected_particles.clear();
311-
312-
for (Node *node : selected_nodes) {
313-
if (GPUParticles2D *selected_gpu_particle = Object::cast_to<GPUParticles2D>(node)) {
314-
selected_gpu_particle->set_show_gizmos(true);
315-
selected_particles.push_back(selected_gpu_particle);
316-
} else if (CPUParticles2D *selected_cpu_particle = Object::cast_to<CPUParticles2D>(node)) {
317-
selected_cpu_particle->set_show_gizmos(true);
318-
selected_particles.push_back(selected_cpu_particle);
331+
// Turn gizmos on for nodes that are newly selected.
332+
for (Node *node : current_selection) {
333+
if (selected_particles.find(node) == nullptr) {
334+
_set_show_gizmos(node, true);
335+
selected_particles.push_back(node);
319336
}
320337
}
321338
}
322339

340+
void Particles2DEditorPlugin::_node_removed(Node *p_node) {
341+
List<Node *>::Element *E = selected_particles.find(p_node);
342+
if (E) {
343+
_set_show_gizmos(E->get(), false);
344+
selected_particles.erase(E);
345+
}
346+
}
347+
323348
void GPUParticles2DEditorPlugin::_generate_visibility_rect() {
324349
GPUParticles2D *particles = Object::cast_to<GPUParticles2D>(edited_node);
325350

editor/plugins/particles_editor_plugin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ class Particles2DEditorPlugin : public ParticlesEditorPlugin {
109109
void _get_base_emission_mask(PackedVector2Array &r_valid_positions, PackedVector2Array &r_valid_normals, PackedByteArray &r_valid_colors, Vector2i &r_image_size);
110110
virtual void _generate_emission_mask() = 0;
111111
void _notification(int p_what);
112+
void _set_show_gizmos(Node *p_node, bool p_show);
112113
void _selection_changed();
114+
void _node_removed(Node *p_node);
113115

114116
public:
115117
Particles2DEditorPlugin();

0 commit comments

Comments
 (0)