|
@@ -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();
|
|
|
}
|