diff options
author | geequlim <geequlim@gmail.com> | 2017-10-17 22:37:25 +0800 |
---|---|---|
committer | Geequlim <geequlim@gmail.com> | 2017-11-17 09:20:32 +0800 |
commit | ccf76798d54c7ed70813346493b7f64264181f7c (patch) | |
tree | a7ead8b82ae57af5f47e959d40c49b5144d227f4 | |
parent | 475cee9c0fc7b1975de1c5380178763dc2c2df38 (diff) |
Send script members, contants and globals to debugger
Remove remote inspector panel
-rw-r--r-- | core/script_debugger_remote.cpp | 146 | ||||
-rw-r--r-- | editor/script_editor_debugger.cpp | 180 | ||||
-rw-r--r-- | editor/script_editor_debugger.h | 11 |
3 files changed, 217 insertions, 120 deletions
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index f77fb116c7..14f0cddb9c 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -35,6 +35,8 @@ #include "os/input.h" #include "os/os.h" #include "project_settings.h" +#include "scene/main/node.h" + void ScriptDebuggerRemote::_send_video_memory() { List<ResourceUsage> usage; @@ -201,20 +203,39 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue) List<String> members; List<Variant> member_vals; - + if (ScriptInstance *inst = p_script->debug_get_stack_level_instance(lv)) { + members.push_back("self"); + member_vals.push_back(inst->get_owner()); + } p_script->debug_get_stack_level_members(lv, &members, &member_vals); - ERR_CONTINUE(members.size() != member_vals.size()); List<String> locals; List<Variant> local_vals; - p_script->debug_get_stack_level_locals(lv, &locals, &local_vals); - ERR_CONTINUE(locals.size() != local_vals.size()); + List<String> globals; + List<Variant> globals_vals; + p_script->debug_get_globals(&globals, &globals_vals); + ERR_CONTINUE(globals.size() != globals_vals.size()); + packet_peer_stream->put_var("stack_frame_vars"); - packet_peer_stream->put_var(2 + locals.size() * 2 + members.size() * 2); + packet_peer_stream->put_var(3 + (locals.size() + members.size() + globals.size()) * 2); + + { //locals + packet_peer_stream->put_var(locals.size()); + + List<String>::Element *E = locals.front(); + List<Variant>::Element *F = local_vals.front(); + + while (E) { + _put_variable(E->get(), F->get()); + + E = E->next(); + F = F->next(); + } + } { //members packet_peer_stream->put_var(members.size()); @@ -231,11 +252,11 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue) } } - { //locals - packet_peer_stream->put_var(locals.size()); + { //globals + packet_peer_stream->put_var(globals.size()); - List<String>::Element *E = locals.front(); - List<Variant>::Element *F = local_vals.front(); + List<String>::Element *E = globals.front(); + List<Variant>::Element *F = globals_vals.front(); while (E) { _put_variable(E->get(), F->get()); @@ -532,56 +553,77 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { if (!obj) return; - List<PropertyInfo> pinfo; - obj->get_property_list(&pinfo, true); + typedef Pair<PropertyInfo, Variant> PropertyDesc; + List<PropertyDesc> properties; - int props_to_send = 0; - for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { + if (ScriptInstance *si = obj->get_script_instance()) { + if (!si->get_script().is_null()) { - if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) { - props_to_send++; - } - } + Set<StringName> members; + si->get_script()->get_members(&members); + for (Set<StringName>::Element *E = members.front(); E; E = E->next()) { - packet_peer_stream->put_var("message:inspect_object"); - packet_peer_stream->put_var(props_to_send * 5 + 4); - packet_peer_stream->put_var(p_id); - packet_peer_stream->put_var(obj->get_class()); - if (obj->is_class("Resource") || obj->is_class("Node")) - packet_peer_stream->put_var(obj->call("get_path")); - else - packet_peer_stream->put_var(""); + Variant m; + if (si->get(E->get(), m)) { + PropertyInfo pi(m.get_type(), String("Members/") + E->get()); + properties.push_back(PropertyDesc(pi, m)); + } + } - packet_peer_stream->put_var(props_to_send); + Map<StringName, Variant> constants; + si->get_script()->get_constants(&constants); + for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { + PropertyInfo pi(E->value().get_type(), (String("Constants/") + E->key())); + properties.push_back(PropertyDesc(pi, E->value())); + } + } + } + if (Node *node = Object::cast_to<Node>(obj)) { + PropertyInfo pi(Variant::NODE_PATH, String("Node/path")); + properties.push_front(PropertyDesc(pi, node->get_path())); + } else if (Resource *res = Object::cast_to<Resource>(obj)) { + if (Script *s = Object::cast_to<Script>(res)) { + Map<StringName, Variant> constants; + s->get_constants(&constants); + for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { + PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key()); + properties.push_front(PropertyDesc(pi, E->value())); + } + } + } + List<PropertyInfo> pinfo; + obj->get_property_list(&pinfo, true); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) { + properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name))); + } + } - if (E->get().usage & PROPERTY_USAGE_CATEGORY) { - packet_peer_stream->put_var("*" + E->get().name); - } else { - packet_peer_stream->put_var(E->get().name); - } - - Variant var = obj->get(E->get().name); - packet_peer_stream->put_var(E->get().type); - //only send information that can be sent.. - - int len = 0; //test how big is this to encode - encode_variant(var, NULL, len); + Array send_props; + for (int i = 0; i < properties.size(); i++) { + const PropertyInfo &pi = properties[i].first; + const Variant &var = properties[i].second; + RES res = var; - if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size - packet_peer_stream->put_var(PROPERTY_HINT_OBJECT_TOO_BIG); - packet_peer_stream->put_var(""); - packet_peer_stream->put_var(Variant()); - } else { - packet_peer_stream->put_var(E->get().hint); - packet_peer_stream->put_var(E->get().hint_string); - packet_peer_stream->put_var(var); - } - } + 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); + send_props.push_back(prop); } + + packet_peer_stream->put_var("message:inspect_object"); + packet_peer_stream->put_var(3); + packet_peer_stream->put_var(p_id); + packet_peer_stream->put_var(obj->get_class()); + packet_peer_stream->put_var(send_props); } void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value) { @@ -590,7 +632,11 @@ void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_p if (!obj) return; - obj->set(p_property, p_value); + String prop_name = p_property; + if (p_property.begins_with("Members/")) + prop_name = p_property.substr(8, p_property.length()); + + obj->set(prop_name, p_value); } void ScriptDebuggerRemote::_poll_events() { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index bc2423fffd..c2ef16571a 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<PropertyInfo> *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<PropertyInfo> prop_list; Map<StringName, Variant> 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 "<null>"; + } + 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<ObjectID, ScriptEditorDebuggerInspectedObject *>::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<PacketPeerStream>(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<StreamPeer>()); server->stop(); - memdelete(inspected_object); + _clear_remote_objects(); } diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index d18a625eef..d13048ce2b 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<ObjectID, ScriptEditorDebuggerInspectedObject *> remote_objects; Set<ObjectID> 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(); |