diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 8c9e3277de5..6cb193cb664 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -293,33 +293,58 @@ Particles2DEditorPlugin::Particles2DEditorPlugin() { emission_mask->connect(SceneStringName(confirmed), callable_mp(this, &Particles2DEditorPlugin::_generate_emission_mask)); } +void Particles2DEditorPlugin::_set_show_gizmos(Node *p_node, bool p_show) { + GPUParticles2D *gpu_particles = Object::cast_to(p_node); + if (gpu_particles) { + gpu_particles->set_show_gizmos(p_show); + } + CPUParticles2D *cpu_particles = Object::cast_to(p_node); + if (cpu_particles) { + cpu_particles->set_show_gizmos(p_show); + } + + // The `selection_changed` signal is deferred. A node could be deleted before the signal is emitted. + if (p_show) { + p_node->connect(SceneStringName(tree_exiting), callable_mp(this, &Particles2DEditorPlugin::_node_removed).bind(p_node)); + } else { + p_node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Particles2DEditorPlugin::_node_removed)); + } +} + void Particles2DEditorPlugin::_selection_changed() { - List selected_nodes = EditorNode::get_singleton()->get_editor_selection()->get_top_selected_node_list(); - if (selected_particles.is_empty() && selected_nodes.is_empty()) { + List current_selection = EditorNode::get_singleton()->get_editor_selection()->get_top_selected_node_list(); + if (selected_particles.is_empty() && current_selection.is_empty()) { return; } - for (Node *particles : selected_particles) { - if (GPUParticles2D *gpu_particles = Object::cast_to(particles)) { - gpu_particles->set_show_gizmos(false); - } else if (CPUParticles2D *cpu_particles = Object::cast_to(particles)) { - cpu_particles->set_show_gizmos(false); + // Turn gizmos off for nodes that are no longer selected. + for (List::Element *E = selected_particles.front(); E;) { + Node *node = E->get(); + List::Element *N = E->next(); + if (current_selection.find(node) == nullptr) { + _set_show_gizmos(node, false); + selected_particles.erase(E); } + E = N; } - selected_particles.clear(); - - for (Node *node : selected_nodes) { - if (GPUParticles2D *selected_gpu_particle = Object::cast_to(node)) { - selected_gpu_particle->set_show_gizmos(true); - selected_particles.push_back(selected_gpu_particle); - } else if (CPUParticles2D *selected_cpu_particle = Object::cast_to(node)) { - selected_cpu_particle->set_show_gizmos(true); - selected_particles.push_back(selected_cpu_particle); + // Turn gizmos on for nodes that are newly selected. + for (Node *node : current_selection) { + if (selected_particles.find(node) == nullptr) { + _set_show_gizmos(node, true); + selected_particles.push_back(node); } } } +void Particles2DEditorPlugin::_node_removed(Node *p_node) { + List::Element *E = selected_particles.find(p_node); + if (E) { + _set_show_gizmos(E->get(), false); + selected_particles.erase(E); + } +} + void GPUParticles2DEditorPlugin::_generate_visibility_rect() { GPUParticles2D *particles = Object::cast_to(edited_node); diff --git a/editor/plugins/particles_editor_plugin.h b/editor/plugins/particles_editor_plugin.h index 9d556748cf9..d2f6187ac17 100644 --- a/editor/plugins/particles_editor_plugin.h +++ b/editor/plugins/particles_editor_plugin.h @@ -109,7 +109,9 @@ protected: void _get_base_emission_mask(PackedVector2Array &r_valid_positions, PackedVector2Array &r_valid_normals, PackedByteArray &r_valid_colors, Vector2i &r_image_size); virtual void _generate_emission_mask() = 0; void _notification(int p_what); + void _set_show_gizmos(Node *p_node, bool p_show); void _selection_changed(); + void _node_removed(Node *p_node); public: Particles2DEditorPlugin();