summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/object.cpp2
-rw-r--r--core/object.h1
-rw-r--r--core/script_debugger_remote.cpp99
-rw-r--r--core/script_debugger_remote.h3
-rw-r--r--scene/main/scene_main_loop.cpp1
-rw-r--r--tools/editor/property_editor.cpp32
-rw-r--r--tools/editor/script_editor_debugger.cpp725
-rw-r--r--tools/editor/script_editor_debugger.h28
8 files changed, 663 insertions, 228 deletions
diff --git a/core/object.cpp b/core/object.cpp
index 7f4db7c8b5..3cfc0329bc 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1396,7 +1396,7 @@ Error Object::connect(const StringName& p_signal, Object *p_to_object, const Str
signal_is_valid=true;
if (!signal_is_valid) {
- ERR_EXPLAIN("Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_method+"'");
+ ERR_EXPLAIN("In Object of type '"+String(get_type())+"': Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_object->get_type()+"."+p_to_method+"'");
ERR_FAIL_COND_V(!signal_is_valid,ERR_INVALID_PARAMETER);
}
signal_map[p_signal]=Signal();
diff --git a/core/object.h b/core/object.h
index c34440100f..3945d1d0ba 100644
--- a/core/object.h
+++ b/core/object.h
@@ -67,6 +67,7 @@ enum PropertyHint {
PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
PROPERTY_HINT_IMAGE_COMPRESS_LOSSY,
PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS,
+ PROPERTY_HINT_OBJECT_ID,
PROPERTY_HINT_MAX,
};
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 10e1b65cf3..011b1f78a0 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -283,6 +283,14 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
} else if (command=="request_video_mem") {
_send_video_memory();
+ } else if (command=="inspect_object") {
+
+ ObjectID id = cmd[1];
+ _send_object_id(id);
+ } else if (command=="set_object_property") {
+
+ _set_object_property(cmd[1],cmd[2],cmd[3]);
+
} else if (command=="breakpoint") {
bool set = cmd[3];
@@ -539,6 +547,89 @@ bool ScriptDebuggerRemote::_parse_live_edit(const Array& cmd) {
return true;
}
+
+void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
+
+ Object* obj = ObjectDB::get_instance(p_id);
+ if (!obj)
+ return;
+
+ List<PropertyInfo> pinfo;
+ obj->get_property_list(&pinfo,true);
+
+ int props_to_send=0;
+ for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+ if (E->get().usage&(PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CATEGORY)) {
+ props_to_send++;
+ }
+ }
+
+ 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_type());
+ if (obj->is_type("Resource") || obj->is_type("Node"))
+ packet_peer_stream->put_var(obj->call("get_path"));
+ else
+ packet_peer_stream->put_var("");
+
+ packet_peer_stream->put_var(props_to_send);
+
+ for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+ if (E->get().usage&(PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CATEGORY)) {
+
+ 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);
+
+ if (E->get().type==Variant::OBJECT || var.get_type()==Variant::OBJECT) {
+
+ ObjectID id2;
+ Object *obj=var;
+ if (obj) {
+ id2=obj->get_instance_ID();
+ } else {
+ id2=0;
+ }
+
+ packet_peer_stream->put_var(Variant::INT); //hint string
+ packet_peer_stream->put_var(PROPERTY_HINT_OBJECT_ID); //hint
+ packet_peer_stream->put_var(E->get().hint_string); //hint string
+ packet_peer_stream->put_var(id2); //value
+ } else {
+ packet_peer_stream->put_var(E->get().type);
+ packet_peer_stream->put_var(E->get().hint);
+ packet_peer_stream->put_var(E->get().hint_string);
+ //only send information that can be sent..
+ if (var.get_type()==Variant::IMAGE) {
+ var=Image();
+ }
+ if (var.get_type()>=Variant::DICTIONARY) {
+ var=Array(); //send none for now, may be to big
+ }
+ packet_peer_stream->put_var(var);
+ }
+
+ }
+ }
+
+}
+
+void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String& p_property, const Variant& p_value) {
+
+ Object* obj = ObjectDB::get_instance(p_id);
+ if (!obj)
+ return;
+
+ obj->set(p_property,p_value);
+}
+
void ScriptDebuggerRemote::_poll_events() {
//this si called from ::idle_poll, happens only when running the game,
@@ -575,6 +666,14 @@ void ScriptDebuggerRemote::_poll_events() {
} else if (command=="request_video_mem") {
_send_video_memory();
+ } else if (command=="inspect_object") {
+
+ ObjectID id = cmd[1];
+ _send_object_id(id);
+ } else if (command=="set_object_property") {
+
+ _set_object_property(cmd[1],cmd[2],cmd[3]);
+
} else if (command=="start_profiling") {
for(int i=0;i<ScriptServer::get_language_count();i++) {
diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h
index a19b4ed2bd..8fdab47013 100644
--- a/core/script_debugger_remote.h
+++ b/core/script_debugger_remote.h
@@ -111,6 +111,9 @@ class ScriptDebuggerRemote : public ScriptDebugger {
RequestSceneTreeMessageFunc request_scene_tree;
void *request_scene_tree_ud;
+ void _set_object_property(ObjectID p_id, const String& p_property, const Variant& p_value);
+
+ void _send_object_id(ObjectID p_id);
void _send_video_memory();
LiveEditFuncs *live_edit_funcs;
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index b83ad7381e..24fe1e1bb3 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -1002,6 +1002,7 @@ static void _fill_array(Node *p_node, Array& array, int p_level) {
array.push_back(p_level);
array.push_back(p_node->get_name());
array.push_back(p_node->get_type());
+ array.push_back(p_node->get_instance_ID());
for(int i=0;i<p_node->get_child_count();i++) {
_fill_array(p_node->get_child(i),array,p_level+1);
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index f94ca48ec2..afc6396ab3 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -2989,6 +2989,32 @@ void PropertyEditor::update_tree() {
item->set_range(1, obj->get( p.name ) );
item->set_editable(1,!read_only);
break;
+ } else if (p.hint==PROPERTY_HINT_OBJECT_ID) {
+
+// int c = p.hint_string.get_slice_count(",");
+ item->set_cell_mode(1,TreeItem::CELL_MODE_CUSTOM);
+
+ String type=p.hint_string;
+ if (type=="")
+ type="Object";
+
+ ObjectID id = obj->get( p.name );
+ if (id!=0) {
+ item->set_text(1,type+" ID: "+itos(id));
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+ } else {
+ item->set_text(1,"[Empty]");
+ }
+
+ if (has_icon(p.hint_string,"EditorIcons")) {
+ type=p.hint_string;
+ } else {
+ type="Object";
+ }
+
+ item->set_icon(0,get_icon(type,"EditorIcons"));
+
+ break;
} else {
if (p.type == Variant::REAL) {
@@ -3758,6 +3784,11 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
emit_signal("resource_selected",r,n);
}
+ } else if (t==Variant::INT && h==PROPERTY_HINT_OBJECT_ID) {
+
+ emit_signal("object_id_selected",obj->get(n));
+ print_line("OBJ ID SELECTED");
+
} else if (t==Variant::ARRAY || t==Variant::INT_ARRAY || t==Variant::REAL_ARRAY || t==Variant::STRING_ARRAY || t==Variant::VECTOR2_ARRAY || t==Variant::VECTOR3_ARRAY || t==Variant::COLOR_ARRAY || t==Variant::RAW_ARRAY) {
Variant v = obj->get(n);
@@ -3860,6 +3891,7 @@ void PropertyEditor::_bind_methods() {
ADD_SIGNAL( MethodInfo("property_toggled",PropertyInfo( Variant::STRING, "property"),PropertyInfo( Variant::BOOL, "value")));
ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) );
+ ADD_SIGNAL( MethodInfo("object_id_selected", PropertyInfo( Variant::INT, "id")) );
ADD_SIGNAL( MethodInfo("property_keyed",PropertyInfo( Variant::STRING, "property")));
ADD_SIGNAL( MethodInfo("property_edited",PropertyInfo( Variant::STRING, "property")));
}
diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp
index 12840ee4c5..479b694f0b 100644
--- a/tools/editor/script_editor_debugger.cpp
+++ b/tools/editor/script_editor_debugger.cpp
@@ -111,6 +111,68 @@ public:
}
};
+
+class ScriptEditorDebuggerInspectedObject : public Object {
+
+ OBJ_TYPE( ScriptEditorDebuggerInspectedObject, Object);
+
+
+
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ if (!prop_values.has(p_name))
+ return false;
+
+ emit_signal("value_edited",p_name,p_value);
+ prop_values[p_name]=p_value;
+ return true;
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const {
+
+ if (!prop_values.has(p_name))
+ return false;
+
+ r_ret=prop_values[p_name];
+ return true;
+
+ }
+ void _get_property_list( List<PropertyInfo> *p_list) const {
+
+ p_list->clear(); //sorry, no want category
+ for (const List<PropertyInfo>::Element *E=prop_list.front();E;E=E->next()) {
+ p_list->push_back(E->get());
+ }
+ }
+
+
+ static void _bind_methods() {
+
+ ADD_SIGNAL(MethodInfo("value_edited"));
+ }
+
+public:
+
+ ObjectID last_edited_id;
+ List<PropertyInfo> prop_list;
+ Map<StringName,Variant> prop_values;
+
+ void update() {
+ _change_notify();
+ }
+
+ void update_single(const char* p_prop) {
+ _change_notify(p_prop);
+ }
+
+ ScriptEditorDebuggerInspectedObject() { last_edited_id=0; }
+
+
+};
+
void ScriptEditorDebugger::debug_next() {
ERR_FAIL_COND(!breaked);
@@ -160,6 +222,72 @@ void ScriptEditorDebugger::debug_continue() {
}
+void ScriptEditorDebugger::_scene_tree_folded(Object* obj) {
+
+
+ if (updating_scene_tree) {
+
+ return;
+ }
+ TreeItem *item=obj->cast_to<TreeItem>();
+
+ if (!item)
+ return;
+
+ ObjectID id = item->get_metadata(0);
+ if (item->is_collapsed()) {
+ unfold_cache.erase(id);
+ } else {
+ unfold_cache.insert(id);
+ }
+
+
+}
+
+void ScriptEditorDebugger::_scene_tree_selected() {
+
+
+ if (updating_scene_tree) {
+
+ return;
+ }
+ TreeItem *item = inspect_scene_tree->get_selected();
+ if (!item) {
+
+ return;
+ }
+
+ inspected_object_id = item->get_metadata(0);
+
+ Array msg;
+ msg.push_back("inspect_object");
+ msg.push_back(inspected_object_id);
+ ppeer->put_var(msg);
+
+}
+
+void ScriptEditorDebugger::_scene_tree_property_value_edited(const String& p_prop,const Variant& p_value) {
+
+
+ Array msg;
+ msg.push_back("set_object_property");
+ msg.push_back(inspected_object_id);
+ msg.push_back(p_prop);
+ msg.push_back(p_value);
+ ppeer->put_var(msg);
+ inspect_edited_object_timeout=0.7; //avoid annoyance, don't request soon after editing
+}
+
+void ScriptEditorDebugger::_scene_tree_property_select_object(ObjectID p_object) {
+
+ inspected_object_id=p_object;
+ Array msg;
+ msg.push_back("inspect_object");
+ msg.push_back(inspected_object_id);
+ ppeer->put_var(msg);
+
+}
+
void ScriptEditorDebugger::_scene_tree_request() {
ERR_FAIL_COND(connection.is_null());
@@ -246,10 +374,12 @@ void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_dat
} else if (p_msg=="message:scene_tree") {
- scene_tree->clear();
+ inspect_scene_tree->clear();
Map<int,TreeItem*> lv;
- for(int i=0;i<p_data.size();i+=3) {
+ updating_scene_tree=true;
+
+ for(int i=0;i<p_data.size();i+=4) {
TreeItem *p;
int level = p_data[i];
@@ -260,15 +390,90 @@ void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_dat
p=lv[level-1];
}
- TreeItem *it = scene_tree->create_item(p);
+
+ TreeItem *it = inspect_scene_tree->create_item(p);
+
+ ObjectID id = ObjectID(p_data[i+3]);
+
it->set_text(0,p_data[i+1]);
if (has_icon(p_data[i+2],"EditorIcons"))
it->set_icon(0,get_icon(p_data[i+2],"EditorIcons"));
+ it->set_metadata(0,id);
+ if (id==inspected_object_id) {
+ it->select(0);
+ }
+
+ if (p) {
+ if (!unfold_cache.has(id)) {
+ it->set_collapsed(true);
+ }
+ } else {
+ if (unfold_cache.has(id)) { //reverse for root
+ it->set_collapsed(true);
+ }
+ }
lv[level]=it;
}
+ updating_scene_tree=false;
le_clear->set_disabled(false);
le_set->set_disabled(false);
+ } else if (p_msg=="message:inspect_object") {
+
+
+ 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];
+
+ int idx=4;
+
+
+ if (inspected_object->last_edited_id!=id) {
+ inspected_object->prop_list.clear();
+ inspected_object->prop_values.clear();
+ }
+
+ for(int i=0;i<prop_count;i++) {
+
+ 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;
+ }
+
+ if (inspected_object->last_edited_id!=id) {
+ //don't update.. it's the same, instead refresh
+ inspected_object->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());
+ }
+
+ }
+
+
+
+ if (inspected_object->last_edited_id!=id) {
+ //only if different
+ inspected_object->update();
+ }
+
+ inspected_object->last_edited_id=id;
+
+
+ inspect_properties->edit(inspected_object);
} else if (p_msg=="message:video_mem") {
@@ -684,7 +889,7 @@ void ScriptEditorDebugger::_notification(int p_what) {
forward->set_icon( get_icon("Forward","EditorIcons"));
dobreak->set_icon( get_icon("Pause","EditorIcons"));
docontinue->set_icon( get_icon("DebugContinue","EditorIcons"));
- scene_tree_refresh->set_icon( get_icon("Reload","EditorIcons"));
+ //scene_tree_refresh->set_icon( get_icon("Reload","EditorIcons"));
le_set->connect("pressed",this,"_live_edit_set");
le_clear->connect("pressed",this,"_live_edit_clear");
error_list->connect("item_selected",this,"_error_selected");
@@ -694,6 +899,36 @@ void ScriptEditorDebugger::_notification(int p_what) {
} break;
case NOTIFICATION_PROCESS: {
+ if (connection.is_valid()) {
+ inspect_scene_tree_timeout-=get_process_delta_time();
+ if (inspect_scene_tree_timeout<0) {
+ inspect_scene_tree_timeout=EditorSettings::get_singleton()->get("debugger/scene_tree_refresh_interval");
+ if (inspect_scene_tree->is_visible()) {
+ _scene_tree_request();
+
+ if (inspected_object_id!=0) {
+ //take the chance and re-inspect selected object
+ Array msg;
+ msg.push_back("inspect_object");
+ msg.push_back(inspected_object_id);
+ ppeer->put_var(msg);
+ }
+ }
+ }
+
+ inspect_edited_object_timeout-=get_process_delta_time();
+ if (inspect_edited_object_timeout<0) {
+ inspect_edited_object_timeout=EditorSettings::get_singleton()->get("debugger/remote_inspect_refresh_interval");
+ if (inspect_scene_tree->is_visible() && inspected_object_id) {
+ //take the chance and re-inspect selected object
+ Array msg;
+ msg.push_back("inspect_object");
+ msg.push_back(inspected_object_id);
+ ppeer->put_var(msg);
+ }
+ }
+ }
+
if (error_count!=last_error_count) {
if (error_count==0) {
@@ -732,7 +967,7 @@ void ScriptEditorDebugger::_notification(int p_what) {
reason->set_tooltip(TTR("Child Process Connected"));
profiler->clear();
- scene_tree->clear();
+ inspect_scene_tree->clear();
le_set->set_disabled(true);
le_clear->set_disabled(false);
error_list->clear();
@@ -904,6 +1139,9 @@ 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);
EditorNode::get_singleton()->get_pause_button()->set_disabled(true);
@@ -1191,7 +1429,7 @@ void ScriptEditorDebugger::_live_edit_set() {
if (!connection.is_valid())
return;
- TreeItem* ti = scene_tree->get_selected();
+ TreeItem* ti = inspect_scene_tree->get_selected();
if (!ti)
return;
String path;
@@ -1408,6 +1646,9 @@ void ScriptEditorDebugger::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_paused"),&ScriptEditorDebugger::_paused);
+ ObjectTypeDB::bind_method(_MD("_scene_tree_selected"),&ScriptEditorDebugger::_scene_tree_selected);
+ ObjectTypeDB::bind_method(_MD("_scene_tree_folded"),&ScriptEditorDebugger::_scene_tree_folded);
+
ObjectTypeDB::bind_method(_MD("live_debug_create_node"),&ScriptEditorDebugger::live_debug_create_node);
ObjectTypeDB::bind_method(_MD("live_debug_instance_node"),&ScriptEditorDebugger::live_debug_instance_node);
@@ -1416,6 +1657,8 @@ void ScriptEditorDebugger::_bind_methods() {
ObjectTypeDB::bind_method(_MD("live_debug_restore_node"),&ScriptEditorDebugger::live_debug_restore_node);
ObjectTypeDB::bind_method(_MD("live_debug_duplicate_node"),&ScriptEditorDebugger::live_debug_duplicate_node);
ObjectTypeDB::bind_method(_MD("live_debug_reparent_node"),&ScriptEditorDebugger::live_debug_reparent_node);
+ ObjectTypeDB::bind_method(_MD("_scene_tree_property_select_object"),&ScriptEditorDebugger::_scene_tree_property_select_object);
+ ObjectTypeDB::bind_method(_MD("_scene_tree_property_value_edited"),&ScriptEditorDebugger::_scene_tree_property_value_edited);
ADD_SIGNAL(MethodInfo("goto_script_line"));
ADD_SIGNAL(MethodInfo("breaked",PropertyInfo(Variant::BOOL,"reallydid"),PropertyInfo(Variant::BOOL,"can_debug")));
@@ -1435,249 +1678,284 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
add_child(tabs);
- VBoxContainer *vbc = memnew( VBoxContainer );
- vbc->set_name(TTR("Debugger"));
- //tabs->add_child(vbc);
- Control *dbg=vbc;
+ { //debugger
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ vbc->set_name(TTR("Debugger"));
+ //tabs->add_child(vbc);
+ Control *dbg=vbc;
- HBoxContainer *hbc = memnew( HBoxContainer );
- vbc->add_child(hbc);
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ vbc->add_child(hbc);
- reason = memnew( LineEdit );
- reason->set_text("");
- reason->set_editable(false);
- hbc->add_child(reason);
- reason->add_color_override("font_color",Color(1,0.4,0.0,0.8));
- reason->set_h_size_flags(SIZE_EXPAND_FILL);
- //reason->set_clip_text(true);
+ reason = memnew( LineEdit );
+ reason->set_text("");
+ reason->set_editable(false);
+ hbc->add_child(reason);
+ reason->add_color_override("font_color",Color(1,0.4,0.0,0.8));
+ reason->set_h_size_flags(SIZE_EXPAND_FILL);
+ //reason->set_clip_text(true);
- hbc->add_child( memnew( VSeparator) );
+ hbc->add_child( memnew( VSeparator) );
- step = memnew( Button );
- hbc->add_child(step);
- step->set_tooltip(TTR("Step Into"));
- step->connect("pressed",this,"debug_step");
+ step = memnew( Button );
+ hbc->add_child(step);
+ step->set_tooltip(TTR("Step Into"));
+ step->connect("pressed",this,"debug_step");
- next = memnew( Button );
- hbc->add_child(next);
- next->set_tooltip(TTR("Step Over"));
- next->connect("pressed",this,"debug_next");
+ next = memnew( Button );
+ hbc->add_child(next);
+ next->set_tooltip(TTR("Step Over"));
+ next->connect("pressed",this,"debug_next");
- hbc->add_child( memnew( VSeparator) );
+ hbc->add_child( memnew( VSeparator) );
- dobreak = memnew( Button );
- hbc->add_child(dobreak);
- dobreak->set_tooltip(TTR("Break"));
- dobreak->connect("pressed",this,"debug_break");
+ dobreak = memnew( Button );
+ hbc->add_child(dobreak);
+ dobreak->set_tooltip(TTR("Break"));
+ dobreak->connect("pressed",this,"debug_break");
- docontinue = memnew( Button );
- hbc->add_child(docontinue);
- docontinue->set_tooltip(TTR("Continue"));
- docontinue->connect("pressed",this,"debug_continue");
+ docontinue = memnew( Button );
+ hbc->add_child(docontinue);
+ docontinue->set_tooltip(TTR("Continue"));
+ docontinue->connect("pressed",this,"debug_continue");
- hbc->add_child( memnew( VSeparator) );
+ hbc->add_child( memnew( VSeparator) );
- back = memnew( Button );
- hbc->add_child(back);
- back->set_tooltip(TTR("Inspect Previous Instance"));
+ back = memnew( Button );
+ hbc->add_child(back);
+ back->set_tooltip(TTR("Inspect Previous Instance"));
- forward = memnew( Button );
- hbc->add_child(forward);
- forward->set_tooltip(TTR("Inspect Next Instance"));
+ forward = memnew( Button );
+ hbc->add_child(forward);
+ forward->set_tooltip(TTR("Inspect Next Instance"));
- HSplitContainer *sc = memnew( HSplitContainer );
- vbc->add_child(sc);
- sc->set_v_size_flags(SIZE_EXPAND_FILL);
+ HSplitContainer *sc = memnew( HSplitContainer );
+ vbc->add_child(sc);
+ sc->set_v_size_flags(SIZE_EXPAND_FILL);
- stack_dump = memnew( Tree );
- stack_dump->set_columns(1);
- stack_dump->set_column_titles_visible(true);
- stack_dump->set_column_title(0,TTR("Stack Frames"));
- stack_dump->set_h_size_flags(SIZE_EXPAND_FILL);
- stack_dump->set_hide_root(true);
- stack_dump->connect("cell_selected",this,"_stack_dump_frame_selected");
- sc->add_child(stack_dump);
+ stack_dump = memnew( Tree );
+ stack_dump->set_columns(1);
+ stack_dump->set_column_titles_visible(true);
+ stack_dump->set_column_title(0,TTR("Stack Frames"));
+ stack_dump->set_h_size_flags(SIZE_EXPAND_FILL);
+ stack_dump->set_hide_root(true);
+ stack_dump->connect("cell_selected",this,"_stack_dump_frame_selected");
+ sc->add_child(stack_dump);
- inspector = memnew( PropertyEditor );
- inspector->set_h_size_flags(SIZE_EXPAND_FILL);
- inspector->hide_top_label();
- inspector->get_scene_tree()->set_column_title(0,TTR("Variable"));
- inspector->set_capitalize_paths(false);
- inspector->set_read_only(true);
- sc->add_child(inspector);
+ inspector = memnew( PropertyEditor );
+ inspector->set_h_size_flags(SIZE_EXPAND_FILL);
+ inspector->hide_top_label();
+ inspector->get_scene_tree()->set_column_title(0,TTR("Variable"));
+ inspector->set_capitalize_paths(false);
+ inspector->set_read_only(true);
+ sc->add_child(inspector);
- server = TCP_Server::create_ref();
+ server = TCP_Server::create_ref();
- pending_in_queue=0;
+ pending_in_queue=0;
- variables = memnew( ScriptEditorDebuggerVariables );
-
- breaked=false;
-
- tabs->add_child(dbg);
- //tabs->move_child(vbc,0);
-
- hbc = memnew( HBoxContainer );
- vbc->add_child(hbc);
-
-
- error_split = memnew( HSplitContainer );
- VBoxContainer *errvb = memnew( VBoxContainer );
- errvb->set_h_size_flags(SIZE_EXPAND_FILL);
- error_list = memnew( ItemList );
- errvb->add_margin_child(TTR("Errors:"),error_list,true);
- error_split->add_child(errvb);
-
- errvb = memnew( VBoxContainer );
- errvb->set_h_size_flags(SIZE_EXPAND_FILL);
- error_stack = memnew( ItemList );
- errvb->add_margin_child(TTR("Stack Trace (if applicable):"),error_stack,true);
- error_split->add_child(errvb);
-
- error_split->set_name(TTR("Errors"));
- tabs->add_child(error_split);
-
- profiler = memnew( EditorProfiler );
- profiler->set_name("Profiler");
- tabs->add_child(profiler);
- profiler->connect("enable_profiling",this,"_profiler_activate");
- profiler->connect("break_request",this,"_profiler_seeked");
-
-
- HSplitContainer *hsp = memnew( HSplitContainer );
-
- perf_monitors = memnew(Tree);
- perf_monitors->set_columns(2);
- perf_monitors->set_column_title(0,TTR("Monitor"));
- perf_monitors->set_column_title(1,TTR("Value"));
- perf_monitors->set_column_titles_visible(true);
- hsp->add_child(perf_monitors);
- perf_monitors->set_select_mode(Tree::SELECT_MULTI);
- perf_monitors->connect("multi_selected",this,"_performance_select");
- perf_draw = memnew( Control );
- perf_draw->connect("draw",this,"_performance_draw");
- hsp->add_child(perf_draw);
- hsp->set_name("Metrics");
- hsp->set_split_offset(300);
- tabs->add_child(hsp);
- perf_max.resize(Performance::MONITOR_MAX);
-
- Map<String,TreeItem*> bases;
- TreeItem *root=perf_monitors->create_item();
- perf_monitors->set_hide_root(true);
- for(int i=0;i<Performance::MONITOR_MAX;i++) {
+ variables = memnew( ScriptEditorDebuggerVariables );
- String n = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i));
- String base = n.get_slice("/",0);
- String name = n.get_slice("/",1);
- if (!bases.has(base)) {
- TreeItem *b = perf_monitors->create_item(root);
- b->set_text(0,base.capitalize());
- b->set_editable(0,false);
- b->set_selectable(0,false);
- bases[base]=b;
- }
+ breaked=false;
+
+ tabs->add_child(dbg);
+ //tabs->move_child(vbc,0);
+
+ hbc = memnew( HBoxContainer );
+ vbc->add_child(hbc);
+
+ }
+
+ { //errors
+
+
+ error_split = memnew( HSplitContainer );
+ VBoxContainer *errvb = memnew( VBoxContainer );
+ errvb->set_h_size_flags(SIZE_EXPAND_FILL);
+ error_list = memnew( ItemList );
+ errvb->add_margin_child(TTR("Errors:"),error_list,true);
+ error_split->add_child(errvb);
+
+ errvb = memnew( VBoxContainer );
+ errvb->set_h_size_flags(SIZE_EXPAND_FILL);
+ error_stack = memnew( ItemList );
+ errvb->add_margin_child(TTR("Stack Trace (if applicable):"),error_stack,true);
+ error_split->add_child(errvb);
+
+ error_split->set_name(TTR("Errors"));
+ tabs->add_child(error_split);
+ }
+
+
+ { // inquire
- TreeItem *it = perf_monitors->create_item(bases[base]);
- it->set_editable(0,false);
- it->set_selectable(0,true);
- it->set_text(0,name.capitalize());
- perf_items.push_back(it);
- perf_max[i]=0;
+ 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);
+
+ inspect_scene_tree = memnew( Tree );
+ info_left->add_margin_child("Live Scene Tree:",inspect_scene_tree,true);
+ 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("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");
}
- VBoxContainer *vmem_vb = memnew( VBoxContainer );
- HBoxContainer *vmem_hb = memnew( HBoxContainer );
- Label *vmlb = memnew(Label(TTR("List of Video Memory Usage by Resource:")+" ") );
- vmlb->set_h_size_flags(SIZE_EXPAND_FILL);
- vmem_hb->add_child( vmlb );
- vmem_hb->add_child( memnew(Label(TTR("Total:")+" ")) );
- vmem_total = memnew( LineEdit );
- vmem_total->set_editable(false);
- vmem_total->set_custom_minimum_size(Size2(100,1));
- vmem_hb->add_child(vmem_total);
- vmem_refresh = memnew( Button );
- vmem_hb->add_child(vmem_refresh);
- vmem_vb->add_child(vmem_hb);
- vmem_refresh->connect("pressed",this,"_video_mem_request");
-
- MarginContainer *vmmc = memnew( MarginContainer );
- vmem_tree = memnew( Tree );
- vmem_tree->set_v_size_flags(SIZE_EXPAND_FILL);
- vmem_tree->set_h_size_flags(SIZE_EXPAND_FILL);
- vmmc->add_child(vmem_tree);
- vmmc->set_v_size_flags(SIZE_EXPAND_FILL);
- vmem_vb->add_child(vmmc);
-
- vmem_vb->set_name(TTR("Video Mem"));
- vmem_tree->set_columns(4);
- vmem_tree->set_column_titles_visible(true);
- vmem_tree->set_column_title(0,TTR("Resource Path"));
- vmem_tree->set_column_expand(0,true);
- vmem_tree->set_column_expand(1,false);
- vmem_tree->set_column_title(1,TTR("Type"));
- vmem_tree->set_column_min_width(1,100);
- vmem_tree->set_column_expand(2,false);
- vmem_tree->set_column_title(2,TTR("Format"));
- vmem_tree->set_column_min_width(2,150);
- vmem_tree->set_column_expand(3,false);
- vmem_tree->set_column_title(3,TTR("Usage"));
- vmem_tree->set_column_min_width(3,80);
- vmem_tree->set_hide_root(true);
-
- tabs->add_child(vmem_vb);
-
- info = memnew( HSplitContainer );
- info->set_name(TTR("Info"));
- tabs->add_child(info);
-
- VBoxContainer *info_left = memnew( VBoxContainer );
- info_left->set_h_size_flags(SIZE_EXPAND_FILL);
- info->add_child(info_left);
- clicked_ctrl = memnew( LineEdit );
- info_left->add_margin_child(TTR("Clicked Control:"),clicked_ctrl);
- clicked_ctrl_type = memnew( LineEdit );
- info_left->add_margin_child(TTR("Clicked Control Type:"),clicked_ctrl_type);
-
- live_edit_root = memnew( LineEdit );
-
- {
- HBoxContainer *lehb = memnew( HBoxContainer );
- Label *l = memnew( Label(TTR("Live Edit Root:")) );
- lehb->add_child(l);
- l->set_h_size_flags(SIZE_EXPAND_FILL);
- le_set = memnew( Button(TTR("Set From Tree")) );
- lehb->add_child(le_set);
- le_clear = memnew( Button(TTR("Clear")) );
- lehb->add_child(le_clear);
- info_left->add_child(lehb);
- MarginContainer *mc = memnew( MarginContainer );
- mc->add_child(live_edit_root);
- info_left->add_child(mc);
- le_set->set_disabled(true);
- le_clear->set_disabled(true);
+ { //profiler
+ profiler = memnew( EditorProfiler );
+ profiler->set_name("Profiler");
+ tabs->add_child(profiler);
+ profiler->connect("enable_profiling",this,"_profiler_activate");
+ profiler->connect("break_request",this,"_profiler_seeked");
+ }
+
+
+ { //monitors
+
+ HSplitContainer *hsp = memnew( HSplitContainer );
+
+ perf_monitors = memnew(Tree);
+ perf_monitors->set_columns(2);
+ perf_monitors->set_column_title(0,TTR("Monitor"));
+ perf_monitors->set_column_title(1,TTR("Value"));
+ perf_monitors->set_column_titles_visible(true);
+ hsp->add_child(perf_monitors);
+ perf_monitors->set_select_mode(Tree::SELECT_MULTI);
+ perf_monitors->connect("multi_selected",this,"_performance_select");
+ perf_draw = memnew( Control );
+ perf_draw->connect("draw",this,"_performance_draw");
+ hsp->add_child(perf_draw);
+ hsp->set_name("Monitors");
+ hsp->set_split_offset(300);
+ tabs->add_child(hsp);
+ perf_max.resize(Performance::MONITOR_MAX);
+
+ Map<String,TreeItem*> bases;
+ TreeItem *root=perf_monitors->create_item();
+ perf_monitors->set_hide_root(true);
+ for(int i=0;i<Performance::MONITOR_MAX;i++) {
+
+ String n = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i));
+ String base = n.get_slice("/",0);
+ String name = n.get_slice("/",1);
+ if (!bases.has(base)) {
+ TreeItem *b = perf_monitors->create_item(root);
+ b->set_text(0,base.capitalize());
+ b->set_editable(0,false);
+ b->set_selectable(0,false);
+ bases[base]=b;
+ }
+
+ TreeItem *it = perf_monitors->create_item(bases[base]);
+ it->set_editable(0,false);
+ it->set_selectable(0,true);
+ it->set_text(0,name.capitalize());
+ perf_items.push_back(it);
+ perf_max[i]=0;
+
+ }
+ }
+
+ { //vmem inspect
+ VBoxContainer *vmem_vb = memnew( VBoxContainer );
+ HBoxContainer *vmem_hb = memnew( HBoxContainer );
+ Label *vmlb = memnew(Label(TTR("List of Video Memory Usage by Resource:")+" ") );
+ vmlb->set_h_size_flags(SIZE_EXPAND_FILL);
+ vmem_hb->add_child( vmlb );
+ vmem_hb->add_child( memnew(Label(TTR("Total:")+" ")) );
+ vmem_total = memnew( LineEdit );
+ vmem_total->set_editable(false);
+ vmem_total->set_custom_minimum_size(Size2(100,1));
+ vmem_hb->add_child(vmem_total);
+ vmem_refresh = memnew( Button );
+ vmem_hb->add_child(vmem_refresh);
+ vmem_vb->add_child(vmem_hb);
+ vmem_refresh->connect("pressed",this,"_video_mem_request");
+
+ MarginContainer *vmmc = memnew( MarginContainer );
+ vmem_tree = memnew( Tree );
+ vmem_tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ vmem_tree->set_h_size_flags(SIZE_EXPAND_FILL);
+ vmmc->add_child(vmem_tree);
+ vmmc->set_v_size_flags(SIZE_EXPAND_FILL);
+ vmem_vb->add_child(vmmc);
+
+ vmem_vb->set_name(TTR("Video Mem"));
+ vmem_tree->set_columns(4);
+ vmem_tree->set_column_titles_visible(true);
+ vmem_tree->set_column_title(0,TTR("Resource Path"));
+ vmem_tree->set_column_expand(0,true);
+ vmem_tree->set_column_expand(1,false);
+ vmem_tree->set_column_title(1,TTR("Type"));
+ vmem_tree->set_column_min_width(1,100);
+ vmem_tree->set_column_expand(2,false);
+ vmem_tree->set_column_title(2,TTR("Format"));
+ vmem_tree->set_column_min_width(2,150);
+ vmem_tree->set_column_expand(3,false);
+ vmem_tree->set_column_title(3,TTR("Usage"));
+ vmem_tree->set_column_min_width(3,80);
+ vmem_tree->set_hide_root(true);
+
+ tabs->add_child(vmem_vb);
+ }
+
+ { // misc
+ VBoxContainer *info_left = memnew( VBoxContainer );
+ info_left->set_h_size_flags(SIZE_EXPAND_FILL);
+ info_left->set_name("Misc");
+ tabs->add_child(info_left);
+ clicked_ctrl = memnew( LineEdit );
+ info_left->add_margin_child(TTR("Clicked Control:"),clicked_ctrl);
+ clicked_ctrl_type = memnew( LineEdit );
+ info_left->add_margin_child(TTR("Clicked Control Type:"),clicked_ctrl_type);
+
+ live_edit_root = memnew( LineEdit );
+
+ {
+ HBoxContainer *lehb = memnew( HBoxContainer );
+ Label *l = memnew( Label(TTR("Live Edit Root:")) );
+ lehb->add_child(l);
+ l->set_h_size_flags(SIZE_EXPAND_FILL);
+ le_set = memnew( Button(TTR("Set From Tree")) );
+ lehb->add_child(le_set);
+ le_clear = memnew( Button(TTR("Clear")) );
+ lehb->add_child(le_clear);
+ info_left->add_child(lehb);
+ MarginContainer *mc = memnew( MarginContainer );
+ mc->add_child(live_edit_root);
+ info_left->add_child(mc);
+ le_set->set_disabled(true);
+ le_clear->set_disabled(true);
+ }
+
}
- VBoxContainer *info_right = memnew(VBoxContainer);
- info_right->set_h_size_flags(SIZE_EXPAND_FILL);
- info->add_child(info_right);
- HBoxContainer *inforhb = memnew( HBoxContainer );
- info_right->add_child(inforhb);
- Label *l2 = memnew( Label(TTR("Scene Tree:") ) );
- l2->set_h_size_flags(SIZE_EXPAND_FILL);
- inforhb->add_child( l2 );
- Button *refresh = memnew( Button );
- inforhb->add_child(refresh);
- refresh->connect("pressed",this,"_scene_tree_request");
- scene_tree_refresh=refresh;
- MarginContainer *infomc = memnew( MarginContainer );
- info_right->add_child(infomc);
- infomc->set_v_size_flags(SIZE_EXPAND_FILL);
- scene_tree = memnew( Tree );
- infomc->add_child(scene_tree);
msgdialog = memnew( AcceptDialog );
@@ -1706,5 +1984,6 @@ ScriptEditorDebugger::~ScriptEditorDebugger() {
ppeer->set_stream_peer(Ref<StreamPeer>());
server->stop();
+ memdelete(inspected_object);
}
diff --git a/tools/editor/script_editor_debugger.h b/tools/editor/script_editor_debugger.h
index 1288349884..128ca16173 100644
--- a/tools/editor/script_editor_debugger.h
+++ b/tools/editor/script_editor_debugger.h
@@ -33,7 +33,7 @@
#include "scene/gui/button.h"
#include "core/io/tcp_server.h"
#include "core/io/packet_peer.h"
-
+#include "property_editor.h"
class Tree;
class PropertyEditor;
@@ -49,6 +49,10 @@ class HSplitContainer;
class ItemList;
class EditorProfiler;
+
+
+class ScriptEditorDebuggerInspectedObject;
+
class ScriptEditorDebugger : public Control {
OBJ_TYPE( ScriptEditorDebugger, Control );
@@ -61,12 +65,23 @@ class ScriptEditorDebugger : public Control {
LineEdit *clicked_ctrl;
LineEdit *clicked_ctrl_type;
LineEdit *live_edit_root;
- Tree *scene_tree;
- HSplitContainer *info;
- Button *scene_tree_refresh;
Button *le_set;
Button *le_clear;
+
+
+ Tree *inspect_scene_tree;
+ HSplitContainer *inspect_info;
+ PropertyEditor *inspect_properties;
+ float inspect_scene_tree_timeout;
+ float inspect_edited_object_timeout;
+ ObjectID inspected_object_id;
+ ScriptEditorDebuggerInspectedObject *inspected_object;
+ bool updating_scene_tree;
+ Set<ObjectID> unfold_cache;
+
+
+
HSplitContainer *error_split;
ItemList *error_list;
ItemList *error_stack;
@@ -132,8 +147,13 @@ class ScriptEditorDebugger : public Control {
void _stack_dump_frame_selected();
void _output_clear();
+
+ void _scene_tree_folded(Object* obj);
+ void _scene_tree_selected();
void _scene_tree_request();
void _parse_message(const String& p_msg,const Array& p_data);
+ void _scene_tree_property_select_object(ObjectID p_object);
+ void _scene_tree_property_value_edited(const String& p_prop,const Variant& p_value);
void _video_mem_request();