diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 632285f48da..75bcedbbc83 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -37,6 +37,7 @@ #include "os/os.h" #include "project_settings.h" #include "scene/main/node.h" +#include "scene/resources/packed_scene.h" void ScriptDebuggerRemote::_send_video_memory() { @@ -148,6 +149,16 @@ void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_ } } +void ScriptDebuggerRemote::_save_node(ObjectID id, const String &p_path) { + + Node *node = Object::cast_to(ObjectDB::get_instance(id)); + ERR_FAIL_COND(!node); + + Ref ps = memnew(PackedScene); + ps->pack(node); + ResourceSaver::save(p_path, ps); +} + void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue) { //this function is called when there is a debugger break (bug on script) @@ -322,6 +333,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue) else remove_breakpoint(cmd[2], cmd[1]); + } else if (command == "save_node") { + _save_node(cmd[1], cmd[2]); } else { _parse_live_edit(cmd); } diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h index 2c4e29f172b..cc12d978d6c 100644 --- a/core/script_debugger_remote.h +++ b/core/script_debugger_remote.h @@ -133,6 +133,8 @@ class ScriptDebuggerRemote : public ScriptDebugger { void _put_variable(const String &p_name, const Variant &p_variable); + void _save_node(ObjectID id, const String &p_path); + public: struct ResourceUsage { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 50519e2c6e0..a83de1627d0 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -46,6 +46,7 @@ #include "scene/gui/tab_container.h" #include "scene/gui/texture_button.h" #include "scene/gui/tree.h" +#include "scene/resources/packed_scene.h" #include "ustring.h" class ScriptEditorDebuggerVariables : public Object { @@ -286,6 +287,30 @@ void ScriptEditorDebugger::_scene_tree_selected() { ppeer->put_var(msg); } +void ScriptEditorDebugger::_scene_tree_rmb_selected(const Vector2 &p_position) { + + TreeItem *item = inspect_scene_tree->get_item_at_position(p_position); + if (!item) + return; + + item->select(0); + + item_menu->clear(); + item_menu->add_icon_item(get_icon("CreateNewSceneFrom", "EditorIcons"), TTR("Save Branch as Scene"), ITEM_MENU_SAVE_REMOTE_NODE); + item_menu->set_global_position(get_global_mouse_position()); + item_menu->popup(); +} + +void ScriptEditorDebugger::_file_selected(const String &p_file) { + if (file_dialog->get_mode() == EditorFileDialog::MODE_SAVE_FILE) { + Array msg; + msg.push_back("save_node"); + msg.push_back(inspected_object_id); + msg.push_back(p_file); + ppeer->put_var(msg); + } +} + void ScriptEditorDebugger::_scene_tree_property_value_edited(const String &p_prop, const Variant &p_value) { Array msg; @@ -1754,6 +1779,21 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) { OS::get_singleton()->set_clipboard(title + "\n----------\n" + desc); } break; + case ITEM_MENU_SAVE_REMOTE_NODE: { + + file_dialog->set_access(EditorFileDialog::ACCESS_RESOURCES); + file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + + List extensions; + Ref sd = memnew(PackedScene); + ResourceSaver::get_recognized_extensions(sd, &extensions); + file_dialog->clear_filters(); + for (int i = 0; i < extensions.size(); i++) { + file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); + } + + file_dialog->popup_centered_ratio(); + } break; } } @@ -1788,6 +1828,8 @@ void ScriptEditorDebugger::_bind_methods() { ClassDB::bind_method(D_METHOD("_scene_tree_selected"), &ScriptEditorDebugger::_scene_tree_selected); ClassDB::bind_method(D_METHOD("_scene_tree_folded"), &ScriptEditorDebugger::_scene_tree_folded); + ClassDB::bind_method(D_METHOD("_scene_tree_rmb_selected"), &ScriptEditorDebugger::_scene_tree_rmb_selected); + ClassDB::bind_method(D_METHOD("_file_selected"), &ScriptEditorDebugger::_file_selected); ClassDB::bind_method(D_METHOD("live_debug_create_node"), &ScriptEditorDebugger::live_debug_create_node); ClassDB::bind_method(D_METHOD("live_debug_instance_node"), &ScriptEditorDebugger::live_debug_instance_node); @@ -1960,7 +2002,8 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { inspect_scene_tree->set_v_size_flags(SIZE_EXPAND_FILL); inspect_scene_tree->connect("cell_selected", this, "_scene_tree_selected"); inspect_scene_tree->connect("item_collapsed", this, "_scene_tree_folded"); - + inspect_scene_tree->set_allow_rmb_select(true); + inspect_scene_tree->connect("item_rmb_selected", this, "_scene_tree_rmb_selected"); auto_switch_remote_scene_tree = EDITOR_DEF("debugger/auto_switch_to_remote_scene_tree", false); inspect_scene_tree_timeout = EDITOR_DEF("debugger/remote_scene_tree_refresh_interval", 1.0); inspect_edited_object_timeout = EDITOR_DEF("debugger/remote_inspect_refresh_interval", 0.2); @@ -1968,6 +2011,12 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { updating_scene_tree = false; } + { // File dialog + file_dialog = memnew(EditorFileDialog); + file_dialog->connect("file_selected", this, "_file_selected"); + add_child(file_dialog); + } + { //profiler profiler = memnew(EditorProfiler); profiler->set_name(TTR("Profiler")); diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index 669d8737fe9..f7fe348b65e 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -65,6 +65,7 @@ class ScriptEditorDebugger : public Control { enum ItemMenu { ITEM_MENU_COPY_ERROR, + ITEM_MENU_SAVE_REMOTE_NODE, }; AcceptDialog *msgdialog; @@ -92,6 +93,7 @@ class ScriptEditorDebugger : public Control { Tree *inspect_scene_tree; Button *clearbutton; PopupMenu *item_menu; + EditorFileDialog *file_dialog; int error_count; int last_error_count; @@ -155,6 +157,8 @@ class ScriptEditorDebugger : public Control { void _scene_tree_folded(Object *obj); void _scene_tree_selected(); + void _scene_tree_rmb_selected(const Vector2 &p_position); + void _file_selected(const String &p_file); void _scene_tree_request(); void _parse_message(const String &p_msg, const Array &p_data); void _set_reason_text(const String &p_reason, MessageType p_type);