Avoid unnecessary inspector updates when loading or switching scenes

This should result in some noticeable performance improvements,
aside from fixing bugs due to conflicts in logic.
This also simplifies some related code identified while debugging.
This commit is contained in:
Yuri Sizov 2023-08-11 15:55:47 +02:00
parent 4714e95896
commit 2445414aa0
19 changed files with 102 additions and 93 deletions

View file

@ -1347,20 +1347,20 @@ void ScriptEditorDebugger::_live_edit_set() {
NodePath np = path;
EditorNode::get_singleton()->get_editor_data().set_edited_scene_live_edit_root(np);
EditorNode::get_editor_data().set_edited_scene_live_edit_root(np);
update_live_edit_root();
}
void ScriptEditorDebugger::_live_edit_clear() {
NodePath np = NodePath("/root");
EditorNode::get_singleton()->get_editor_data().set_edited_scene_live_edit_root(np);
EditorNode::get_editor_data().set_edited_scene_live_edit_root(np);
update_live_edit_root();
}
void ScriptEditorDebugger::update_live_edit_root() {
NodePath np = EditorNode::get_singleton()->get_editor_data().get_edited_scene_live_edit_root();
NodePath np = EditorNode::get_editor_data().get_edited_scene_live_edit_root();
Array msg;
msg.push_back(np);

View file

@ -244,7 +244,7 @@ EditorSelectionHistory::EditorSelectionHistory() {
////////////////////////////////////////////////////////////
EditorPlugin *EditorData::get_editor(Object *p_object) {
EditorPlugin *EditorData::get_handling_main_editor(Object *p_object) {
// We need to iterate backwards so that we can check user-created plugins first.
// Otherwise, it would not be possible for plugins to handle CanvasItem and Spatial nodes.
for (int i = editor_plugins.size() - 1; i > -1; i--) {
@ -256,7 +256,7 @@ EditorPlugin *EditorData::get_editor(Object *p_object) {
return nullptr;
}
Vector<EditorPlugin *> EditorData::get_subeditors(Object *p_object) {
Vector<EditorPlugin *> EditorData::get_handling_sub_editors(Object *p_object) {
Vector<EditorPlugin *> sub_plugins;
for (int i = editor_plugins.size() - 1; i > -1; i--) {
if (!editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object)) {
@ -266,7 +266,7 @@ Vector<EditorPlugin *> EditorData::get_subeditors(Object *p_object) {
return sub_plugins;
}
EditorPlugin *EditorData::get_editor(String p_name) {
EditorPlugin *EditorData::get_editor_by_name(String p_name) {
for (int i = editor_plugins.size() - 1; i > -1; i--) {
if (editor_plugins[i]->get_name() == p_name) {
return editor_plugins[i];

View file

@ -150,9 +150,9 @@ private:
Ref<Texture2D> _load_script_icon(const String &p_path) const;
public:
EditorPlugin *get_editor(Object *p_object);
Vector<EditorPlugin *> get_subeditors(Object *p_object);
EditorPlugin *get_editor(String p_name);
EditorPlugin *get_handling_main_editor(Object *p_object);
Vector<EditorPlugin *> get_handling_sub_editors(Object *p_object);
EditorPlugin *get_editor_by_name(String p_name);
void copy_object_params(Object *p_object);
void paste_object_params(Object *p_object);

View file

@ -880,8 +880,8 @@ void EditorProperty::_update_pin_flags() {
// Avoid errors down the road by ignoring nodes which are not part of a scene
if (!node->get_owner()) {
bool is_scene_root = false;
for (int i = 0; i < EditorNode::get_singleton()->get_editor_data().get_edited_scene_count(); ++i) {
if (EditorNode::get_singleton()->get_editor_data().get_edited_scene_root(i) == node) {
for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); ++i) {
if (EditorNode::get_editor_data().get_edited_scene_root(i) == node) {
is_scene_root = true;
break;
}
@ -1719,7 +1719,7 @@ void EditorInspectorArray::_move_element(int p_element_index, int p_to_pos) {
undo_redo->create_action(action_name);
if (mode == MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION) {
// Call the function.
Callable move_function = EditorNode::get_singleton()->get_editor_data().get_move_array_element_function(object->get_class_name());
Callable move_function = EditorNode::get_editor_data().get_move_array_element_function(object->get_class_name());
if (move_function.is_valid()) {
Variant args[] = { undo_redo, object, array_element_prefix, p_element_index, p_to_pos };
const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] };
@ -1864,7 +1864,7 @@ void EditorInspectorArray::_clear_array() {
if (mode == MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION) {
for (int i = count - 1; i >= 0; i--) {
// Call the function.
Callable move_function = EditorNode::get_singleton()->get_editor_data().get_move_array_element_function(object->get_class_name());
Callable move_function = EditorNode::get_editor_data().get_move_array_element_function(object->get_class_name());
if (move_function.is_valid()) {
Variant args[] = { undo_redo, object, array_element_prefix, i, -1 };
const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] };
@ -1918,7 +1918,7 @@ void EditorInspectorArray::_resize_array(int p_size) {
if (mode == MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION) {
for (int i = count; i < p_size; i++) {
// Call the function.
Callable move_function = EditorNode::get_singleton()->get_editor_data().get_move_array_element_function(object->get_class_name());
Callable move_function = EditorNode::get_editor_data().get_move_array_element_function(object->get_class_name());
if (move_function.is_valid()) {
Variant args[] = { undo_redo, object, array_element_prefix, -1, -1 };
const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] };
@ -1937,7 +1937,7 @@ void EditorInspectorArray::_resize_array(int p_size) {
if (mode == MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION) {
for (int i = count - 1; i > p_size - 1; i--) {
// Call the function.
Callable move_function = EditorNode::get_singleton()->get_editor_data().get_move_array_element_function(object->get_class_name());
Callable move_function = EditorNode::get_editor_data().get_move_array_element_function(object->get_class_name());
if (move_function.is_valid()) {
Variant args[] = { undo_redo, object, array_element_prefix, i, -1 };
const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] };
@ -3393,6 +3393,7 @@ void EditorInspector::edit(Object *p_object) {
if (object == p_object) {
return;
}
if (object) {
_clear();
object->disconnect("property_list_changed", callable_mp(this, &EditorInspector::_changed_callback));
@ -3500,9 +3501,12 @@ void EditorInspector::_filter_changed(const String &p_text) {
update_tree();
}
void EditorInspector::set_use_folding(bool p_enable) {
use_folding = p_enable;
update_tree();
void EditorInspector::set_use_folding(bool p_use_folding, bool p_update_tree) {
use_folding = p_use_folding;
if (p_update_tree) {
update_tree();
}
}
bool EditorInspector::is_using_folding() {
@ -3693,7 +3697,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
Variant v_undo_redo = undo_redo;
Variant v_object = object;
Variant v_name = p_name;
const Vector<Callable> &callbacks = EditorNode::get_singleton()->get_editor_data().get_undo_redo_inspector_hook_callback();
const Vector<Callable> &callbacks = EditorNode::get_editor_data().get_undo_redo_inspector_hook_callback();
for (int i = 0; i < callbacks.size(); i++) {
const Callable &callback = callbacks[i];

View file

@ -589,7 +589,7 @@ public:
void set_use_filter(bool p_use);
void register_text_enter(Node *p_line_edit);
void set_use_folding(bool p_enable);
void set_use_folding(bool p_use_folding, bool p_update_tree = true);
bool is_using_folding();
void collapse_all_folding();

View file

@ -2145,52 +2145,61 @@ bool EditorNode::_is_class_editor_disabled_by_feature_profile(const StringName &
void EditorNode::edit_item(Object *p_object, Object *p_editing_owner) {
ERR_FAIL_NULL(p_editing_owner);
if (p_object && _is_class_editor_disabled_by_feature_profile(p_object->get_class())) {
// Editing for this type of object may be disabled by user's feature profile.
if (!p_object || _is_class_editor_disabled_by_feature_profile(p_object->get_class())) {
// Nothing to edit, clean up the owner context and return.
hide_unused_editors(p_editing_owner);
return;
}
Vector<EditorPlugin *> item_plugins;
if (p_object) {
item_plugins = editor_data.get_subeditors(p_object);
// Get a list of editor plugins that can handle this type of object.
Vector<EditorPlugin *> available_plugins = editor_data.get_handling_sub_editors(p_object);
if (available_plugins.is_empty()) {
// None, clean up the owner context and return.
hide_unused_editors(p_editing_owner);
return;
}
if (!item_plugins.is_empty()) {
ObjectID owner_id = p_editing_owner->get_instance_id();
ObjectID owner_id = p_editing_owner->get_instance_id();
List<EditorPlugin *> to_remove;
for (EditorPlugin *plugin : active_plugins[owner_id]) {
if (!item_plugins.has(plugin)) {
// Remove plugins no longer used by this editing owner.
to_remove.push_back(plugin);
_plugin_over_edit(plugin, nullptr);
}
// Remove editor plugins no longer used by this editing owner. Keep the ones that can
// still be reused by the new edited object.
List<EditorPlugin *> to_remove;
for (EditorPlugin *plugin : active_plugins[owner_id]) {
if (!available_plugins.has(plugin)) {
to_remove.push_back(plugin);
_plugin_over_edit(plugin, nullptr);
}
}
for (EditorPlugin *plugin : to_remove) {
active_plugins[owner_id].erase(plugin);
}
// Send the edited object to the plugins.
for (EditorPlugin *plugin : available_plugins) {
if (active_plugins[owner_id].has(plugin)) {
// Plugin was already active, just change the object.
plugin->edit(p_object);
continue;
}
for (EditorPlugin *plugin : to_remove) {
active_plugins[owner_id].erase(plugin);
}
for (EditorPlugin *plugin : item_plugins) {
if (active_plugins[owner_id].has(plugin)) {
plugin->edit(p_object);
continue;
}
for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) {
if (kv.key != owner_id) {
EditorPropertyResource *epres = Object::cast_to<EditorPropertyResource>(ObjectDB::get_instance(kv.key));
if (epres && kv.value.has(plugin)) {
// If it's resource property editing the same resource type, fold it.
epres->fold_resource();
}
kv.value.erase(plugin);
// If plugin is already associated with another owner, remove it from there first.
for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) {
if (kv.key != owner_id) {
EditorPropertyResource *epres = Object::cast_to<EditorPropertyResource>(ObjectDB::get_instance(kv.key));
if (epres && kv.value.has(plugin)) {
// If it's resource property editing the same resource type, fold it.
epres->fold_resource();
}
kv.value.erase(plugin);
}
active_plugins[owner_id].insert(plugin);
_plugin_over_edit(plugin, p_object);
}
} else {
hide_unused_editors(p_editing_owner);
// Activate previously inactive plugin and edit the object.
active_plugins[owner_id].insert(plugin);
_plugin_over_edit(plugin, p_object);
}
}
@ -2291,15 +2300,16 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
InspectorDock::get_inspector_singleton()->edit(nullptr);
NodeDock::get_singleton()->set_node(nullptr);
InspectorDock::get_singleton()->update(nullptr);
hide_unused_editors();
return;
}
Object *prev_inspected_object = InspectorDock::get_inspector_singleton()->get_edited_object();
// Update the use folding setting and state.
bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding"));
if (InspectorDock::get_inspector_singleton()->is_using_folding() == disable_folding) {
InspectorDock::get_inspector_singleton()->set_use_folding(!disable_folding, false);
}
bool is_resource = current_obj->is_class("Resource");
bool is_node = current_obj->is_class("Node");
bool stay_in_script_editor_on_node_selected = bool(EDITOR_GET("text_editor/behavior/navigation/stay_in_script_editor_on_node_selected"));
@ -2317,6 +2327,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
if (is_resource) {
Resource *current_res = Object::cast_to<Resource>(current_obj);
ERR_FAIL_COND(!current_res);
InspectorDock::get_inspector_singleton()->edit(current_res);
SceneTreeDock::get_singleton()->set_selected(nullptr);
NodeDock::get_singleton()->set_node(nullptr);
@ -2406,27 +2417,18 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
InspectorDock::get_singleton()->update(nullptr);
}
if (current_obj == prev_inspected_object) {
// Make sure inspected properties are restored.
InspectorDock::get_inspector_singleton()->update_tree();
}
InspectorDock::get_singleton()->set_info(
info_is_warning ? TTR("Changes may be lost!") : TTR("This object is read-only."),
editable_info,
info_is_warning);
if (InspectorDock::get_inspector_singleton()->is_using_folding() == disable_folding) {
InspectorDock::get_inspector_singleton()->set_use_folding(!disable_folding);
}
Object *editor_owner = is_node ? (Object *)SceneTreeDock::get_singleton() : is_resource ? (Object *)InspectorDock::get_inspector_singleton()
: (Object *)this;
// Take care of the main editor plugin.
if (!inspector_only) {
EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
EditorPlugin *main_plugin = editor_data.get_handling_main_editor(current_obj);
int plugin_index = 0;
for (; plugin_index < editor_table.size(); plugin_index++) {
@ -3815,11 +3817,14 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
prev_scene->set_disabled(previous_scenes.size() == 0);
opening_prev = false;
SceneTreeDock::get_singleton()->set_selected(new_scene);
EditorDebuggerNode::get_singleton()->update_live_edit_root();
push_item(new_scene);
// Tell everything to edit this object, unless we're in the process of restoring scenes.
// If we are, we'll edit it after the restoration is done.
if (!restoring_scenes) {
push_item(new_scene);
}
// Load the selected nodes.
if (editor_state_cf->has_section_key("editor_states", "selected_nodes")) {

View file

@ -378,11 +378,11 @@ bool EditorPlugin::get_remove_list(List<Node *> *p_list) {
}
void EditorPlugin::add_undo_redo_inspector_hook_callback(Callable p_callable) {
EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(p_callable);
EditorNode::get_editor_data().add_undo_redo_inspector_hook_callback(p_callable);
}
void EditorPlugin::remove_undo_redo_inspector_hook_callback(Callable p_callable) {
EditorNode::get_singleton()->get_editor_data().remove_undo_redo_inspector_hook_callback(p_callable);
EditorNode::get_editor_data().remove_undo_redo_inspector_hook_callback(p_callable);
}
void EditorPlugin::add_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser) {

View file

@ -70,7 +70,7 @@ int EditorUndoRedoManager::get_history_id_for_object(Object *p_object) const {
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
if (edited_scene && (node == edited_scene || edited_scene->is_ancestor_of(node))) {
int idx = EditorNode::get_singleton()->get_editor_data().get_current_edited_scene_history_id();
int idx = EditorNode::get_editor_data().get_current_edited_scene_history_id();
if (idx > 0) {
history_id = idx;
}
@ -80,12 +80,12 @@ int EditorUndoRedoManager::get_history_id_for_object(Object *p_object) const {
if (Resource *res = Object::cast_to<Resource>(p_object)) {
if (res->is_built_in()) {
if (res->get_path().is_empty()) {
int idx = EditorNode::get_singleton()->get_editor_data().get_current_edited_scene_history_id();
int idx = EditorNode::get_editor_data().get_current_edited_scene_history_id();
if (idx > 0) {
history_id = idx;
}
} else {
int idx = EditorNode::get_singleton()->get_editor_data().get_scene_history_id_from_path(res->get_path().get_slice("::", 0));
int idx = EditorNode::get_editor_data().get_scene_history_id_from_path(res->get_path().get_slice("::", 0));
if (idx > 0) {
history_id = idx;
}

View file

@ -1361,7 +1361,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
for (int i = 0; i < file_changed_paths.size(); ++i) {
String new_item_path = p_item.is_file ? new_path : file_changed_paths[i].replace_first(old_path, new_path);
if (ResourceLoader::get_resource_type(new_item_path) == "PackedScene" && EditorNode::get_singleton()->is_scene_open(file_changed_paths[i])) {
EditorData *ed = &EditorNode::get_singleton()->get_editor_data();
EditorData *ed = &EditorNode::get_editor_data();
for (int j = 0; j < ed->get_edited_scene_count(); j++) {
if (ed->get_scene_path(j) == file_changed_paths[i]) {
ed->get_edited_scene_root(j)->set_scene_file_path(new_item_path);
@ -1629,7 +1629,7 @@ void FileSystemDock::_make_scene_confirm() {
const String scene_path = make_scene_dialog->get_scene_path();
int idx = EditorNode::get_singleton()->new_scene();
EditorNode::get_singleton()->get_editor_data().set_scene_path(idx, scene_path);
EditorNode::get_editor_data().set_scene_path(idx, scene_path);
EditorNode::get_singleton()->set_edited_scene(make_scene_dialog->create_scene_root());
EditorNode::get_singleton()->save_scene_list({ scene_path });
}

View file

@ -116,7 +116,7 @@ void AudioStreamRandomizerEditorPlugin::_move_stream_array_element(Object *p_und
}
AudioStreamRandomizerEditorPlugin::AudioStreamRandomizerEditorPlugin() {
EditorNode::get_singleton()->get_editor_data().add_move_array_element_function(SNAME("AudioStreamRandomizer"), callable_mp(this, &AudioStreamRandomizerEditorPlugin::_move_stream_array_element));
EditorNode::get_editor_data().add_move_array_element_function(SNAME("AudioStreamRandomizer"), callable_mp(this, &AudioStreamRandomizerEditorPlugin::_move_stream_array_element));
}
AudioStreamRandomizerEditorPlugin::~AudioStreamRandomizerEditorPlugin() {}

View file

@ -346,7 +346,7 @@ EditorInspectorPluginMaterial::EditorInspectorPluginMaterial() {
env->set_ambient_source(Environment::AMBIENT_SOURCE_SKY);
env->set_reflection_source(Environment::REFLECTION_SOURCE_SKY);
EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &EditorInspectorPluginMaterial::_undo_redo_inspector_callback));
EditorNode::get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &EditorInspectorPluginMaterial::_undo_redo_inspector_callback));
}
MaterialEditorPlugin::MaterialEditorPlugin() {

View file

@ -3623,7 +3623,7 @@ void ScriptEditor::_on_find_in_files_result_selected(String fpath, int line_numb
Ref<Resource> res = ResourceLoader::load(fpath);
if (fpath.get_extension() == "gdshader") {
ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_singleton()->get_editor_data().get_editor("Shader"));
ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_editor_data().get_editor_by_name("Shader"));
shader_editor->edit(res.ptr());
shader_editor->make_visible(true);
shader_editor->get_shader_editor(res)->goto_line_selection(line_number - 1, begin, end);

View file

@ -4090,7 +4090,7 @@ TileMapEditor::TileMapEditor() {
_tab_changed(0);
// Registers UndoRedo inspector callback.
EditorNode::get_singleton()->get_editor_data().add_move_array_element_function(SNAME("TileMap"), callable_mp(this, &TileMapEditor::_move_tile_map_array_element));
EditorNode::get_editor_data().add_move_array_element_function(SNAME("TileMap"), callable_mp(this, &TileMapEditor::_move_tile_map_array_element));
}
TileMapEditor::~TileMapEditor() {

View file

@ -2635,7 +2635,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control_unscaled, false);
alternative_tiles_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetAtlasSourceEditor::_undo_redo_inspector_callback));
EditorNode::get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetAtlasSourceEditor::_undo_redo_inspector_callback));
// -- Dialogs --
confirm_auto_create_tiles = memnew(AcceptDialog);

View file

@ -963,8 +963,8 @@ TileSetEditor::TileSetEditor() {
expanded_area->hide();
// Registers UndoRedo inspector callback.
EditorNode::get_singleton()->get_editor_data().add_move_array_element_function(SNAME("TileSet"), callable_mp(this, &TileSetEditor::_move_tile_set_array_element));
EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetEditor::_undo_redo_inspector_callback));
EditorNode::get_editor_data().add_move_array_element_function(SNAME("TileSet"), callable_mp(this, &TileSetEditor::_move_tile_set_array_element));
EditorNode::get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetEditor::_undo_redo_inspector_callback));
}
void TileSourceInspectorPlugin::_show_id_edit_dialog(Object *p_for_source) {

View file

@ -458,7 +458,7 @@ void VersionControlEditorPlugin::_force_push() {
}
void VersionControlEditorPlugin::_update_opened_tabs() {
Vector<EditorData::EditedScene> open_scenes = EditorNode::get_singleton()->get_editor_data().get_edited_scenes();
Vector<EditorData::EditedScene> open_scenes = EditorNode::get_editor_data().get_edited_scenes();
for (int i = 0; i < open_scenes.size(); i++) {
if (open_scenes[i].root == NULL) {
continue;

View file

@ -6544,7 +6544,7 @@ void EditorPropertyVisualShaderMode::_option_selected(int p_which) {
return;
}
ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_singleton()->get_editor_data().get_editor("Shader"));
ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_editor_data().get_editor_by_name("Shader"));
if (!shader_editor) {
return;
}

View file

@ -444,11 +444,11 @@ String RenameDialog::_substitute(const String &subject, const Node *node, int co
result = result.replace("${TYPE}", node->get_class());
}
int current = EditorNode::get_singleton()->get_editor_data().get_edited_scene();
int current = EditorNode::get_editor_data().get_edited_scene();
// Always request the scene title with the extension stripped.
// Otherwise, the result could vary depending on whether a scene with the same name
// (but different extension) is currently open.
result = result.replace("${SCENE}", EditorNode::get_singleton()->get_editor_data().get_scene_title(current, true));
result = result.replace("${SCENE}", EditorNode::get_editor_data().get_scene_title(current, true));
Node *root_node = SceneTree::get_singleton()->get_edited_scene_root();
if (root_node) {

View file

@ -1288,14 +1288,14 @@ void SceneTreeDock::_notification(int p_what) {
EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", callable_mp(this, &SceneTreeDock::_feature_profile_changed));
CanvasItemEditorPlugin *canvas_item_plugin = Object::cast_to<CanvasItemEditorPlugin>(editor_data->get_editor("2D"));
CanvasItemEditorPlugin *canvas_item_plugin = Object::cast_to<CanvasItemEditorPlugin>(editor_data->get_editor_by_name("2D"));
if (canvas_item_plugin) {
canvas_item_plugin->get_canvas_item_editor()->connect("item_lock_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false));
canvas_item_plugin->get_canvas_item_editor()->connect("item_group_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false));
scene_tree->connect("node_changed", callable_mp((CanvasItem *)canvas_item_plugin->get_canvas_item_editor()->get_viewport_control(), &CanvasItem::queue_redraw));
}
Node3DEditorPlugin *spatial_editor_plugin = Object::cast_to<Node3DEditorPlugin>(editor_data->get_editor("3D"));
Node3DEditorPlugin *spatial_editor_plugin = Object::cast_to<Node3DEditorPlugin>(editor_data->get_editor_by_name("3D"));
spatial_editor_plugin->get_spatial_editor()->connect("item_lock_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false));
spatial_editor_plugin->get_spatial_editor()->connect("item_group_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false));
@ -3215,10 +3215,10 @@ void SceneTreeDock::_focus_node() {
ERR_FAIL_COND(!node);
if (node->is_class("CanvasItem")) {
CanvasItemEditorPlugin *editor = Object::cast_to<CanvasItemEditorPlugin>(editor_data->get_editor("2D"));
CanvasItemEditorPlugin *editor = Object::cast_to<CanvasItemEditorPlugin>(editor_data->get_editor_by_name("2D"));
editor->get_canvas_item_editor()->focus_selection();
} else {
Node3DEditorPlugin *editor = Object::cast_to<Node3DEditorPlugin>(editor_data->get_editor("3D"));
Node3DEditorPlugin *editor = Object::cast_to<Node3DEditorPlugin>(editor_data->get_editor_by_name("3D"));
editor->get_spatial_editor()->get_editor_viewport(0)->focus_selection();
}
}