| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  script_debugger_remote.cpp                                           */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                    http://www.godotengine.org                         */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-01-01 22:01:57 +01:00
										 |  |  | /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							| 
									
										
										
										
											2017-04-08 00:45:00 +02:00
										 |  |  | /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* 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 "script_debugger_remote.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | #include "core/io/marshalls.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "globals.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | #include "io/ip.h"
 | 
					
						
							| 
									
										
										
										
											2016-01-02 12:58:59 -03:00
										 |  |  | #include "os/input.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | #include "os/os.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-21 09:50:44 -03:00
										 |  |  | void ScriptDebuggerRemote::_send_video_memory() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	List<ResourceUsage> usage; | 
					
						
							|  |  |  | 	if (resource_usage_func) | 
					
						
							|  |  |  | 		resource_usage_func(&usage); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	usage.sort(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packet_peer_stream->put_var("message:video_mem"); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	packet_peer_stream->put_var(usage.size() * 4); | 
					
						
							| 
									
										
										
										
											2015-10-21 09:50:44 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	for (List<ResourceUsage>::Element *E = usage.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2015-10-21 09:50:44 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(E->get().path); | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(E->get().type); | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(E->get().format); | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(E->get().vram); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | Error ScriptDebuggerRemote::connect_to_host(const String &p_host, uint16_t p_port) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	IP_Address ip; | 
					
						
							|  |  |  | 	if (p_host.is_valid_ip_address()) | 
					
						
							|  |  |  | 		ip = p_host; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		ip = IP::get_singleton()->resolve_hostname(p_host); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	int port = p_port; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	int tries = 3; | 
					
						
							|  |  |  | 	tcp_client->connect(ip, port); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	while (tries--) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			OS::get_singleton()->delay_usec(1000000); | 
					
						
							|  |  |  | 			print_line("Remote Debugger: Connection failed with status: " + String::num(tcp_client->get_status()) + "'', retrying in 1 sec."); | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		print_line("Remote Debugger: Unable to connect"); | 
					
						
							|  |  |  | 		return FAILED; | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	//    print_line("Remote Debugger: Connection OK!");
 | 
					
						
							|  |  |  | 	packet_peer_stream->set_stream_peer(tcp_client); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	return OK; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | static int _ScriptDebuggerRemote_found_id = 0; | 
					
						
							|  |  |  | static Object *_ScriptDebuggerRemote_find = NULL; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | static void _ScriptDebuggerRemote_debug_func(Object *p_obj) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (_ScriptDebuggerRemote_find == p_obj) { | 
					
						
							|  |  |  | 		_ScriptDebuggerRemote_found_id = p_obj->get_instance_ID(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | static ObjectID safe_get_instance_id(const Variant &p_v) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Object *o = p_v; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (o == NULL) | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		REF r = p_v; | 
					
						
							|  |  |  | 		if (r.is_valid()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return r->get_instance_ID(); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			_ScriptDebuggerRemote_found_id = 0; | 
					
						
							|  |  |  | 			_ScriptDebuggerRemote_find = NULL; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			ObjectDB::debug_objects(_ScriptDebuggerRemote_debug_func); | 
					
						
							|  |  |  | 			return _ScriptDebuggerRemote_found_id; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	//this function is called when there is a debugger break (bug on script)
 | 
					
						
							|  |  |  | 	//or when execution is paused from editor
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (!tcp_client->is_connected()) { | 
					
						
							|  |  |  | 		ERR_EXPLAIN("Script Debugger failed to connect, but being used anyway."); | 
					
						
							|  |  |  | 		ERR_FAIL(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-14 04:02:18 +02:00
										 |  |  | 	OS::get_singleton()->enable_for_stealing_focus(Globals::get_singleton()->get("editor_pid")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	packet_peer_stream->put_var("debug_enter"); | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(2); | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(p_can_continue); | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(p_script->debug_get_error()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	skip_profile_frame = true; // to avoid super long frame time for the frame
 | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode(); | 
					
						
							|  |  |  | 	if (mouse_mode != Input::MOUSE_MODE_VISIBLE) | 
					
						
							| 
									
										
										
										
											2016-01-02 12:58:59 -03:00
										 |  |  | 		Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	while (true) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		_get_output(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		if (packet_peer_stream->get_available_packet_count() > 0) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			Variant var; | 
					
						
							|  |  |  | 			Error err = packet_peer_stream->get_var(var); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			ERR_CONTINUE(err != OK); | 
					
						
							|  |  |  | 			ERR_CONTINUE(var.get_type() != Variant::ARRAY); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			Array cmd = var; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			ERR_CONTINUE(cmd.size() == 0); | 
					
						
							|  |  |  | 			ERR_CONTINUE(cmd[0].get_type() != Variant::STRING); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			String command = cmd[0]; | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			if (command == "get_stack_dump") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				packet_peer_stream->put_var("stack_dump"); | 
					
						
							|  |  |  | 				int slc = p_script->debug_get_stack_level_count(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				packet_peer_stream->put_var(slc); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				for (int i = 0; i < slc; i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					Dictionary d; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					d["file"] = p_script->debug_get_stack_level_source(i); | 
					
						
							|  |  |  | 					d["line"] = p_script->debug_get_stack_level_line(i); | 
					
						
							|  |  |  | 					d["function"] = p_script->debug_get_stack_level_function(i); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					//d["id"]=p_script->debug_get_stack_level_
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					d["id"] = 0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					packet_peer_stream->put_var(d); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "get_stack_frame_vars") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 				cmd.remove(0); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				ERR_CONTINUE(cmd.size() != 1); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				int lv = cmd[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 				ScriptInstance *self_instance = p_script->debug_get_stack_level_instance(lv); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				List<String> members; | 
					
						
							|  |  |  | 				List<Variant> member_vals; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				p_script->debug_get_stack_level_members(lv, &members, &member_vals); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				ERR_CONTINUE(members.size() != member_vals.size()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				List<String> locals; | 
					
						
							|  |  |  | 				List<Variant> local_vals; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				p_script->debug_get_stack_level_locals(lv, &locals, &local_vals); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				ERR_CONTINUE(locals.size() != local_vals.size()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 				List<String> globals; | 
					
						
							|  |  |  | 				List<Variant> global_vals; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				p_script->debug_get_globals(&globals, &global_vals); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				ERR_CONTINUE(globals.size() != global_vals.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				packet_peer_stream->put_var("stack_frame_vars"); | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 				packet_peer_stream->put_var(locals.size() + members.size() + globals.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				{ //locals
 | 
					
						
							|  |  |  | 					List<String>::Element *E = locals.front(); | 
					
						
							|  |  |  | 					List<Variant>::Element *F = local_vals.front(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					while (E) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						PropertyInfo pi(var.get_type(), String("locals/") + E->get()); | 
					
						
							|  |  |  | 						packet_peer_stream->put_var(_serialize(F->get(), pi)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						E = E->next(); | 
					
						
							|  |  |  | 						F = F->next(); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				{ //members
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					if (self_instance) { // self
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						members.push_front("self"); | 
					
						
							|  |  |  | 						member_vals.push_front(self_instance->get_owner()); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					List<String>::Element *E = members.front(); | 
					
						
							|  |  |  | 					List<Variant>::Element *F = member_vals.front(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					while (E) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 						PropertyInfo pi(var.get_type(), String("members/") + E->get()); | 
					
						
							|  |  |  | 						packet_peer_stream->put_var(_serialize(F->get(), pi)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 						E = E->next(); | 
					
						
							|  |  |  | 						F = F->next(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 				if (self_instance) { // constants
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 					Ref<Script> script = self_instance->get_script(); | 
					
						
							|  |  |  | 					if (!script.is_null()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 						const Map<StringName, Variant> &constants = script->get_constants(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 						for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							PropertyInfo pi(var.get_type(), String("constants/") + E->key()); | 
					
						
							|  |  |  | 							packet_peer_stream->put_var(_serialize(E->value(), pi)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				{ //globals
 | 
					
						
							|  |  |  | 					List<String>::Element *E = globals.front(); | 
					
						
							|  |  |  | 					List<Variant>::Element *F = global_vals.front(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					while (E) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						PropertyInfo pi(var.get_type(), String("globals/") + E->get()); | 
					
						
							|  |  |  | 						packet_peer_stream->put_var(_serialize(F->get(), pi)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 						E = E->next(); | 
					
						
							|  |  |  | 						F = F->next(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "step") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				set_depth(-1); | 
					
						
							|  |  |  | 				set_lines_left(1); | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "next") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				set_depth(0); | 
					
						
							|  |  |  | 				set_lines_left(1); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "continue") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				set_depth(-1); | 
					
						
							|  |  |  | 				set_lines_left(-1); | 
					
						
							| 
									
										
										
										
											2016-09-14 04:02:18 +02:00
										 |  |  | 				OS::get_singleton()->move_window_to_foreground(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "break") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				ERR_PRINT("Got break when already broke!"); | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "request_scene_tree") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if (request_scene_tree) | 
					
						
							|  |  |  | 					request_scene_tree(request_scene_tree_ud); | 
					
						
							| 
									
										
										
										
											2015-08-04 20:17:13 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "request_video_mem") { | 
					
						
							| 
									
										
										
										
											2015-10-21 09:50:44 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				_send_video_memory(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "inspect_object") { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				ObjectID id = cmd[1]; | 
					
						
							|  |  |  | 				_send_object_id(id); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "set_object_property") { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				_set_object_property(cmd[1], cmd[2], cmd[3]); | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			} else if (command == "reload_scripts") { | 
					
						
							|  |  |  | 				reload_all_scripts = true; | 
					
						
							|  |  |  | 			} else if (command == "breakpoint") { | 
					
						
							| 
									
										
										
										
											2015-08-04 20:17:13 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				bool set = cmd[3]; | 
					
						
							|  |  |  | 				if (set) | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					insert_breakpoint(cmd[2], cmd[1]); | 
					
						
							| 
									
										
										
										
											2015-08-04 20:17:13 -03:00
										 |  |  | 				else | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 					remove_breakpoint(cmd[2], cmd[1]); | 
					
						
							| 
									
										
										
										
											2015-08-04 20:17:13 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				_parse_live_edit(cmd); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			OS::get_singleton()->delay_usec(10000); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packet_peer_stream->put_var("debug_exit"); | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (mouse_mode != Input::MOUSE_MODE_VISIBLE) | 
					
						
							| 
									
										
										
										
											2016-01-02 12:58:59 -03:00
										 |  |  | 		Input::get_singleton()->set_mouse_mode(mouse_mode); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebuggerRemote::_get_output() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex->lock(); | 
					
						
							|  |  |  | 	if (output_strings.size()) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		locking = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		packet_peer_stream->put_var("output"); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		packet_peer_stream->put_var(output_strings.size()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		while (output_strings.size()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			packet_peer_stream->put_var(output_strings.front()->get()); | 
					
						
							|  |  |  | 			output_strings.pop_front(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		locking = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (messages.size()) { | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		locking = true; | 
					
						
							|  |  |  | 		packet_peer_stream->put_var("message:" + messages.front()->get().message); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		packet_peer_stream->put_var(messages.front()->get().data.size()); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		for (int i = 0; i < messages.front()->get().data.size(); i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			packet_peer_stream->put_var(messages.front()->get().data[i]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		messages.pop_front(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		locking = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while (errors.size()) { | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		locking = true; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 		packet_peer_stream->put_var("error"); | 
					
						
							|  |  |  | 		OutputError oe = errors.front()->get(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		packet_peer_stream->put_var(oe.callstack.size() + 2); | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Array error_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		error_data.push_back(oe.hr); | 
					
						
							|  |  |  | 		error_data.push_back(oe.min); | 
					
						
							|  |  |  | 		error_data.push_back(oe.sec); | 
					
						
							|  |  |  | 		error_data.push_back(oe.msec); | 
					
						
							|  |  |  | 		error_data.push_back(oe.source_func); | 
					
						
							|  |  |  | 		error_data.push_back(oe.source_file); | 
					
						
							|  |  |  | 		error_data.push_back(oe.source_line); | 
					
						
							|  |  |  | 		error_data.push_back(oe.error); | 
					
						
							|  |  |  | 		error_data.push_back(oe.error_descr); | 
					
						
							|  |  |  | 		error_data.push_back(oe.warning); | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(error_data); | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(oe.callstack.size()); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		for (int i = 0; i < oe.callstack.size(); i++) { | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 			packet_peer_stream->put_var(oe.callstack[i]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		errors.pop_front(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		locking = false; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	mutex->unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebuggerRemote::line_poll() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//the purpose of this is just processing events every now and then when the script might get too busy
 | 
					
						
							|  |  |  | 	//otherwise bugs like infinite loops cant be catched
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (poll_every % 2048 == 0) | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		_poll_events(); | 
					
						
							|  |  |  | 	poll_every++; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | void ScriptDebuggerRemote::_err_handler(void *ud, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (p_type == ERR_HANDLER_SCRIPT) | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 		return; //ignore script errors, those go through debugger
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)ud; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	OutputError oe; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	oe.error = p_err; | 
					
						
							|  |  |  | 	oe.error_descr = p_descr; | 
					
						
							|  |  |  | 	oe.source_file = p_file; | 
					
						
							|  |  |  | 	oe.source_line = p_line; | 
					
						
							|  |  |  | 	oe.source_func = p_func; | 
					
						
							|  |  |  | 	oe.warning = p_type == ERR_HANDLER_WARNING; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 	uint64_t time = OS::get_singleton()->get_ticks_msec(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	oe.hr = time / 3600000; | 
					
						
							|  |  |  | 	oe.min = (time / 60000) % 60; | 
					
						
							|  |  |  | 	oe.sec = (time / 1000) % 60; | 
					
						
							|  |  |  | 	oe.msec = time % 1000; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 	Array cstack; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector<ScriptLanguage::StackInfo> si; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	for (int i = 0; i < ScriptServer::get_language_count(); i++) { | 
					
						
							|  |  |  | 		si = ScriptServer::get_language(i)->debug_get_current_stack_info(); | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 		if (si.size()) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	cstack.resize(si.size() * 2); | 
					
						
							|  |  |  | 	for (int i = 0; i < si.size(); i++) { | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 		String path; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		int line = 0; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 		if (si[i].script.is_valid()) { | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			path = si[i].script->get_path(); | 
					
						
							|  |  |  | 			line = si[i].line; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		cstack[i * 2 + 0] = path; | 
					
						
							|  |  |  | 		cstack[i * 2 + 1] = line; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	oe.callstack = cstack; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sdr->mutex->lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!sdr->locking && sdr->tcp_client->is_connected()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sdr->errors.push_back(oe); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sdr->mutex->unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | bool ScriptDebuggerRemote::_parse_live_edit(const Array &cmd) { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	String cmdstr = cmd[0]; | 
					
						
							|  |  |  | 	if (!live_edit_funcs || !cmdstr.begins_with("live_")) | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-02 20:28:10 -03:00
										 |  |  | 	//print_line(Variant(cmd).get_construct_string());
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (cmdstr == "live_set_root") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!live_edit_funcs->root_func) | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2015-08-02 20:28:10 -03:00
										 |  |  | 		//print_line("root: "+Variant(cmd).get_construct_string());
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->root_func(live_edit_funcs->udata, cmd[1], cmd[2]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_node_path") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!live_edit_funcs->node_path_func) | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2015-08-02 20:28:10 -03:00
										 |  |  | 		//print_line("path: "+Variant(cmd).get_construct_string());
 | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->node_path_func(live_edit_funcs->udata, cmd[1], cmd[2]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_res_path") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!live_edit_funcs->res_path_func) | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->res_path_func(live_edit_funcs->udata, cmd[1], cmd[2]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_node_prop_res") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 		if (!live_edit_funcs->node_set_res_func) | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->node_set_res_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_node_prop") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!live_edit_funcs->node_set_func) | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->node_set_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_res_prop_res") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!live_edit_funcs->res_set_res_func) | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->res_set_res_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_res_prop") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!live_edit_funcs->res_set_func) | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->res_set_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_node_call") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!live_edit_funcs->node_call_func) | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->node_call_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_res_call") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!live_edit_funcs->res_call_func) | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->res_call_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_create_node") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->tree_create_node_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_instance_node") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->tree_instance_node_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_remove_node") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->tree_remove_node_func(live_edit_funcs->udata, cmd[1]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_remove_and_keep_node") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->tree_remove_and_keep_node_func(live_edit_funcs->udata, cmd[1], cmd[2]); | 
					
						
							|  |  |  | 	} else if (cmdstr == "live_restore_node") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->tree_restore_node_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} else if (cmdstr == "live_duplicate_node") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->tree_duplicate_node_func(live_edit_funcs->udata, cmd[1], cmd[2]); | 
					
						
							|  |  |  | 	} else if (cmdstr == "live_reparent_node") { | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		live_edit_funcs->tree_reparent_node_func(live_edit_funcs->udata, cmd[1], cmd[2], cmd[3], cmd[4]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	Object *obj = ObjectDB::get_instance(p_id); | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 	if (!obj) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 	Array props; | 
					
						
							|  |  |  | 	const uint32_t SEND_PROPERTIES = 0xFFFFFFFF; // All kind of properties are allowed
 | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 	List<PropertyInfo> pinfo; | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 	Set<StringName> ignored_properties; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	obj->get_property_list(&pinfo, true); | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 	bool query_props = true; | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 	if (ScriptInstance *si = obj->get_script_instance()) { | 
					
						
							|  |  |  | 		if (!si->get_script().is_null()) { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 			const Map<StringName, Variant> &constants = si->get_script()->get_constants(); | 
					
						
							|  |  |  | 			for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 				PropertyInfo pi(E->value().get_type(), String("constants/") + E->key()); | 
					
						
							|  |  |  | 				props.push_back(_serialize(E->value(), pi)); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 			const Set<StringName> &members = si->get_script()->get_members(); | 
					
						
							|  |  |  | 			for (Set<StringName>::Element *E = members.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 				Variant m; | 
					
						
							|  |  |  | 				if (si->get(E->get(), m)) { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 					PropertyInfo pi(m.get_type(), String("members/") + E->get()); | 
					
						
							|  |  |  | 					props.push_back(_serialize(m, pi)); | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 					ignored_properties.insert(E->get()); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 			PropertyInfo pi(Variant::OBJECT, String("Resource/script")); | 
					
						
							|  |  |  | 			props.push_back(_serialize(si->get_script(), pi)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if (Resource *res = obj->cast_to<Resource>()) { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 		if (res->cast_to<Script>()) { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 			const Map<StringName, Variant> &constants = res->cast_to<Script>()->get_constants(); | 
					
						
							|  |  |  | 			for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 				PropertyInfo pi(E->value().get_type(), String("constants/") + E->key()); | 
					
						
							|  |  |  | 				props.push_back(_serialize(E->value(), pi)); | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		PropertyInfo pi(Variant::OBJECT, res->get_type_name(), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY); | 
					
						
							|  |  |  | 		props.push_front(_serialize(res, pi)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PropertyInfo pathpi(Variant::STRING, "Resource/Resource"); | 
					
						
							|  |  |  | 		pathpi.hint_string = "REMOTE:RES"; | 
					
						
							|  |  |  | 		props.push_back(_serialize(res->get_path(), pathpi)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		query_props = false; | 
					
						
							|  |  |  | 	} else if (obj->is_type("Node")) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		String path = obj->call("get_path"); | 
					
						
							|  |  |  | 		PropertyInfo pi(Variant::OBJECT, String("Node/path")); | 
					
						
							|  |  |  | 		props.push_back(_serialize(path, pi)); | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (query_props) { | 
					
						
							|  |  |  | 		for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (E->get().usage & SEND_PROPERTIES && !ignored_properties.has(E->get().name)) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				Variant var = obj->get(E->get().name); | 
					
						
							|  |  |  | 				props.push_back(_serialize(var, E->get())); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packet_peer_stream->put_var("message:inspect_object"); | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(2); | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(p_id); | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(props); | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value) { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	Object *obj = ObjectDB::get_instance(p_id); | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 	if (!obj) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 	String name = p_property; | 
					
						
							|  |  |  | 	const String member_prefix = String("members/"); | 
					
						
							|  |  |  | 	if (name.begins_with(member_prefix) && p_property.length() > member_prefix.length()) { | 
					
						
							|  |  |  | 		name = p_property.substr(member_prefix.length(), p_property.length()); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj->set(name, p_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int __put_value_to_buff_at_pos(const Variant &value, DVector<uint8_t> &buff, int pos) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int size_required = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DVector<uint8_t> valuebuf; | 
					
						
							|  |  |  | 	if (value.get_type() == Variant::RAW_ARRAY) | 
					
						
							|  |  |  | 		valuebuf = value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String sub_contetn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (value.get_type()) { | 
					
						
							|  |  |  | 		case Variant::NIL: | 
					
						
							|  |  |  | 		case Variant::INT: | 
					
						
							|  |  |  | 		case Variant::BOOL: | 
					
						
							|  |  |  | 			size_required = sizeof(uint32_t); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case Variant::REAL: | 
					
						
							|  |  |  | 			size_required = sizeof(uint32_t); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case Variant::STRING: { | 
					
						
							|  |  |  | 			sub_contetn = value; | 
					
						
							|  |  |  | 			const int MAX_STR_LEN = 80; // More than 80 will not be send to the debugger
 | 
					
						
							|  |  |  | 			if (sub_contetn.length() > MAX_STR_LEN) | 
					
						
							|  |  |  | 				sub_contetn = sub_contetn.substr(0, MAX_STR_LEN) + "..."; | 
					
						
							|  |  |  | 			encode_variant(sub_contetn, NULL, size_required); | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			encode_variant(value, NULL, size_required); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (buff.size() < pos + size_required) | 
					
						
							|  |  |  | 		buff.resize((pos + size_required) * 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (value.get_type()) { | 
					
						
							|  |  |  | 		case Variant::INT: | 
					
						
							|  |  |  | 		case Variant::BOOL: | 
					
						
							|  |  |  | 			encode_uint32(value, &buff.write()[pos]); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case Variant::REAL: | 
					
						
							|  |  |  | 			encode_float(value, &buff.write()[pos]); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case Variant::STRING: | 
					
						
							|  |  |  | 			encode_variant(sub_contetn, &buff.write()[pos], size_required); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			encode_variant(value, &buff.write()[pos], size_required); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return size_required; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ScriptDebuggerRemote::_serialize_variant(const Variant &var, const PropertyInfo &p_info, DVector<uint8_t> &buff) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int used_size = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	used_size += __put_value_to_buff_at_pos(p_info.name, buff, used_size); | 
					
						
							|  |  |  | 	const int type_index = used_size; | 
					
						
							|  |  |  | 	used_size += __put_value_to_buff_at_pos(var.get_type(), buff, type_index); | 
					
						
							|  |  |  | 	const int hint_index = used_size; | 
					
						
							|  |  |  | 	used_size += __put_value_to_buff_at_pos(p_info.hint, buff, hint_index); | 
					
						
							|  |  |  | 	used_size += __put_value_to_buff_at_pos(p_info.usage, buff, used_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	StringName hint_string = p_info.hint_string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int value_len = 0; | 
					
						
							|  |  |  | 	switch (var.get_type()) { | 
					
						
							|  |  |  | 		case Variant::OBJECT: { | 
					
						
							|  |  |  | 			__put_value_to_buff_at_pos(Variant::INT, buff, type_index); | 
					
						
							|  |  |  | 			__put_value_to_buff_at_pos(PROPERTY_HINT_OBJECT_ID, buff, hint_index); | 
					
						
							|  |  |  | 			Object *obj = var; | 
					
						
							|  |  |  | 			uint32_t id = obj ? obj->get_instance_ID() : 0; | 
					
						
							|  |  |  | 			hint_string = obj ? obj->get_type_name() : hint_string; | 
					
						
							|  |  |  | 			value_len += __put_value_to_buff_at_pos(id, buff, used_size + value_len); | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		case Variant::IMAGE: | 
					
						
							|  |  |  | 			value_len += __put_value_to_buff_at_pos(Image(), buff, used_size + value_len); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case Variant::ARRAY: { | 
					
						
							|  |  |  | 			Array arr = var; | 
					
						
							|  |  |  | 			value_len += __put_value_to_buff_at_pos(arr.size(), buff, used_size + value_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (int i = 0; i < arr.size(); i++) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				const Variant &e = arr[i]; | 
					
						
							|  |  |  | 				PropertyInfo pi(e.get_type(), ""); | 
					
						
							|  |  |  | 				DVector<uint8_t> ebuff; | 
					
						
							|  |  |  | 				ebuff.resize(256); | 
					
						
							|  |  |  | 				ebuff.resize(_serialize_variant(e, pi, ebuff)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				value_len += __put_value_to_buff_at_pos(ebuff, buff, used_size + value_len); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		case Variant::STRING_ARRAY: { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			DVector<String> strarr = var; | 
					
						
							|  |  |  | 			Array arr; | 
					
						
							|  |  |  | 			arr.resize(strarr.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (int i = 0; i < strarr.size(); i++) | 
					
						
							|  |  |  | 				arr[i] = strarr[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			PropertyInfo pi(Variant::ARRAY, ""); | 
					
						
							|  |  |  | 			DVector<uint8_t> ebuff; | 
					
						
							|  |  |  | 			ebuff.resize(256); | 
					
						
							|  |  |  | 			ebuff.resize(_serialize_variant(arr, pi, ebuff)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			value_len += __put_value_to_buff_at_pos(ebuff, buff, used_size + value_len); | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		case Variant::DICTIONARY: { | 
					
						
							|  |  |  | 			Dictionary dict = var; | 
					
						
							|  |  |  | 			value_len += __put_value_to_buff_at_pos(dict.size(), buff, used_size + value_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			const Array &keys = dict.keys(); | 
					
						
							|  |  |  | 			for (int i = 0; i < keys.size(); i++) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				PropertyInfo pi; | 
					
						
							|  |  |  | 				const Variant &key = keys[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				DVector<uint8_t> tmpbuff; | 
					
						
							|  |  |  | 				tmpbuff.resize(256); | 
					
						
							|  |  |  | 				pi.type = key.get_type(); | 
					
						
							|  |  |  | 				tmpbuff.resize(_serialize_variant(key, pi, tmpbuff)); | 
					
						
							|  |  |  | 				value_len += __put_value_to_buff_at_pos(tmpbuff, buff, used_size + value_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				const Variant &value = dict[key]; | 
					
						
							|  |  |  | 				pi.type = value.get_type(); | 
					
						
							|  |  |  | 				tmpbuff.resize(_serialize_variant(value, pi, tmpbuff)); | 
					
						
							|  |  |  | 				value_len += __put_value_to_buff_at_pos(tmpbuff, buff, used_size + value_len); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			value_len += __put_value_to_buff_at_pos(var, buff, used_size + value_len); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	used_size += value_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	used_size += __put_value_to_buff_at_pos(hint_string, buff, used_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return used_size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DVector<uint8_t> ScriptDebuggerRemote::_serialize(const Variant &var, const PropertyInfo &p_info) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DVector<uint8_t> buff; | 
					
						
							|  |  |  | 	buff.resize(256); | 
					
						
							|  |  |  | 	buff.resize(_serialize_variant(var, p_info, buff)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return buff; | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void ScriptDebuggerRemote::_poll_events() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	//this si called from ::idle_poll, happens only when running the game,
 | 
					
						
							|  |  |  | 	//does not get called while on debug break
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	while (packet_peer_stream->get_available_packet_count() > 0) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		_get_output(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//send over output_strings
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Variant var; | 
					
						
							|  |  |  | 		Error err = packet_peer_stream->get_var(var); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		ERR_CONTINUE(err != OK); | 
					
						
							|  |  |  | 		ERR_CONTINUE(var.get_type() != Variant::ARRAY); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Array cmd = var; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		ERR_CONTINUE(cmd.size() == 0); | 
					
						
							|  |  |  | 		ERR_CONTINUE(cmd[0].get_type() != Variant::STRING); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		String command = cmd[0]; | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 		//cmd.remove(0);
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		if (command == "break") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (get_break_language()) | 
					
						
							|  |  |  | 				debug(get_break_language()); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		} else if (command == "request_scene_tree") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (request_scene_tree) | 
					
						
							|  |  |  | 				request_scene_tree(request_scene_tree_ud); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		} else if (command == "request_video_mem") { | 
					
						
							| 
									
										
										
										
											2015-10-21 09:50:44 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			_send_video_memory(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		} else if (command == "inspect_object") { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			ObjectID id = cmd[1]; | 
					
						
							|  |  |  | 			_send_object_id(id); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		} else if (command == "set_object_property") { | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			_set_object_property(cmd[1], cmd[2], cmd[3]); | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 		} else if (command == "set_variable_value") { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// TODO: Implement set the value stack variale
 | 
					
						
							| 
									
										
										
										
											2016-05-22 19:28:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		} else if (command == "start_profiling") { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			for (int i = 0; i < ScriptServer::get_language_count(); i++) { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 				ScriptServer::get_language(i)->profiling_start(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			max_frame_functions = cmd[1]; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 			profiler_function_signature_map.clear(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			profiling = true; | 
					
						
							|  |  |  | 			frame_time = 0; | 
					
						
							|  |  |  | 			idle_time = 0; | 
					
						
							|  |  |  | 			fixed_time = 0; | 
					
						
							|  |  |  | 			fixed_frame_time = 0; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			print_line("PROFILING ALRIGHT!"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		} else if (command == "stop_profiling") { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			for (int i = 0; i < ScriptServer::get_language_count(); i++) { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 				ScriptServer::get_language(i)->profiling_stop(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			profiling = false; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 			_send_profiling_data(false); | 
					
						
							|  |  |  | 			print_line("PROFILING END!"); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		} else if (command == "reload_scripts") { | 
					
						
							|  |  |  | 			reload_all_scripts = true; | 
					
						
							|  |  |  | 		} else if (command == "breakpoint") { | 
					
						
							| 
									
										
										
										
											2015-08-04 20:17:13 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			bool set = cmd[3]; | 
					
						
							|  |  |  | 			if (set) | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				insert_breakpoint(cmd[2], cmd[1]); | 
					
						
							| 
									
										
										
										
											2015-08-04 20:17:13 -03:00
										 |  |  | 			else | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 				remove_breakpoint(cmd[2], cmd[1]); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			_parse_live_edit(cmd); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | void ScriptDebuggerRemote::_send_profiling_data(bool p_for_frame) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	int ofs = 0; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	for (int i = 0; i < ScriptServer::get_language_count(); i++) { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 		if (p_for_frame) | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&profile_info[ofs], profile_info.size() - ofs); | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&profile_info[ofs], profile_info.size() - ofs); | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	for (int i = 0; i < ofs; i++) { | 
					
						
							|  |  |  | 		profile_info_ptrs[i] = &profile_info[i]; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	SortArray<ScriptLanguage::ProfilingInfo *, ProfileInfoSort> sa; | 
					
						
							|  |  |  | 	sa.sort(profile_info_ptrs.ptr(), ofs); | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	int to_send = MIN(ofs, max_frame_functions); | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	//check signatures first
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	uint64_t total_script_time = 0; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	for (int i = 0; i < to_send; i++) { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			int idx = profiler_function_signature_map.size(); | 
					
						
							|  |  |  | 			packet_peer_stream->put_var("profile_sig"); | 
					
						
							|  |  |  | 			packet_peer_stream->put_var(2); | 
					
						
							|  |  |  | 			packet_peer_stream->put_var(profile_info_ptrs[i]->signature); | 
					
						
							|  |  |  | 			packet_peer_stream->put_var(idx); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			profiler_function_signature_map[profile_info_ptrs[i]->signature] = idx; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		total_script_time += profile_info_ptrs[i]->self_time; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//send frames then
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p_for_frame) { | 
					
						
							|  |  |  | 		packet_peer_stream->put_var("profile_frame"); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		packet_peer_stream->put_var(8 + profile_frame_data.size() * 2 + to_send * 4); | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		packet_peer_stream->put_var("profile_total"); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		packet_peer_stream->put_var(8 + to_send * 4); | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(OS::get_singleton()->get_frames_drawn()); //total frame time
 | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(frame_time); //total frame time
 | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(idle_time); //idle frame time
 | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(fixed_time); //fixed frame time
 | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(fixed_frame_time); //fixed frame time
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packet_peer_stream->put_var(USEC_TO_SEC(total_script_time)); //total script execution time
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p_for_frame) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		packet_peer_stream->put_var(profile_frame_data.size()); //how many profile framedatas to send
 | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 		packet_peer_stream->put_var(to_send); //how many script functions to send
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		for (int i = 0; i < profile_frame_data.size(); i++) { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			packet_peer_stream->put_var(profile_frame_data[i].name); | 
					
						
							|  |  |  | 			packet_peer_stream->put_var(profile_frame_data[i].data); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(0); //how many script functions to send
 | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(to_send); //how many script functions to send
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	for (int i = 0; i < to_send; i++) { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		int sig_id = -1; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) { | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			sig_id = profiler_function_signature_map[profile_info_ptrs[i]->signature]; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(sig_id); | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(profile_info_ptrs[i]->call_count); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		packet_peer_stream->put_var(profile_info_ptrs[i]->total_time / 1000000.0); | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(profile_info_ptrs[i]->self_time / 1000000.0); | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p_for_frame) { | 
					
						
							|  |  |  | 		profile_frame_data.clear(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void ScriptDebuggerRemote::idle_poll() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	// this function is called every frame, except when there is a debugger break (::debug() in this class)
 | 
					
						
							|  |  |  | 	// execution stops and remains in the ::debug function
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	_get_output(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (requested_quit) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		packet_peer_stream->put_var("kill_me"); | 
					
						
							|  |  |  | 		packet_peer_stream->put_var(0); | 
					
						
							|  |  |  | 		requested_quit = false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (performance) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		uint64_t pt = OS::get_singleton()->get_ticks_msec(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		if (pt - last_perf_time > 1000) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			last_perf_time = pt; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			int max = performance->get("MONITOR_MAX"); | 
					
						
							|  |  |  | 			Array arr; | 
					
						
							|  |  |  | 			arr.resize(max); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 			for (int i = 0; i < max; i++) { | 
					
						
							|  |  |  | 				arr[i] = performance->call("get_monitor", i); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			packet_peer_stream->put_var("performance"); | 
					
						
							|  |  |  | 			packet_peer_stream->put_var(1); | 
					
						
							|  |  |  | 			packet_peer_stream->put_var(arr); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (profiling) { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		if (skip_profile_frame) { | 
					
						
							|  |  |  | 			skip_profile_frame = false; | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 			//send profiling info normally
 | 
					
						
							|  |  |  | 			_send_profiling_data(true); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-01 20:22:02 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (reload_all_scripts) { | 
					
						
							| 
									
										
										
										
											2016-06-01 20:22:02 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		for (int i = 0; i < ScriptServer::get_language_count(); i++) { | 
					
						
							|  |  |  | 			ScriptServer::get_language(i)->reload_all_scripts(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		reload_all_scripts = false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	_poll_events(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | void ScriptDebuggerRemote::send_message(const String &p_message, const Array &p_args) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mutex->lock(); | 
					
						
							|  |  |  | 	if (!locking && tcp_client->is_connected()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Message msg; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		msg.message = p_message; | 
					
						
							|  |  |  | 		msg.data = p_args; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		messages.push_back(msg); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mutex->unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)p_this; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	uint64_t ticks = OS::get_singleton()->get_ticks_usec() / 1000; | 
					
						
							|  |  |  | 	sdr->msec_count += ticks - sdr->last_msec; | 
					
						
							|  |  |  | 	sdr->last_msec = ticks; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (sdr->msec_count > 1000) { | 
					
						
							|  |  |  | 		sdr->char_count = 0; | 
					
						
							|  |  |  | 		sdr->msec_count = 0; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String s = p_string; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	int allowed_chars = MIN(MAX(sdr->max_cps - sdr->char_count, 0), s.length()); | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (allowed_chars == 0) | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (allowed_chars < s.length()) { | 
					
						
							|  |  |  | 		s = s.substr(0, allowed_chars); | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	sdr->char_count += allowed_chars; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (sdr->char_count >= sdr->max_cps) { | 
					
						
							|  |  |  | 		s += "\n[output overflow, print less text!]\n"; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	sdr->mutex->lock(); | 
					
						
							|  |  |  | 	if (!sdr->locking && sdr->tcp_client->is_connected()) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 		sdr->output_strings.push_back(s); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	sdr->mutex->unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebuggerRemote::request_quit() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	requested_quit = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebuggerRemote::set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	request_scene_tree = p_func; | 
					
						
							|  |  |  | 	request_scene_tree_ud = p_udata; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | void ScriptDebuggerRemote::set_live_edit_funcs(LiveEditFuncs *p_funcs) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	live_edit_funcs = p_funcs; | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | bool ScriptDebuggerRemote::is_profiling() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return profiling; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | void ScriptDebuggerRemote::add_profiling_frame_data(const StringName &p_name, const Array &p_data) { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	int idx = -1; | 
					
						
							|  |  |  | 	for (int i = 0; i < profile_frame_data.size(); i++) { | 
					
						
							|  |  |  | 		if (profile_frame_data[i].name == p_name) { | 
					
						
							|  |  |  | 			idx = i; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	FrameData fd; | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	fd.name = p_name; | 
					
						
							|  |  |  | 	fd.data = p_data; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	if (idx == -1) { | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 		profile_frame_data.push_back(fd); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 		profile_frame_data[idx] = fd; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebuggerRemote::profiling_start() { | 
					
						
							|  |  |  | 	//ignores this, uses it via connnection
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebuggerRemote::profiling_end() { | 
					
						
							|  |  |  | 	//ignores this, uses it via connnection
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	frame_time = p_frame_time; | 
					
						
							|  |  |  | 	idle_time = p_idle_time; | 
					
						
							|  |  |  | 	fixed_time = p_fixed_time; | 
					
						
							|  |  |  | 	fixed_frame_time = p_fixed_frame_time; | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | ScriptDebuggerRemote::ResourceUsageFunc ScriptDebuggerRemote::resource_usage_func = NULL; | 
					
						
							| 
									
										
										
										
											2015-10-21 09:50:44 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | ScriptDebuggerRemote::ScriptDebuggerRemote() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	tcp_client = StreamPeerTCP::create_ref(); | 
					
						
							|  |  |  | 	packet_peer_stream = Ref<PacketPeerStream>(memnew(PacketPeerStream)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	packet_peer_stream->set_stream_peer(tcp_client); | 
					
						
							| 
									
										
										
										
											2017-05-29 14:09:16 +08:00
										 |  |  | 	packet_peer_stream->set_input_buffer_max_size(pow(2, 20)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	mutex = Mutex::create(); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	locking = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	phl.printfunc = _print_handler; | 
					
						
							|  |  |  | 	phl.userdata = this; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	add_print_handler(&phl); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	requested_quit = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	performance = Globals::get_singleton()->get_singleton_object("Performance"); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	last_perf_time = 0; | 
					
						
							|  |  |  | 	poll_every = 0; | 
					
						
							|  |  |  | 	request_scene_tree = NULL; | 
					
						
							|  |  |  | 	live_edit_funcs = NULL; | 
					
						
							|  |  |  | 	max_cps = GLOBAL_DEF("debug/max_remote_stdout_chars_per_second", 2048); | 
					
						
							|  |  |  | 	char_count = 0; | 
					
						
							|  |  |  | 	msec_count = 0; | 
					
						
							|  |  |  | 	last_msec = 0; | 
					
						
							|  |  |  | 	skip_profile_frame = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	eh.errfunc = _err_handler; | 
					
						
							|  |  |  | 	eh.userdata = this; | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 	add_error_handler(&eh); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	profile_info.resize(CLAMP(int(Globals::get_singleton()->get("debug/profiler_max_functions")), 128, 65535)); | 
					
						
							| 
									
										
										
										
											2016-05-21 21:18:16 -03:00
										 |  |  | 	profile_info_ptrs.resize(profile_info.size()); | 
					
						
							| 
									
										
										
										
											2017-03-19 00:36:26 +01:00
										 |  |  | 	profiling = false; | 
					
						
							|  |  |  | 	max_frame_functions = 16; | 
					
						
							|  |  |  | 	reload_all_scripts = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ScriptDebuggerRemote::~ScriptDebuggerRemote() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	remove_print_handler(&phl); | 
					
						
							| 
									
										
										
										
											2015-08-04 09:47:32 -03:00
										 |  |  | 	remove_error_handler(&eh); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	memdelete(mutex); | 
					
						
							|  |  |  | } |