mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-03 23:21:15 +00:00 
			
		
		
		
	Send script members, contants and globals to debugger
Remove remote inspector panel
This commit is contained in:
		
							parent
							
								
									475cee9c0f
								
							
						
					
					
						commit
						ccf76798d5
					
				
					 3 changed files with 218 additions and 121 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
	typedef Pair<PropertyInfo, Variant> PropertyDesc;
 | 
			
		||||
	List<PropertyDesc> properties;
 | 
			
		||||
 | 
			
		||||
	if (ScriptInstance *si = obj->get_script_instance()) {
 | 
			
		||||
		if (!si->get_script().is_null()) {
 | 
			
		||||
 | 
			
		||||
			Set<StringName> members;
 | 
			
		||||
			si->get_script()->get_members(&members);
 | 
			
		||||
			for (Set<StringName>::Element *E = members.front(); E; E = E->next()) {
 | 
			
		||||
 | 
			
		||||
				Variant m;
 | 
			
		||||
				if (si->get(E->get(), m)) {
 | 
			
		||||
					PropertyInfo pi(m.get_type(), String("Members/") + E->get());
 | 
			
		||||
					properties.push_back(PropertyDesc(pi, m));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			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);
 | 
			
		||||
 | 
			
		||||
	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++;
 | 
			
		||||
			properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name)));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
		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(props_to_send * 5 + 4);
 | 
			
		||||
	packet_peer_stream->put_var(3);
 | 
			
		||||
	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("");
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
			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);
 | 
			
		||||
 | 
			
		||||
			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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	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() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,11 @@ 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;
 | 
			
		||||
 | 
			
		||||
		mcount = p_data[ofs];
 | 
			
		||||
 | 
			
		||||
		ofs++;
 | 
			
		||||
		for (int i = 0; i < mcount; i++) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -545,7 +571,30 @@ 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("Members/" + n, v, h, hs);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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("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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue