From ccf76798d54c7ed70813346493b7f64264181f7c Mon Sep 17 00:00:00 2001 From: geequlim Date: Tue, 17 Oct 2017 22:37:25 +0800 Subject: Send script members, contants and globals to debugger Remove remote inspector panel --- editor/script_editor_debugger.cpp | 180 ++++++++++++++++++++++++-------------- editor/script_editor_debugger.h | 11 ++- 2 files changed, 121 insertions(+), 70 deletions(-) (limited to 'editor') diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index bc2423fff..c2ef16571 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -116,7 +116,7 @@ class ScriptEditorDebuggerInspectedObject : public Object { protected: bool _set(const StringName &p_name, const Variant &p_value) { - if (!prop_values.has(p_name)) + if (!prop_values.has(p_name) || String(p_name).begins_with("Constants/")) return false; emit_signal("value_edited", p_name, p_value); @@ -132,6 +132,7 @@ protected: r_ret = prop_values[p_name]; return true; } + void _get_property_list(List *p_list) const { p_list->clear(); //sorry, no want category @@ -142,23 +143,52 @@ protected: static void _bind_methods() { + ClassDB::bind_method(D_METHOD("get_title"), &ScriptEditorDebuggerInspectedObject::get_title); + ClassDB::bind_method(D_METHOD("get_variant"), &ScriptEditorDebuggerInspectedObject::get_variant); + ClassDB::bind_method(D_METHOD("clear"), &ScriptEditorDebuggerInspectedObject::clear); + ClassDB::bind_method(D_METHOD("get_remote_object_id"), &ScriptEditorDebuggerInspectedObject::get_remote_object_id); + ADD_SIGNAL(MethodInfo("value_edited")); } public: - ObjectID last_edited_id; + String type_name; + ObjectID remote_object_id; List prop_list; Map prop_values; + ObjectID get_remote_object_id() { + return remote_object_id; + } + + String get_title() { + if (remote_object_id) + return TTR("Remote ") + String(type_name) + ": " + itos(remote_object_id); + else + return ""; + } + Variant get_variant(const StringName &p_name) { + + Variant var; + _get(p_name, var); + return var; + } + + void clear() { + + prop_list.clear(); + prop_values.clear(); + } void update() { _change_notify(); } - void update_single(const char *p_prop) { _change_notify(p_prop); } - ScriptEditorDebuggerInspectedObject() { last_edited_id = 0; } + ScriptEditorDebuggerInspectedObject() { + remote_object_id = 0; + } }; void ScriptEditorDebugger::debug_next() { @@ -297,7 +327,6 @@ Size2 ScriptEditorDebugger::get_minimum_size() const { void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_data) { if (p_msg == "debug_enter") { - Array msg; msg.push_back("get_stack_dump"); ppeer->put_var(msg); @@ -315,12 +344,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da if (error != "") { tabs->set_current_tab(0); } - profiler->set_enabled(false); - EditorNode::get_singleton()->get_pause_button()->set_pressed(true); - EditorNode::get_singleton()->make_bottom_panel_item_visible(this); + _clear_remote_objects(); } else if (p_msg == "debug_exit") { @@ -337,9 +364,8 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da //tabs->set_current_tab(0); profiler->set_enabled(true); profiler->disable_seeking(); - + inspector->edit(NULL); EditorNode::get_singleton()->get_pause_button()->set_pressed(false); - } else if (p_msg == "message:click_ctrl") { clicked_ctrl->set_text(p_data[0]); @@ -399,55 +425,57 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da le_set->set_disabled(false); } else if (p_msg == "message:inspect_object") { + ScriptEditorDebuggerInspectedObject *debugObj = NULL; + ObjectID id = p_data[0]; String type = p_data[1]; - Variant path = p_data[2]; //what to do yet, i don't know - int prop_count = p_data[3]; + Array properties = p_data[2]; - int idx = 4; - - if (inspected_object->last_edited_id != id) { - inspected_object->prop_list.clear(); - inspected_object->prop_values.clear(); + bool is_new_object = false; + if (remote_objects.has(id)) { + debugObj = remote_objects[id]; + } else { + debugObj = memnew(ScriptEditorDebuggerInspectedObject); + debugObj->remote_object_id = id; + debugObj->type_name = type; + remote_objects[id] = debugObj; + is_new_object = true; + debugObj->connect("value_edited", this, "_scene_tree_property_value_edited"); } - for (int i = 0; i < prop_count; i++) { + for (int i = 0; i < properties.size(); i++) { + + Array prop = properties[i]; + if (prop.size() != 6) + continue; PropertyInfo pinfo; - pinfo.name = p_data[idx++]; - pinfo.type = Variant::Type(int(p_data[idx++])); - pinfo.hint = PropertyHint(int(p_data[idx++])); - pinfo.hint_string = p_data[idx++]; - if (pinfo.name.begins_with("*")) { - pinfo.name = pinfo.name.substr(1, pinfo.name.length()); - pinfo.usage = PROPERTY_USAGE_CATEGORY; - } else { - pinfo.usage = PROPERTY_USAGE_EDITOR; + pinfo.name = prop[0]; + pinfo.type = Variant::Type(int(prop[1])); + pinfo.hint = PropertyHint(int(prop[2])); + pinfo.hint_string = prop[3]; + pinfo.usage = PropertyUsageFlags(int(prop[4])); + Variant var = prop[5]; + + String hint_string = pinfo.hint_string; + if (hint_string.begins_with("RES:") && hint_string != "RES:") { + String path = hint_string.substr(4, hint_string.length()); + var = ResourceLoader::load(path); } - if (inspected_object->last_edited_id != id) { + if (is_new_object) { //don't update.. it's the same, instead refresh - inspected_object->prop_list.push_back(pinfo); + debugObj->prop_list.push_back(pinfo); } - inspected_object->prop_values[pinfo.name] = p_data[idx++]; - - if (inspected_object->last_edited_id == id) { - //same, just update value, don't rebuild - inspected_object->update_single(pinfo.name.ascii().get_data()); - } + debugObj->prop_values[pinfo.name] = var; } - if (inspected_object->last_edited_id != id) { - //only if different - inspected_object->update(); + if (editor->get_editor_history()->get_current() != debugObj->get_instance_id()) { + editor->push_item(debugObj, ""); + } else { + debugObj->update(); } - - inspected_object->last_edited_id = id; - - tabs->set_current_tab(inspect_info->get_index()); - inspect_properties->edit(inspected_object); - } else if (p_msg == "message:video_mem") { vmem_tree->clear(); @@ -502,7 +530,6 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da int ofs = 0; int mcount = p_data[ofs]; - ofs++; for (int i = 0; i < mcount; i++) { @@ -521,12 +548,34 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da v = s.get_slice(":", 1).to_int(); } - variables->add_property("members/" + n, v, h, hs); + variables->add_property("Locals/" + n, v, h, hs); } - ofs += mcount * 2; + ofs += mcount * 2; mcount = p_data[ofs]; + ofs++; + for (int i = 0; i < mcount; i++) { + + String n = p_data[ofs + i * 2 + 0]; + Variant v = p_data[ofs + i * 2 + 1]; + PropertyHint h = PROPERTY_HINT_NONE; + String hs = String(); + + if (n.begins_with("*")) { + + n = n.substr(1, n.length()); + h = PROPERTY_HINT_OBJECT_ID; + String s = v; + s = s.replace("[", ""); + hs = s.get_slice(":", 0); + v = s.get_slice(":", 1).to_int(); + } + + variables->add_property("Members/" + n, v, h, hs); + } + ofs += mcount * 2; + mcount = p_data[ofs]; ofs++; for (int i = 0; i < mcount; i++) { @@ -545,7 +594,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da v = s.get_slice(":", 1).to_int(); } - variables->add_property("locals/" + n, v, h, hs); + variables->add_property("Globals/" + n, v, h, hs); } variables->update(); @@ -1133,7 +1182,6 @@ void ScriptEditorDebugger::stop() { le_set->set_disabled(true); profiler->set_enabled(true); - inspect_properties->edit(NULL); inspect_scene_tree->clear(); EditorNode::get_singleton()->get_pause_button()->set_pressed(false); @@ -1604,6 +1652,21 @@ void ScriptEditorDebugger::_paused() { } } +void ScriptEditorDebugger::_set_remote_object(ObjectID p_id, ScriptEditorDebuggerInspectedObject *p_obj) { + + if (remote_objects.has(p_id)) + memdelete(remote_objects[p_id]); + remote_objects[p_id] = p_obj; +} + +void ScriptEditorDebugger::_clear_remote_objects() { + + for (Map::Element *E = remote_objects.front(); E; E = E->next()) { + memdelete(E->value()); + } + remote_objects.clear(); +} + void ScriptEditorDebugger::_bind_methods() { ClassDB::bind_method(D_METHOD("_stack_dump_frame_selected"), &ScriptEditorDebugger::_stack_dump_frame_selected); @@ -1649,6 +1712,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { ppeer = Ref(memnew(PacketPeerStream)); ppeer->set_input_buffer_max_size(1024 * 1024 * 8); //8mb should be enough editor = p_editor; + editor->get_property_editor()->connect("object_id_selected", this, "_scene_tree_property_select_object"); tabs = memnew(TabContainer); tabs->set_tab_align(TabContainer::ALIGN_LEFT); @@ -1776,26 +1840,10 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { inspect_scene_tree->connect("cell_selected", this, "_scene_tree_selected"); inspect_scene_tree->connect("item_collapsed", this, "_scene_tree_folded"); - // - - VBoxContainer *info_right = memnew(VBoxContainer); - info_right->set_h_size_flags(SIZE_EXPAND_FILL); - inspect_info->add_child(info_right); - - inspect_properties = memnew(PropertyEditor); - inspect_properties->hide_top_label(); - inspect_properties->set_show_categories(true); - inspect_properties->connect("object_id_selected", this, "_scene_tree_property_select_object"); - - info_right->add_margin_child(TTR("Remote Object Properties: "), inspect_properties, true); - inspect_scene_tree_timeout = EDITOR_DEF("debugger/scene_tree_refresh_interval", 1.0); inspect_edited_object_timeout = EDITOR_DEF("debugger/remote_inspect_refresh_interval", 0.2); inspected_object_id = 0; updating_scene_tree = false; - - inspected_object = memnew(ScriptEditorDebuggerInspectedObject); - inspected_object->connect("value_edited", this, "_scene_tree_property_value_edited"); } { //profiler @@ -1952,5 +2000,5 @@ ScriptEditorDebugger::~ScriptEditorDebugger() { ppeer->set_stream_peer(Ref()); server->stop(); - memdelete(inspected_object); + _clear_remote_objects(); } diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index d18a625ee..d13048ce2 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -74,12 +74,13 @@ class ScriptEditorDebugger : public Control { Tree *inspect_scene_tree; HSplitContainer *inspect_info; - PropertyEditor *inspect_properties; + + bool updating_scene_tree; float inspect_scene_tree_timeout; float inspect_edited_object_timeout; ObjectID inspected_object_id; - ScriptEditorDebuggerInspectedObject *inspected_object; - bool updating_scene_tree; + ScriptEditorDebuggerVariables *variables; + Map remote_objects; Set unfold_cache; HSplitContainer *error_split; @@ -96,7 +97,6 @@ class ScriptEditorDebugger : public Control { TabContainer *tabs; Label *reason; - ScriptEditorDebuggerVariables *variables; Button *step; Button *next; @@ -174,6 +174,9 @@ class ScriptEditorDebugger : public Control { void _paused(); + void _set_remote_object(ObjectID p_id, ScriptEditorDebuggerInspectedObject *p_obj); + void _clear_remote_objects(); + protected: void _notification(int p_what); static void _bind_methods(); -- cgit v1.2.3-70-g09d2 From c655fc7cd89d17eb858b3c99e82402de61571bb0 Mon Sep 17 00:00:00 2001 From: geequlim Date: Tue, 17 Oct 2017 22:39:31 +0800 Subject: Better supported for remote object editing with the inspector with a simple dictionary editor implement --- editor/dictionary_property_edit.cpp | 189 ++++++++++++++++++++++++++++++++++++ editor/dictionary_property_edit.h | 62 ++++++++++++ editor/editor_node.cpp | 15 ++- editor/editor_path.cpp | 10 +- editor/property_editor.cpp | 36 +++++-- 5 files changed, 298 insertions(+), 14 deletions(-) create mode 100644 editor/dictionary_property_edit.cpp create mode 100644 editor/dictionary_property_edit.h (limited to 'editor') diff --git a/editor/dictionary_property_edit.cpp b/editor/dictionary_property_edit.cpp new file mode 100644 index 000000000..5b5a7ec9b --- /dev/null +++ b/editor/dictionary_property_edit.cpp @@ -0,0 +1,189 @@ +/*************************************************************************/ +/* dictionary_property_edit.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "dictionary_property_edit.h" +#include "editor_node.h" + +void DictionaryPropertyEdit::_notif_change() { + _change_notify(); +} + +void DictionaryPropertyEdit::_notif_changev(const String &p_v) { + _change_notify(p_v.utf8().get_data()); +} + +void DictionaryPropertyEdit::_set_key(const Variant &p_old_key, const Variant &p_new_key) { + + // TODO: Set key of a dictionary is not allowd yet + return; +} + +void DictionaryPropertyEdit::_set_value(const Variant &p_key, const Variant &p_value) { + + Dictionary dict = get_dictionary(); + dict[p_key] = p_value; + Object *o = ObjectDB::get_instance(obj); + if (!o) + return; + + o->set(property, dict); +} + +Variant DictionaryPropertyEdit::get_dictionary() const { + + Object *o = ObjectDB::get_instance(obj); + if (!o) + return Dictionary(); + Variant dict = o->get(property); + if (dict.get_type() != Variant::DICTIONARY) + return Dictionary(); + return dict; +} + +void DictionaryPropertyEdit::_get_property_list(List *p_list) const { + + Dictionary dict = get_dictionary(); + + Array keys = dict.keys(); + keys.sort(); + + for (int i = 0; i < keys.size(); i++) { + String index = itos(i); + + const Variant &key = keys[i]; + PropertyInfo pi(key.get_type(), index + ": key"); + p_list->push_back(pi); + + const Variant &value = dict[key]; + pi = PropertyInfo(value.get_type(), index + ": value"); + p_list->push_back(pi); + } +} + +void DictionaryPropertyEdit::edit(Object *p_obj, const StringName &p_prop) { + + property = p_prop; + obj = p_obj->get_instance_id(); +} + +Node *DictionaryPropertyEdit::get_node() { + + Object *o = ObjectDB::get_instance(obj); + if (!o) + return NULL; + + return cast_to(o); +} + +void DictionaryPropertyEdit::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_set_key"), &DictionaryPropertyEdit::_set_key); + ClassDB::bind_method(D_METHOD("_set_value"), &DictionaryPropertyEdit::_set_value); + ClassDB::bind_method(D_METHOD("_notif_change"), &DictionaryPropertyEdit::_notif_change); + ClassDB::bind_method(D_METHOD("_notif_changev"), &DictionaryPropertyEdit::_notif_changev); +} + +bool DictionaryPropertyEdit::_set(const StringName &p_name, const Variant &p_value) { + + Dictionary dict = get_dictionary(); + Array keys = dict.keys(); + keys.sort(); + + String pn = p_name; + int slash = pn.find(": "); + if (slash != -1 && pn.length() > slash) { + String type = pn.substr(slash + 2, pn.length()); + int index = pn.substr(0, slash).to_int(); + if (type == "key" && index < keys.size()) { + + const Variant &key = keys[index]; + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + + ur->create_action(TTR("Change Dictionary Key")); + ur->add_do_method(this, "_set_key", key, p_value); + ur->add_undo_method(this, "_set_key", p_value, key); + ur->add_do_method(this, "_notif_changev", p_name); + ur->add_undo_method(this, "_notif_changev", p_name); + ur->commit_action(); + + return true; + } else if (type == "value" && index < keys.size()) { + const Variant &key = keys[index]; + if (dict.has(key)) { + + Variant value = dict[key]; + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + + ur->create_action(TTR("Change Dictionary Value")); + ur->add_do_method(this, "_set_value", key, p_value); + ur->add_undo_method(this, "_set_value", key, value); + ur->add_do_method(this, "_notif_changev", p_name); + ur->add_undo_method(this, "_notif_changev", p_name); + ur->commit_action(); + + return true; + } + } + } + + return false; +} + +bool DictionaryPropertyEdit::_get(const StringName &p_name, Variant &r_ret) const { + + Dictionary dict = get_dictionary(); + Array keys = dict.keys(); + keys.sort(); + + String pn = p_name; + int slash = pn.find(": "); + + if (slash != -1 && pn.length() > slash) { + + String type = pn.substr(slash + 2, pn.length()); + int index = pn.substr(0, slash).to_int(); + + if (type == "key" && index < keys.size()) { + r_ret = keys[index]; + return true; + } else if (type == "value" && index < keys.size()) { + const Variant &key = keys[index]; + if (dict.has(key)) { + r_ret = dict[key]; + return true; + } + } + } + + return false; +} + +DictionaryPropertyEdit::DictionaryPropertyEdit() { + obj = 0; +} diff --git a/editor/dictionary_property_edit.h b/editor/dictionary_property_edit.h new file mode 100644 index 000000000..7a86727fb --- /dev/null +++ b/editor/dictionary_property_edit.h @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* dictionary_property_edit.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef DICTIONARY_PROPERTY_EDIT_H +#define DICTIONARY_PROPERTY_EDIT_H + +#include "scene/main/node.h" + +class DictionaryPropertyEdit : public Reference { + GDCLASS(DictionaryPropertyEdit, Reference); + + ObjectID obj; + StringName property; + + void _notif_change(); + void _notif_changev(const String &p_v); + void _set_key(const Variant &p_old_key, const Variant &p_new_key); + void _set_value(const Variant &p_key, const Variant &p_value); + + Variant get_dictionary() const; + +protected: + static void _bind_methods(); + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List *p_list) const; + +public: + void edit(Object *p_obj, const StringName &p_prop); + + Node *get_node(); + + DictionaryPropertyEdit(); +}; + +#endif // DICTIONARY_PROPERTY_EDIT_H diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index b3a8490fe..e8b341c97 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -283,8 +283,7 @@ void EditorNode::_notification(int p_what) { if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/editor/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); - property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true))); - Ref theme = create_custom_theme(theme_base->get_theme()); + Ref theme = create_editor_theme(theme_base->get_theme()); theme_base->set_theme(theme); gui_base->set_theme(theme); @@ -1330,6 +1329,8 @@ void EditorNode::_prepare_history() { } } else if (Object::cast_to(obj)) { text = Object::cast_to(obj)->get_name(); + } else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) { + text = obj->call("get_title"); } else { text = obj->get_class(); } @@ -1425,6 +1426,7 @@ void EditorNode::_edit_current() { object_menu->set_disabled(true); + bool capitalize = bool(EDITOR_DEF("interface/editor/capitalize_properties", true)); bool is_resource = current_obj->is_class("Resource"); bool is_node = current_obj->is_class("Node"); resource_save_button->set_disabled(!is_resource); @@ -1478,6 +1480,11 @@ void EditorNode::_edit_current() { } else { + if (current_obj->is_class("ScriptEditorDebuggerInspectedObject")) { + editable_warning = TTR("This is a remote object so changes to it will not be kept.\nPlease read the documentation relevant to debugging to better understand this workflow."); + capitalize = false; + } + property_editor->edit(current_obj); node_dock->set_node(NULL); } @@ -1487,6 +1494,10 @@ void EditorNode::_edit_current() { property_editable_warning_dialog->set_text(editable_warning); } + if (property_editor->is_capitalize_paths_enabled() != capitalize) { + property_editor->set_enable_capitalize_paths(capitalize); + } + /* Take care of PLUGIN EDITOR */ EditorPlugin *main_plugin = editor_data.get_editor(current_obj); diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index 0587939a1..f0d3c29c1 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -149,14 +149,14 @@ void EditorPath::_notification(int p_what) { if (name == "") name = r->get_class(); - } else if (Object::cast_to(obj)) { - + } else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) + name = obj->call("get_title"); + else if (Object::cast_to(obj)) name = Object::cast_to(obj)->get_name(); - } else if (Object::cast_to(obj) && Object::cast_to(obj)->get_name() != "") { + else if (Object::cast_to(obj) && Object::cast_to(obj)->get_name() != "") name = Object::cast_to(obj)->get_name(); - } else { + else name = obj->get_class(); - } set_tooltip(obj->get_class()); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 002ae568f..2c6418136 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -40,6 +40,7 @@ #include "core/project_settings.h" #include "editor/array_property_edit.h" #include "editor/create_dialog.h" +#include "editor/dictionary_property_edit.h" #include "editor/editor_export.h" #include "editor/editor_file_system.h" #include "editor/editor_help.h" @@ -1153,7 +1154,8 @@ void CustomPropertyEditor::_node_path_selected(NodePath p_path) { node = Object::cast_to(owner); else if (owner->is_class("ArrayPropertyEdit")) node = Object::cast_to(owner)->get_node(); - + else if (owner->is_class("DictionaryPropertyEdit")) + node = Object::cast_to(owner)->get_node(); if (!node) { v = p_path; emit_signal("variant_changed"); @@ -3211,9 +3213,14 @@ void PropertyEditor::update_tree() { } break; case Variant::DICTIONARY: { + Variant v = obj->get(p.name); + item->set_cell_mode(1, TreeItem::CELL_MODE_STRING); - item->set_editable(1, false); - item->set_text(1, obj->get(p.name).operator String()); + item->set_text(1, String("Dictionary{") + itos(v.call("size")) + "}"); + item->add_button(1, get_icon("EditResource", "EditorIcons")); + + if (show_type_icons) + item->set_icon(0, get_icon("DictionaryData", "EditorIcons")); } break; @@ -3412,7 +3419,9 @@ void PropertyEditor::update_tree() { type = p.hint_string; RES res = obj->get(p.name).operator RefPtr(); - + if (type.begins_with("RES:") && type != "RES:") { // Remote resources + res = ResourceLoader::load(type.substr(4, type.length())); + } Ref encoded = obj->get(p.name); //for debugger and remote tools if (encoded.is_valid()) { @@ -3423,6 +3432,7 @@ void PropertyEditor::update_tree() { item->set_editable(1, true); } else if (obj->get(p.name).get_type() == Variant::NIL || res.is_null()) { + item->set_text(1, ""); item->set_icon(1, Ref()); item->set_custom_as_button(1, false); @@ -3581,7 +3591,7 @@ void PropertyEditor::_edit_set(const String &p_name, const Variant &p_value, boo } } - if (!undo_redo || Object::cast_to(obj)) { //kind of hacky + if (!undo_redo || Object::cast_to(obj) || Object::cast_to(obj)) { //kind of hacky obj->set(p_name, p_value); if (p_refresh_all) @@ -3714,7 +3724,7 @@ void PropertyEditor::_item_edited() { _edit_set(name, item->get_text(1), refresh_all); } } break; - // math types + // math types case Variant::VECTOR3: { @@ -3979,8 +3989,20 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) { Ref ape = memnew(ArrayPropertyEdit); ape->edit(obj, n, ht, Variant::Type(t)); - EditorNode::get_singleton()->push_item(ape.ptr()); + + } else if (t == Variant::DICTIONARY) { + + Variant v = obj->get(n); + + if (v.get_type() != t) { + Variant::CallError ce; + v = Variant::construct(Variant::Type(t), NULL, 0, ce); + } + + Ref dpe = memnew(DictionaryPropertyEdit); + dpe->edit(obj, n); + EditorNode::get_singleton()->push_item(dpe.ptr()); } } } -- cgit v1.2.3-70-g09d2 From fab66af7e99eb71ea6a2df30bea46835f749896a Mon Sep 17 00:00:00 2001 From: Geequlim Date: Thu, 16 Nov 2017 17:18:36 +0800 Subject: Move the remote scene tree to the scene tree dock. Ignore all script constants in the global section of the breakpoint stack. Check property size before send to avoid too large of data be sent. Fix crash while clear the remote objects from the debugger. --- core/script_debugger_remote.cpp | 25 ++++++++++++++++++------- editor/scene_tree_dock.cpp | 2 ++ editor/script_editor_debugger.cpp | 19 +++++++++---------- editor/script_editor_debugger.h | 4 +--- modules/gdscript/gdscript_editor.cpp | 21 +++++++++++++++++---- 5 files changed, 47 insertions(+), 24 deletions(-) (limited to 'editor') diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 14f0cddb9..56056268f 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -609,13 +609,24 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { Array prop; prop.push_back(pi.name); prop.push_back(pi.type); - prop.push_back(pi.hint); - if (res.is_null()) - prop.push_back(pi.hint_string); - else - prop.push_back(String("RES:") + res->get_path()); - prop.push_back(pi.usage); - prop.push_back(var); + + //only send information that can be sent.. + int len = 0; //test how big is this to encode + encode_variant(var, NULL, len); + if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size + prop.push_back(PROPERTY_HINT_OBJECT_TOO_BIG); + prop.push_back(""); + prop.push_back(pi.usage); + prop.push_back(Variant()); + } else { + prop.push_back(pi.hint); + if (res.is_null()) + prop.push_back(pi.hint_string); + else + prop.push_back(String("RES:") + res->get_path()); + prop.push_back(pi.usage); + prop.push_back(var); + } send_props.push_back(prop); } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 816156ef0..94f218757 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1923,6 +1923,8 @@ void SceneTreeDock::_local_tree_selected() { remote_tree->hide(); edit_remote->set_pressed(false); edit_local->set_pressed(true); + + _node_selected(); } void SceneTreeDock::_bind_methods() { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index c2ef16571..2a3e47b2a 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -1150,6 +1150,8 @@ void ScriptEditorDebugger::start() { EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), true); return; } + + EditorNode::get_singleton()->get_scene_tree_dock()->show_remote_tree(); set_process(true); } @@ -1186,6 +1188,7 @@ void ScriptEditorDebugger::stop() { EditorNode::get_singleton()->get_pause_button()->set_pressed(false); EditorNode::get_singleton()->get_pause_button()->set_disabled(true); + EditorNode::get_singleton()->get_scene_tree_dock()->hide_remote_tree(); if (hide_on_stop) { if (is_visible_in_tree()) @@ -1662,6 +1665,9 @@ void ScriptEditorDebugger::_set_remote_object(ObjectID p_id, ScriptEditorDebugge void ScriptEditorDebugger::_clear_remote_objects() { for (Map::Element *E = remote_objects.front(); E; E = E->next()) { + if (editor->get_editor_history()->get_current() == E->value()->get_instance_id()) { + editor->push_item(NULL); + } memdelete(E->value()); } remote_objects.clear(); @@ -1825,18 +1831,11 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { tabs->add_child(error_split); } - { // inquire - - inspect_info = memnew(HSplitContainer); - inspect_info->set_name(TTR("Remote Inspector")); - tabs->add_child(inspect_info); - - VBoxContainer *info_left = memnew(VBoxContainer); - info_left->set_h_size_flags(SIZE_EXPAND_FILL); - inspect_info->add_child(info_left); + { // remote scene tree inspect_scene_tree = memnew(Tree); - info_left->add_margin_child(TTR("Live Scene Tree:"), inspect_scene_tree, true); + EditorNode::get_singleton()->get_scene_tree_dock()->add_remote_tree_editor(inspect_scene_tree); + 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"); diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index d13048ce2..dc851dd57 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -72,9 +72,6 @@ class ScriptEditorDebugger : public Control { Button *le_set; Button *le_clear; - Tree *inspect_scene_tree; - HSplitContainer *inspect_info; - bool updating_scene_tree; float inspect_scene_tree_timeout; float inspect_edited_object_timeout; @@ -86,6 +83,7 @@ class ScriptEditorDebugger : public Control { HSplitContainer *error_split; ItemList *error_list; ItemList *error_stack; + Tree *inspect_scene_tree; int error_count; int last_error_count; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index de7adc7e4..5a76acea6 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -33,7 +33,7 @@ #include "gdscript_compiler.h" #include "global_constants.h" #include "os/file_access.h" -#include "project_settings.h" +#include "core/engine.h" #ifdef TOOLS_ENABLED #include "editor/editor_file_system.h" @@ -287,7 +287,7 @@ ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) { ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, NULL); int l = _debug_call_stack_pos - p_level - 1; - GDInstance *instance = _call_stack[l].instance; + ScriptInstance *instance = _call_stack[l].instance; return instance; } @@ -297,14 +297,27 @@ void GDScriptLanguage::debug_get_globals(List *p_globals, List const Map &name_idx = GDScriptLanguage::get_singleton()->get_global_map(); const Variant *globals = GDScriptLanguage::get_singleton()->get_global_array(); + List > cinfo; + get_public_constants(&cinfo); + for (const Map::Element *E = name_idx.front(); E; E = E->next()) { - if (ClassDB::class_exists(E->key()) || ProjectSettings::get_singleton()->has_singleton(E->key()) || E->key() == "PI" || E->key() == "INF" || E->key() == "NAN") + if (ClassDB::class_exists(E->key()) || Engine::get_singleton()->has_singleton(E->key())) + continue; + + bool is_script_constant = false; + for (List >::Element *CE = cinfo.front(); CE; CE = CE->next()) { + if (CE->get().first == E->key()) { + is_script_constant = true; + break; + } + } + if (is_script_constant) continue; const Variant &var = globals[E->value()]; if (Object *obj = var) { - if (Object::cast_to(obj)) + if (Object::cast_to(obj)) continue; } -- cgit v1.2.3-70-g09d2