diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 2c7d397f656..0b1cc5b0e11 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -3829,7 +3829,23 @@ bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const P if (mesh != nullptr) { MeshInstance *mesh_instance = memnew(MeshInstance); mesh_instance->set_mesh(mesh); - mesh_instance->set_name(path.get_file().get_basename()); + + // Adjust casing according to project setting. The file name is expected to be in snake_case, but will work for others. + String name = path.get_file().get_basename(); + switch (ProjectSettings::get_singleton()->get("node/name_casing").operator int()) { + case NAME_CASING_PASCAL_CASE: + name = name.capitalize().replace(" ", ""); + break; + case NAME_CASING_CAMEL_CASE: + name = name.capitalize().replace(" ", ""); + name[0] = name.to_lower()[0]; + break; + case NAME_CASING_SNAKE_CASE: + name = name.capitalize().replace(" ", "_").to_lower(); + break; + } + mesh_instance->set_name(name); + instanced_scene = mesh_instance; } else { if (!scene.is_valid()) { // invalid scene @@ -3980,6 +3996,7 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p } bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT); + bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); selected_files.clear(); Dictionary d = p_data; @@ -3987,29 +4004,31 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p selected_files = d["files"]; } - List list = editor->get_editor_selection()->get_selected_node_list(); - if (list.size() == 0) { - Node *root_node = editor->get_edited_scene(); - if (root_node) { - list.push_back(root_node); - } else { - accept->set_text(TTR("No parent to instance a child at.")); - accept->popup_centered_minsize(); - _remove_preview(); - return; + List selected_nodes = editor->get_editor_selection()->get_selected_node_list(); + Node *root_node = editor->get_edited_scene(); + if (selected_nodes.size() == 1) { + Node *selected_node = selected_nodes[0]; + target_node = root_node; + if (is_ctrl) { + target_node = selected_node; + } else if (is_shift && selected_node != root_node) { + target_node = selected_node->get_parent(); } - } - if (list.size() != 1) { - accept->set_text(TTR("This operation requires a single selected node.")); - accept->popup_centered_minsize(); + } else if (selected_nodes.size() == 0) { + if (root_node) { + target_node = root_node; + } else { + // Create a root node so we can add child nodes to it. + EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Spatial)); + target_node = get_tree()->get_edited_scene_root(); + } + } else { + accept->set_text(TTR("Cannot drag and drop into multiple selected nodes.")); + accept->popup_centered(); _remove_preview(); return; } - target_node = list[0]; - if (is_shift && target_node != editor->get_edited_scene()) { - target_node = target_node->get_parent(); - } drop_pos = p_point; _perform_drop_data(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index ad117d6d449..58334786cb0 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1190,12 +1190,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } } - editor_data->get_undo_redo().create_action(TTR("New Scene Root")); - editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", new_node); - editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree"); - editor_data->get_undo_redo().add_do_reference(new_node); - editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)nullptr); - editor_data->get_undo_redo().commit_action(); + add_root_node(new_node); editor->edit_node(new_node); editor_selection->clear(); @@ -1233,6 +1228,16 @@ void SceneTreeDock::_perform_property_drop(Node *p_node, String p_property, RES editor_data->get_undo_redo().add_undo_method(p_node, "property_list_changed_notify"); editor_data->get_undo_redo().commit_action(); } + +void SceneTreeDock::add_root_node(Node *p_node) { + editor_data->get_undo_redo().create_action(TTR("New Scene Root")); + editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", p_node); + editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree"); + editor_data->get_undo_redo().add_do_reference(p_node); + editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)nullptr); + editor_data->get_undo_redo().commit_action(); +} + void SceneTreeDock::_node_collapsed(Object *p_obj) { TreeItem *ti = Object::cast_to(p_obj); if (!ti) { diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index fea3b061fc4..9eeacfa3aeb 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -291,6 +291,7 @@ public: void show_tab_buttons(); void hide_tab_buttons(); + void add_root_node(Node *p_node); void replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties = true, bool p_remove_old = true); void attach_script_to_selected(bool p_extend);