1 /*************************************************************************/
2 /* script_debugger_remote.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30
31 #include "script_debugger_remote.h"
32
33 #include "core/engine.h"
34 #include "core/io/ip.h"
35 #include "core/io/marshalls.h"
36 #include "core/os/input.h"
37 #include "core/os/os.h"
38 #include "core/project_settings.h"
39 #include "scene/main/node.h"
40 #include "scene/main/scene_tree.h"
41 #include "scene/main/viewport.h"
42 #include "scene/resources/packed_scene.h"
43 #include "servers/visual_server.h"
44
_send_video_memory()45 void ScriptDebuggerRemote::_send_video_memory() {
46
47 List<ResourceUsage> usage;
48 if (resource_usage_func)
49 resource_usage_func(&usage);
50
51 usage.sort();
52
53 packet_peer_stream->put_var("message:video_mem");
54 packet_peer_stream->put_var(usage.size() * 4);
55
56 for (List<ResourceUsage>::Element *E = usage.front(); E; E = E->next()) {
57
58 packet_peer_stream->put_var(E->get().path);
59 packet_peer_stream->put_var(E->get().type);
60 packet_peer_stream->put_var(E->get().format);
61 packet_peer_stream->put_var(E->get().vram);
62 }
63 }
64
connect_to_host(const String & p_host,uint16_t p_port)65 Error ScriptDebuggerRemote::connect_to_host(const String &p_host, uint16_t p_port) {
66
67 IP_Address ip;
68 if (p_host.is_valid_ip_address())
69 ip = p_host;
70 else
71 ip = IP::get_singleton()->resolve_hostname(p_host);
72
73 int port = p_port;
74
75 const int tries = 6;
76 int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
77
78 tcp_client->connect_to_host(ip, port);
79
80 for (int i = 0; i < tries; i++) {
81
82 if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
83 print_verbose("Remote Debugger: Connected!");
84 break;
85 } else {
86
87 const int ms = waits[i];
88 OS::get_singleton()->delay_usec(ms * 1000);
89 print_verbose("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in " + String::num(ms) + " msec.");
90 };
91 };
92
93 if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
94
95 ERR_PRINTS("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + ".");
96 return FAILED;
97 };
98
99 packet_peer_stream->set_stream_peer(tcp_client);
100
101 return OK;
102 }
103
_put_variable(const String & p_name,const Variant & p_variable)104 void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_variable) {
105
106 packet_peer_stream->put_var(p_name);
107
108 Variant var = p_variable;
109 if (p_variable.get_type() == Variant::OBJECT && !ObjectDB::instance_validate(p_variable)) {
110 var = Variant();
111 }
112
113 int len = 0;
114 Error err = encode_variant(var, NULL, len, true);
115 if (err != OK)
116 ERR_PRINT("Failed to encode variant.");
117
118 if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
119 packet_peer_stream->put_var(Variant());
120 } else {
121 packet_peer_stream->put_var(var);
122 }
123 }
124
_save_node(ObjectID id,const String & p_path)125 void ScriptDebuggerRemote::_save_node(ObjectID id, const String &p_path) {
126
127 Node *node = Object::cast_to<Node>(ObjectDB::get_instance(id));
128 ERR_FAIL_COND(!node);
129
130 Ref<PackedScene> ps = memnew(PackedScene);
131 ps->pack(node);
132 ResourceSaver::save(p_path, ps);
133 }
134
debug(ScriptLanguage * p_script,bool p_can_continue,bool p_is_error_breakpoint)135 void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue, bool p_is_error_breakpoint) {
136
137 //this function is called when there is a debugger break (bug on script)
138 //or when execution is paused from editor
139
140 if (skip_breakpoints && !p_is_error_breakpoint)
141 return;
142
143 ERR_FAIL_COND_MSG(!tcp_client->is_connected_to_host(), "Script Debugger failed to connect, but being used anyway.");
144
145 packet_peer_stream->put_var("debug_enter");
146 packet_peer_stream->put_var(2);
147 packet_peer_stream->put_var(p_can_continue);
148 packet_peer_stream->put_var(p_script->debug_get_error());
149
150 skip_profile_frame = true; // to avoid super long frame time for the frame
151
152 Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode();
153 if (mouse_mode != Input::MOUSE_MODE_VISIBLE)
154 Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
155
156 uint64_t loop_begin_usec = 0;
157 uint64_t loop_time_sec = 0;
158 while (true) {
159 loop_begin_usec = OS::get_singleton()->get_ticks_usec();
160
161 _get_output();
162
163 if (packet_peer_stream->get_available_packet_count() > 0) {
164
165 Variant var;
166 Error err = packet_peer_stream->get_var(var);
167
168 ERR_CONTINUE(err != OK);
169 ERR_CONTINUE(var.get_type() != Variant::ARRAY);
170
171 Array cmd = var;
172
173 ERR_CONTINUE(cmd.size() == 0);
174 ERR_CONTINUE(cmd[0].get_type() != Variant::STRING);
175
176 String command = cmd[0];
177
178 if (command == "get_stack_dump") {
179
180 packet_peer_stream->put_var("stack_dump");
181 int slc = p_script->debug_get_stack_level_count();
182 packet_peer_stream->put_var(slc);
183
184 for (int i = 0; i < slc; i++) {
185
186 Dictionary d;
187 d["file"] = p_script->debug_get_stack_level_source(i);
188 d["line"] = p_script->debug_get_stack_level_line(i);
189 d["function"] = p_script->debug_get_stack_level_function(i);
190 //d["id"]=p_script->debug_get_stack_level_
191 d["id"] = 0;
192
193 packet_peer_stream->put_var(d);
194 }
195
196 } else if (command == "get_stack_frame_vars") {
197
198 cmd.remove(0);
199 ERR_CONTINUE(cmd.size() != 1);
200 int lv = cmd[0];
201
202 List<String> members;
203 List<Variant> member_vals;
204 if (ScriptInstance *inst = p_script->debug_get_stack_level_instance(lv)) {
205 members.push_back("self");
206 member_vals.push_back(inst->get_owner());
207 }
208 p_script->debug_get_stack_level_members(lv, &members, &member_vals);
209 ERR_CONTINUE(members.size() != member_vals.size());
210
211 List<String> locals;
212 List<Variant> local_vals;
213 p_script->debug_get_stack_level_locals(lv, &locals, &local_vals);
214 ERR_CONTINUE(locals.size() != local_vals.size());
215
216 List<String> globals;
217 List<Variant> globals_vals;
218 p_script->debug_get_globals(&globals, &globals_vals);
219 ERR_CONTINUE(globals.size() != globals_vals.size());
220
221 packet_peer_stream->put_var("stack_frame_vars");
222 packet_peer_stream->put_var(3 + (locals.size() + members.size() + globals.size()) * 2);
223
224 { //locals
225 packet_peer_stream->put_var(locals.size());
226
227 List<String>::Element *E = locals.front();
228 List<Variant>::Element *F = local_vals.front();
229
230 while (E) {
231 _put_variable(E->get(), F->get());
232
233 E = E->next();
234 F = F->next();
235 }
236 }
237
238 { //members
239 packet_peer_stream->put_var(members.size());
240
241 List<String>::Element *E = members.front();
242 List<Variant>::Element *F = member_vals.front();
243
244 while (E) {
245
246 _put_variable(E->get(), F->get());
247
248 E = E->next();
249 F = F->next();
250 }
251 }
252
253 { //globals
254 packet_peer_stream->put_var(globals.size());
255
256 List<String>::Element *E = globals.front();
257 List<Variant>::Element *F = globals_vals.front();
258
259 while (E) {
260 _put_variable(E->get(), F->get());
261
262 E = E->next();
263 F = F->next();
264 }
265 }
266
267 } else if (command == "step") {
268
269 set_depth(-1);
270 set_lines_left(1);
271 break;
272 } else if (command == "next") {
273
274 set_depth(0);
275 set_lines_left(1);
276 break;
277
278 } else if (command == "continue") {
279 set_depth(-1);
280 set_lines_left(-1);
281 OS::get_singleton()->move_window_to_foreground();
282 break;
283 } else if (command == "break") {
284 ERR_PRINT("Got break when already broke!");
285 break;
286 } else if (command == "request_scene_tree") {
287
288 #ifdef DEBUG_ENABLED
289 if (scene_tree)
290 scene_tree->_debugger_request_tree();
291 #endif
292 } else if (command == "request_video_mem") {
293
294 _send_video_memory();
295 } else if (command == "inspect_object") {
296
297 ObjectID id = cmd[1];
298 _send_object_id(id);
299 } else if (command == "set_object_property") {
300
301 _set_object_property(cmd[1], cmd[2], cmd[3]);
302
303 } else if (command == "override_camera_2D:set") {
304 bool enforce = cmd[1];
305
306 if (scene_tree) {
307 scene_tree->get_root()->enable_canvas_transform_override(enforce);
308 }
309 } else if (command == "override_camera_2D:transform") {
310 Transform2D transform = cmd[1];
311
312 if (scene_tree) {
313 scene_tree->get_root()->set_canvas_transform_override(transform);
314 }
315 } else if (command == "override_camera_3D:set") {
316 bool enable = cmd[1];
317
318 if (scene_tree) {
319 scene_tree->get_root()->enable_camera_override(enable);
320 }
321 } else if (command == "override_camera_3D:transform") {
322 Transform transform = cmd[1];
323 bool is_perspective = cmd[2];
324 float size_or_fov = cmd[3];
325 float near = cmd[4];
326 float far = cmd[5];
327
328 if (scene_tree) {
329 if (is_perspective) {
330 scene_tree->get_root()->set_camera_override_perspective(size_or_fov, near, far);
331 } else {
332 scene_tree->get_root()->set_camera_override_orthogonal(size_or_fov, near, far);
333 }
334 scene_tree->get_root()->set_camera_override_transform(transform);
335 }
336
337 } else if (command == "reload_scripts") {
338 reload_all_scripts = true;
339 } else if (command == "breakpoint") {
340
341 bool set = cmd[3];
342 if (set)
343 insert_breakpoint(cmd[2], cmd[1]);
344 else
345 remove_breakpoint(cmd[2], cmd[1]);
346
347 } else if (command == "save_node") {
348 _save_node(cmd[1], cmd[2]);
349 } else if (command == "set_skip_breakpoints") {
350 skip_breakpoints = cmd[1];
351 } else {
352 _parse_live_edit(cmd);
353 }
354
355 } else {
356 OS::get_singleton()->delay_usec(10000);
357 OS::get_singleton()->process_and_drop_events();
358 }
359
360 // This is for the camera override to stay live even when the game is paused from the editor
361 loop_time_sec = (OS::get_singleton()->get_ticks_usec() - loop_begin_usec) / 1000000.0f;
362 VisualServer::get_singleton()->sync();
363 if (VisualServer::get_singleton()->has_changed()) {
364 VisualServer::get_singleton()->draw(true, loop_time_sec * Engine::get_singleton()->get_time_scale());
365 }
366 }
367
368 packet_peer_stream->put_var("debug_exit");
369 packet_peer_stream->put_var(0);
370
371 if (mouse_mode != Input::MOUSE_MODE_VISIBLE)
372 Input::get_singleton()->set_mouse_mode(mouse_mode);
373 }
374
_get_output()375 void ScriptDebuggerRemote::_get_output() {
376
377 mutex->lock();
378 if (output_strings.size()) {
379
380 locking = true;
381 packet_peer_stream->put_var("output");
382 packet_peer_stream->put_var(output_strings.size());
383
384 while (output_strings.size()) {
385 const OutputString &output_string = output_strings.front()->get();
386
387 Array msg_data;
388 msg_data.push_back(output_string.message);
389 msg_data.push_back(output_string.type);
390
391 packet_peer_stream->put_var(msg_data);
392
393 output_strings.pop_front();
394 }
395 locking = false;
396 }
397
398 if (n_messages_dropped > 0) {
399 Message msg;
400 msg.message = "Too many messages! " + String::num_int64(n_messages_dropped) + " messages were dropped.";
401 messages.push_back(msg);
402 n_messages_dropped = 0;
403 }
404
405 while (messages.size()) {
406 locking = true;
407 packet_peer_stream->put_var("message:" + messages.front()->get().message);
408 packet_peer_stream->put_var(messages.front()->get().data.size());
409 for (int i = 0; i < messages.front()->get().data.size(); i++) {
410 packet_peer_stream->put_var(messages.front()->get().data[i]);
411 }
412 messages.pop_front();
413 locking = false;
414 }
415
416 if (n_errors_dropped == 1) {
417 // Only print one message about dropping per second
418 OutputError oe;
419 oe.error = "TOO_MANY_ERRORS";
420 oe.error_descr = "Too many errors! Ignoring errors for up to 1 second.";
421 oe.warning = false;
422 uint64_t time = OS::get_singleton()->get_ticks_msec();
423 oe.hr = time / 3600000;
424 oe.min = (time / 60000) % 60;
425 oe.sec = (time / 1000) % 60;
426 oe.msec = time % 1000;
427 errors.push_back(oe);
428 }
429
430 if (n_warnings_dropped == 1) {
431 // Only print one message about dropping per second
432 OutputError oe;
433 oe.error = "TOO_MANY_WARNINGS";
434 oe.error_descr = "Too many warnings! Ignoring warnings for up to 1 second.";
435 oe.warning = true;
436 uint64_t time = OS::get_singleton()->get_ticks_msec();
437 oe.hr = time / 3600000;
438 oe.min = (time / 60000) % 60;
439 oe.sec = (time / 1000) % 60;
440 oe.msec = time % 1000;
441 errors.push_back(oe);
442 }
443
444 while (errors.size()) {
445 locking = true;
446 packet_peer_stream->put_var("error");
447 OutputError oe = errors.front()->get();
448
449 packet_peer_stream->put_var(oe.callstack.size() + 2);
450
451 Array error_data;
452
453 error_data.push_back(oe.hr);
454 error_data.push_back(oe.min);
455 error_data.push_back(oe.sec);
456 error_data.push_back(oe.msec);
457 error_data.push_back(oe.source_func);
458 error_data.push_back(oe.source_file);
459 error_data.push_back(oe.source_line);
460 error_data.push_back(oe.error);
461 error_data.push_back(oe.error_descr);
462 error_data.push_back(oe.warning);
463 packet_peer_stream->put_var(error_data);
464 packet_peer_stream->put_var(oe.callstack.size());
465 for (int i = 0; i < oe.callstack.size(); i++) {
466 packet_peer_stream->put_var(oe.callstack[i]);
467 }
468
469 errors.pop_front();
470 locking = false;
471 }
472 mutex->unlock();
473 }
474
line_poll()475 void ScriptDebuggerRemote::line_poll() {
476
477 //the purpose of this is just processing events every now and then when the script might get too busy
478 //otherwise bugs like infinite loops can't be caught
479 if (poll_every % 2048 == 0)
480 _poll_events();
481 poll_every++;
482 }
483
_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)484 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) {
485
486 if (p_type == ERR_HANDLER_SCRIPT)
487 return; //ignore script errors, those go through debugger
488
489 Vector<ScriptLanguage::StackInfo> si;
490
491 for (int i = 0; i < ScriptServer::get_language_count(); i++) {
492 si = ScriptServer::get_language(i)->debug_get_current_stack_info();
493 if (si.size())
494 break;
495 }
496
497 ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)ud;
498 sdr->send_error(p_func, p_file, p_line, p_err, p_descr, p_type, si);
499 }
500
_parse_live_edit(const Array & p_command)501 bool ScriptDebuggerRemote::_parse_live_edit(const Array &p_command) {
502
503 #ifdef DEBUG_ENABLED
504
505 String cmdstr = p_command[0];
506 if (!scene_tree || !cmdstr.begins_with("live_"))
507 return false;
508
509 if (cmdstr == "live_set_root") {
510
511 scene_tree->_live_edit_root_func(p_command[1], p_command[2]);
512
513 } else if (cmdstr == "live_node_path") {
514
515 scene_tree->_live_edit_node_path_func(p_command[1], p_command[2]);
516
517 } else if (cmdstr == "live_res_path") {
518
519 scene_tree->_live_edit_res_path_func(p_command[1], p_command[2]);
520
521 } else if (cmdstr == "live_node_prop_res") {
522
523 scene_tree->_live_edit_node_set_res_func(p_command[1], p_command[2], p_command[3]);
524
525 } else if (cmdstr == "live_node_prop") {
526
527 scene_tree->_live_edit_node_set_func(p_command[1], p_command[2], p_command[3]);
528
529 } else if (cmdstr == "live_res_prop_res") {
530
531 scene_tree->_live_edit_res_set_res_func(p_command[1], p_command[2], p_command[3]);
532
533 } else if (cmdstr == "live_res_prop") {
534
535 scene_tree->_live_edit_res_set_func(p_command[1], p_command[2], p_command[3]);
536
537 } else if (cmdstr == "live_node_call") {
538
539 scene_tree->_live_edit_node_call_func(p_command[1], p_command[2], p_command[3], p_command[4], p_command[5], p_command[6], p_command[7]);
540
541 } else if (cmdstr == "live_res_call") {
542
543 scene_tree->_live_edit_res_call_func(p_command[1], p_command[2], p_command[3], p_command[4], p_command[5], p_command[6], p_command[7]);
544
545 } else if (cmdstr == "live_create_node") {
546
547 scene_tree->_live_edit_create_node_func(p_command[1], p_command[2], p_command[3]);
548
549 } else if (cmdstr == "live_instance_node") {
550
551 scene_tree->_live_edit_instance_node_func(p_command[1], p_command[2], p_command[3]);
552
553 } else if (cmdstr == "live_remove_node") {
554
555 scene_tree->_live_edit_remove_node_func(p_command[1]);
556
557 } else if (cmdstr == "live_remove_and_keep_node") {
558
559 scene_tree->_live_edit_remove_and_keep_node_func(p_command[1], p_command[2]);
560
561 } else if (cmdstr == "live_restore_node") {
562
563 scene_tree->_live_edit_restore_node_func(p_command[1], p_command[2], p_command[3]);
564
565 } else if (cmdstr == "live_duplicate_node") {
566
567 scene_tree->_live_edit_duplicate_node_func(p_command[1], p_command[2]);
568
569 } else if (cmdstr == "live_reparent_node") {
570
571 scene_tree->_live_edit_reparent_node_func(p_command[1], p_command[2], p_command[3], p_command[4]);
572
573 } else {
574
575 return false;
576 }
577
578 return true;
579 #else
580
581 return false;
582 #endif
583 }
584
_send_object_id(ObjectID p_id)585 void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
586
587 Object *obj = ObjectDB::get_instance(p_id);
588 if (!obj)
589 return;
590
591 typedef Pair<PropertyInfo, Variant> PropertyDesc;
592 List<PropertyDesc> properties;
593
594 if (ScriptInstance *si = obj->get_script_instance()) {
595 if (!si->get_script().is_null()) {
596
597 typedef Map<const Script *, Set<StringName> > ScriptMemberMap;
598 typedef Map<const Script *, Map<StringName, Variant> > ScriptConstantsMap;
599
600 ScriptMemberMap members;
601 members[si->get_script().ptr()] = Set<StringName>();
602 si->get_script()->get_members(&(members[si->get_script().ptr()]));
603
604 ScriptConstantsMap constants;
605 constants[si->get_script().ptr()] = Map<StringName, Variant>();
606 si->get_script()->get_constants(&(constants[si->get_script().ptr()]));
607
608 Ref<Script> base = si->get_script()->get_base_script();
609 while (base.is_valid()) {
610
611 members[base.ptr()] = Set<StringName>();
612 base->get_members(&(members[base.ptr()]));
613
614 constants[base.ptr()] = Map<StringName, Variant>();
615 base->get_constants(&(constants[base.ptr()]));
616
617 base = base->get_base_script();
618 }
619
620 for (ScriptMemberMap::Element *sm = members.front(); sm; sm = sm->next()) {
621 for (Set<StringName>::Element *E = sm->get().front(); E; E = E->next()) {
622 Variant m;
623 if (si->get(E->get(), m)) {
624 String script_path = sm->key() == si->get_script().ptr() ? "" : sm->key()->get_path().get_file() + "/";
625 PropertyInfo pi(m.get_type(), "Members/" + script_path + E->get());
626 properties.push_back(PropertyDesc(pi, m));
627 }
628 }
629 }
630
631 for (ScriptConstantsMap::Element *sc = constants.front(); sc; sc = sc->next()) {
632 for (Map<StringName, Variant>::Element *E = sc->get().front(); E; E = E->next()) {
633 String script_path = sc->key() == si->get_script().ptr() ? "" : sc->key()->get_path().get_file() + "/";
634 if (E->value().get_type() == Variant::OBJECT) {
635 Variant id = ((Object *)E->value())->get_instance_id();
636 PropertyInfo pi(id.get_type(), "Constants/" + E->key(), PROPERTY_HINT_OBJECT_ID, "Object");
637 properties.push_back(PropertyDesc(pi, id));
638 } else {
639 PropertyInfo pi(E->value().get_type(), "Constants/" + script_path + E->key());
640 properties.push_back(PropertyDesc(pi, E->value()));
641 }
642 }
643 }
644 }
645 }
646
647 if (Node *node = Object::cast_to<Node>(obj)) {
648 // in some cases node will not be in tree here
649 // for instance where it created as variable and not yet added to tree
650 // in such cases we can't ask for it's path
651 if (node->is_inside_tree()) {
652 PropertyInfo pi(Variant::NODE_PATH, String("Node/path"));
653 properties.push_front(PropertyDesc(pi, node->get_path()));
654 } else {
655 PropertyInfo pi(Variant::STRING, String("Node/path"));
656 properties.push_front(PropertyDesc(pi, "[Orphan]"));
657 }
658
659 } else if (Resource *res = Object::cast_to<Resource>(obj)) {
660 if (Script *s = Object::cast_to<Script>(res)) {
661 Map<StringName, Variant> constants;
662 s->get_constants(&constants);
663 for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
664 if (E->value().get_type() == Variant::OBJECT) {
665 Variant id = ((Object *)E->value())->get_instance_id();
666 PropertyInfo pi(id.get_type(), "Constants/" + E->key(), PROPERTY_HINT_OBJECT_ID, "Object");
667 properties.push_front(PropertyDesc(pi, E->value()));
668 } else {
669 PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key());
670 properties.push_front(PropertyDesc(pi, E->value()));
671 }
672 }
673 }
674 }
675
676 List<PropertyInfo> pinfo;
677 obj->get_property_list(&pinfo, true);
678 for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
679 if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
680 properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name)));
681 }
682 }
683
684 Array send_props;
685 for (int i = 0; i < properties.size(); i++) {
686 const PropertyInfo &pi = properties[i].first;
687 Variant &var = properties[i].second;
688
689 RES res = var;
690
691 Array prop;
692 prop.push_back(pi.name);
693 prop.push_back(pi.type);
694
695 //only send information that can be sent..
696 int len = 0; //test how big is this to encode
697 encode_variant(var, NULL, len);
698 if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
699 prop.push_back(PROPERTY_HINT_OBJECT_TOO_BIG);
700 prop.push_back("");
701 prop.push_back(pi.usage);
702 prop.push_back(Variant());
703 } else {
704 prop.push_back(pi.hint);
705 prop.push_back(pi.hint_string);
706 prop.push_back(pi.usage);
707
708 if (!res.is_null()) {
709 var = res->get_path();
710 }
711
712 prop.push_back(var);
713 }
714 send_props.push_back(prop);
715 }
716
717 packet_peer_stream->put_var("message:inspect_object");
718 packet_peer_stream->put_var(3);
719 packet_peer_stream->put_var(p_id);
720 packet_peer_stream->put_var(obj->get_class());
721 packet_peer_stream->put_var(send_props);
722 }
723
_set_object_property(ObjectID p_id,const String & p_property,const Variant & p_value)724 void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value) {
725
726 Object *obj = ObjectDB::get_instance(p_id);
727 if (!obj)
728 return;
729
730 String prop_name = p_property;
731 if (p_property.begins_with("Members/")) {
732 Vector<String> ss = p_property.split("/");
733 prop_name = ss[ss.size() - 1];
734 }
735
736 obj->set(prop_name, p_value);
737 }
738
_poll_events()739 void ScriptDebuggerRemote::_poll_events() {
740
741 //this si called from ::idle_poll, happens only when running the game,
742 //does not get called while on debug break
743
744 while (packet_peer_stream->get_available_packet_count() > 0) {
745
746 _get_output();
747
748 //send over output_strings
749
750 Variant var;
751 Error err = packet_peer_stream->get_var(var);
752
753 ERR_CONTINUE(err != OK);
754 ERR_CONTINUE(var.get_type() != Variant::ARRAY);
755
756 Array cmd = var;
757
758 ERR_CONTINUE(cmd.size() == 0);
759 ERR_CONTINUE(cmd[0].get_type() != Variant::STRING);
760
761 String command = cmd[0];
762 //cmd.remove(0);
763
764 if (command == "break") {
765
766 if (get_break_language())
767 debug(get_break_language());
768 } else if (command == "request_scene_tree") {
769
770 #ifdef DEBUG_ENABLED
771 if (scene_tree)
772 scene_tree->_debugger_request_tree();
773 #endif
774 } else if (command == "request_video_mem") {
775
776 _send_video_memory();
777 } else if (command == "inspect_object") {
778
779 ObjectID id = cmd[1];
780 _send_object_id(id);
781 } else if (command == "set_object_property") {
782
783 _set_object_property(cmd[1], cmd[2], cmd[3]);
784
785 } else if (command == "start_profiling") {
786
787 for (int i = 0; i < ScriptServer::get_language_count(); i++) {
788 ScriptServer::get_language(i)->profiling_start();
789 }
790
791 max_frame_functions = cmd[1];
792 profiler_function_signature_map.clear();
793 profiling = true;
794 frame_time = 0;
795 idle_time = 0;
796 physics_time = 0;
797 physics_frame_time = 0;
798
799 print_line("PROFILING ALRIGHT!");
800
801 } else if (command == "stop_profiling") {
802
803 for (int i = 0; i < ScriptServer::get_language_count(); i++) {
804 ScriptServer::get_language(i)->profiling_stop();
805 }
806 profiling = false;
807 _send_profiling_data(false);
808 print_line("PROFILING END!");
809 } else if (command == "start_network_profiling") {
810
811 multiplayer->profiling_start();
812 profiling_network = true;
813 } else if (command == "stop_network_profiling") {
814
815 multiplayer->profiling_end();
816 profiling_network = false;
817 } else if (command == "override_camera_2D:set") {
818 bool enforce = cmd[1];
819
820 if (scene_tree) {
821 scene_tree->get_root()->enable_canvas_transform_override(enforce);
822 }
823 } else if (command == "override_camera_2D:transform") {
824 Transform2D transform = cmd[1];
825
826 if (scene_tree) {
827 scene_tree->get_root()->set_canvas_transform_override(transform);
828 }
829 } else if (command == "override_camera_3D:set") {
830 bool enable = cmd[1];
831
832 if (scene_tree) {
833 scene_tree->get_root()->enable_camera_override(enable);
834 }
835 } else if (command == "override_camera_3D:transform") {
836 Transform transform = cmd[1];
837 bool is_perspective = cmd[2];
838 float size_or_fov = cmd[3];
839 float near = cmd[4];
840 float far = cmd[5];
841
842 if (scene_tree) {
843 if (is_perspective) {
844 scene_tree->get_root()->set_camera_override_perspective(size_or_fov, near, far);
845 } else {
846 scene_tree->get_root()->set_camera_override_orthogonal(size_or_fov, near, far);
847 }
848 scene_tree->get_root()->set_camera_override_transform(transform);
849 }
850
851 } else if (command == "reload_scripts") {
852 reload_all_scripts = true;
853 } else if (command == "breakpoint") {
854
855 bool set = cmd[3];
856 if (set)
857 insert_breakpoint(cmd[2], cmd[1]);
858 else
859 remove_breakpoint(cmd[2], cmd[1]);
860 } else if (command == "set_skip_breakpoints") {
861 skip_breakpoints = cmd[1];
862 } else {
863 _parse_live_edit(cmd);
864 }
865 }
866 }
867
_send_profiling_data(bool p_for_frame)868 void ScriptDebuggerRemote::_send_profiling_data(bool p_for_frame) {
869
870 int ofs = 0;
871
872 for (int i = 0; i < ScriptServer::get_language_count(); i++) {
873 if (p_for_frame)
874 ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&profile_info.write[ofs], profile_info.size() - ofs);
875 else
876 ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&profile_info.write[ofs], profile_info.size() - ofs);
877 }
878
879 for (int i = 0; i < ofs; i++) {
880 profile_info_ptrs.write[i] = &profile_info.write[i];
881 }
882
883 SortArray<ScriptLanguage::ProfilingInfo *, ProfileInfoSort> sa;
884 sa.sort(profile_info_ptrs.ptrw(), ofs);
885
886 int to_send = MIN(ofs, max_frame_functions);
887
888 //check signatures first
889 uint64_t total_script_time = 0;
890
891 for (int i = 0; i < to_send; i++) {
892
893 if (!profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) {
894
895 int idx = profiler_function_signature_map.size();
896 packet_peer_stream->put_var("profile_sig");
897 packet_peer_stream->put_var(2);
898 packet_peer_stream->put_var(profile_info_ptrs[i]->signature);
899 packet_peer_stream->put_var(idx);
900
901 profiler_function_signature_map[profile_info_ptrs[i]->signature] = idx;
902 }
903
904 total_script_time += profile_info_ptrs[i]->self_time;
905 }
906
907 //send frames then
908
909 if (p_for_frame) {
910 packet_peer_stream->put_var("profile_frame");
911 packet_peer_stream->put_var(8 + profile_frame_data.size() * 2 + to_send * 4);
912 } else {
913 packet_peer_stream->put_var("profile_total");
914 packet_peer_stream->put_var(8 + to_send * 4);
915 }
916
917 packet_peer_stream->put_var(Engine::get_singleton()->get_idle_frames()); //total frame time
918 packet_peer_stream->put_var(frame_time); //total frame time
919 packet_peer_stream->put_var(idle_time); //idle frame time
920 packet_peer_stream->put_var(physics_time); //fixed frame time
921 packet_peer_stream->put_var(physics_frame_time); //fixed frame time
922
923 packet_peer_stream->put_var(USEC_TO_SEC(total_script_time)); //total script execution time
924
925 if (p_for_frame) {
926
927 packet_peer_stream->put_var(profile_frame_data.size()); //how many profile framedatas to send
928 packet_peer_stream->put_var(to_send); //how many script functions to send
929 for (int i = 0; i < profile_frame_data.size(); i++) {
930
931 packet_peer_stream->put_var(profile_frame_data[i].name);
932 packet_peer_stream->put_var(profile_frame_data[i].data);
933 }
934 } else {
935 packet_peer_stream->put_var(0); //how many script functions to send
936 packet_peer_stream->put_var(to_send); //how many script functions to send
937 }
938
939 for (int i = 0; i < to_send; i++) {
940
941 int sig_id = -1;
942
943 if (profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) {
944 sig_id = profiler_function_signature_map[profile_info_ptrs[i]->signature];
945 }
946
947 packet_peer_stream->put_var(sig_id);
948 packet_peer_stream->put_var(profile_info_ptrs[i]->call_count);
949 packet_peer_stream->put_var(profile_info_ptrs[i]->total_time / 1000000.0);
950 packet_peer_stream->put_var(profile_info_ptrs[i]->self_time / 1000000.0);
951 }
952
953 if (p_for_frame) {
954 profile_frame_data.clear();
955 }
956 }
957
idle_poll()958 void ScriptDebuggerRemote::idle_poll() {
959
960 // this function is called every frame, except when there is a debugger break (::debug() in this class)
961 // execution stops and remains in the ::debug function
962
963 _get_output();
964
965 if (requested_quit) {
966
967 packet_peer_stream->put_var("kill_me");
968 packet_peer_stream->put_var(0);
969 requested_quit = false;
970 }
971
972 if (performance) {
973
974 uint64_t pt = OS::get_singleton()->get_ticks_msec();
975 if (pt - last_perf_time > 1000) {
976
977 last_perf_time = pt;
978 int max = performance->get("MONITOR_MAX");
979 Array arr;
980 arr.resize(max);
981 for (int i = 0; i < max; i++) {
982 arr[i] = performance->call("get_monitor", i);
983 }
984 packet_peer_stream->put_var("performance");
985 packet_peer_stream->put_var(1);
986 packet_peer_stream->put_var(arr);
987 }
988 }
989
990 if (profiling) {
991
992 if (skip_profile_frame) {
993 skip_profile_frame = false;
994 } else {
995 //send profiling info normally
996 _send_profiling_data(true);
997 }
998 }
999
1000 if (profiling_network) {
1001 uint64_t pt = OS::get_singleton()->get_ticks_msec();
1002 if (pt - last_net_bandwidth_time > 200) {
1003 last_net_bandwidth_time = pt;
1004 _send_network_bandwidth_usage();
1005 }
1006 if (pt - last_net_prof_time > 100) {
1007 last_net_prof_time = pt;
1008 _send_network_profiling_data();
1009 }
1010 }
1011
1012 if (reload_all_scripts) {
1013
1014 for (int i = 0; i < ScriptServer::get_language_count(); i++) {
1015 ScriptServer::get_language(i)->reload_all_scripts();
1016 }
1017 reload_all_scripts = false;
1018 }
1019
1020 _poll_events();
1021 }
1022
_send_network_profiling_data()1023 void ScriptDebuggerRemote::_send_network_profiling_data() {
1024 ERR_FAIL_COND(multiplayer.is_null());
1025
1026 int n_nodes = multiplayer->get_profiling_frame(&network_profile_info.write[0]);
1027
1028 packet_peer_stream->put_var("network_profile");
1029 packet_peer_stream->put_var(n_nodes * 6);
1030 for (int i = 0; i < n_nodes; ++i) {
1031 packet_peer_stream->put_var(network_profile_info[i].node);
1032 packet_peer_stream->put_var(network_profile_info[i].node_path);
1033 packet_peer_stream->put_var(network_profile_info[i].incoming_rpc);
1034 packet_peer_stream->put_var(network_profile_info[i].incoming_rset);
1035 packet_peer_stream->put_var(network_profile_info[i].outgoing_rpc);
1036 packet_peer_stream->put_var(network_profile_info[i].outgoing_rset);
1037 }
1038 }
1039
_send_network_bandwidth_usage()1040 void ScriptDebuggerRemote::_send_network_bandwidth_usage() {
1041 ERR_FAIL_COND(multiplayer.is_null());
1042
1043 int incoming_bandwidth = multiplayer->get_incoming_bandwidth_usage();
1044 int outgoing_bandwidth = multiplayer->get_outgoing_bandwidth_usage();
1045
1046 packet_peer_stream->put_var("network_bandwidth");
1047 packet_peer_stream->put_var(2);
1048 packet_peer_stream->put_var(incoming_bandwidth);
1049 packet_peer_stream->put_var(outgoing_bandwidth);
1050 }
1051
send_message(const String & p_message,const Array & p_args)1052 void ScriptDebuggerRemote::send_message(const String &p_message, const Array &p_args) {
1053
1054 mutex->lock();
1055 if (!locking && tcp_client->is_connected_to_host()) {
1056
1057 if (messages.size() >= max_messages_per_frame) {
1058 n_messages_dropped++;
1059 } else {
1060 Message msg;
1061 msg.message = p_message;
1062 msg.data = p_args;
1063 messages.push_back(msg);
1064 }
1065 }
1066 mutex->unlock();
1067 }
1068
send_error(const String & p_func,const String & p_file,int p_line,const String & p_err,const String & p_descr,ErrorHandlerType p_type,const Vector<ScriptLanguage::StackInfo> & p_stack_info)1069 void ScriptDebuggerRemote::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info) {
1070
1071 OutputError oe;
1072 oe.error = p_err;
1073 oe.error_descr = p_descr;
1074 oe.source_file = p_file;
1075 oe.source_line = p_line;
1076 oe.source_func = p_func;
1077 oe.warning = p_type == ERR_HANDLER_WARNING;
1078 uint64_t time = OS::get_singleton()->get_ticks_msec();
1079 oe.hr = time / 3600000;
1080 oe.min = (time / 60000) % 60;
1081 oe.sec = (time / 1000) % 60;
1082 oe.msec = time % 1000;
1083 Array cstack;
1084
1085 uint64_t ticks = OS::get_singleton()->get_ticks_usec() / 1000;
1086 msec_count += ticks - last_msec;
1087 last_msec = ticks;
1088
1089 if (msec_count > 1000) {
1090 msec_count = 0;
1091
1092 err_count = 0;
1093 n_errors_dropped = 0;
1094 warn_count = 0;
1095 n_warnings_dropped = 0;
1096 }
1097
1098 cstack.resize(p_stack_info.size() * 3);
1099 for (int i = 0; i < p_stack_info.size(); i++) {
1100 cstack[i * 3 + 0] = p_stack_info[i].file;
1101 cstack[i * 3 + 1] = p_stack_info[i].func;
1102 cstack[i * 3 + 2] = p_stack_info[i].line;
1103 }
1104
1105 oe.callstack = cstack;
1106 if (oe.warning) {
1107 warn_count++;
1108 } else {
1109 err_count++;
1110 }
1111
1112 mutex->lock();
1113
1114 if (!locking && tcp_client->is_connected_to_host()) {
1115
1116 if (oe.warning) {
1117 if (warn_count > max_warnings_per_second) {
1118 n_warnings_dropped++;
1119 } else {
1120 errors.push_back(oe);
1121 }
1122 } else {
1123 if (err_count > max_errors_per_second) {
1124 n_errors_dropped++;
1125 } else {
1126 errors.push_back(oe);
1127 }
1128 }
1129 }
1130
1131 mutex->unlock();
1132 }
1133
_print_handler(void * p_this,const String & p_string,bool p_error)1134 void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string, bool p_error) {
1135
1136 ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)p_this;
1137
1138 uint64_t ticks = OS::get_singleton()->get_ticks_usec() / 1000;
1139 sdr->msec_count += ticks - sdr->last_msec;
1140 sdr->last_msec = ticks;
1141
1142 if (sdr->msec_count > 1000) {
1143 sdr->char_count = 0;
1144 sdr->msec_count = 0;
1145 }
1146
1147 String s = p_string;
1148 int allowed_chars = MIN(MAX(sdr->max_cps - sdr->char_count, 0), s.length());
1149
1150 if (allowed_chars == 0 && s.length() > 0)
1151 return;
1152
1153 if (allowed_chars < s.length()) {
1154 s = s.substr(0, allowed_chars);
1155 }
1156
1157 sdr->char_count += allowed_chars;
1158 bool overflowed = sdr->char_count >= sdr->max_cps;
1159
1160 sdr->mutex->lock();
1161 if (!sdr->locking && sdr->tcp_client->is_connected_to_host()) {
1162
1163 if (overflowed)
1164 s += "[...]";
1165
1166 OutputString output_string;
1167 output_string.message = s;
1168 output_string.type = p_error ? MESSAGE_TYPE_ERROR : MESSAGE_TYPE_LOG;
1169 sdr->output_strings.push_back(output_string);
1170
1171 if (overflowed) {
1172 output_string.message = "[output overflow, print less text!]";
1173 output_string.type = MESSAGE_TYPE_ERROR;
1174 sdr->output_strings.push_back(output_string);
1175 }
1176 }
1177 sdr->mutex->unlock();
1178 }
1179
request_quit()1180 void ScriptDebuggerRemote::request_quit() {
1181
1182 requested_quit = true;
1183 }
1184
set_multiplayer(Ref<MultiplayerAPI> p_multiplayer)1185 void ScriptDebuggerRemote::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
1186 multiplayer = p_multiplayer;
1187 }
1188
is_profiling() const1189 bool ScriptDebuggerRemote::is_profiling() const {
1190
1191 return profiling;
1192 }
add_profiling_frame_data(const StringName & p_name,const Array & p_data)1193 void ScriptDebuggerRemote::add_profiling_frame_data(const StringName &p_name, const Array &p_data) {
1194
1195 int idx = -1;
1196 for (int i = 0; i < profile_frame_data.size(); i++) {
1197 if (profile_frame_data[i].name == p_name) {
1198 idx = i;
1199 break;
1200 }
1201 }
1202
1203 FrameData fd;
1204 fd.name = p_name;
1205 fd.data = p_data;
1206
1207 if (idx == -1) {
1208 profile_frame_data.push_back(fd);
1209 } else {
1210 profile_frame_data.write[idx] = fd;
1211 }
1212 }
1213
profiling_start()1214 void ScriptDebuggerRemote::profiling_start() {
1215 //ignores this, uses it via connection
1216 }
1217
profiling_end()1218 void ScriptDebuggerRemote::profiling_end() {
1219 //ignores this, uses it via connection
1220 }
1221
profiling_set_frame_times(float p_frame_time,float p_idle_time,float p_physics_time,float p_physics_frame_time)1222 void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
1223
1224 frame_time = p_frame_time;
1225 idle_time = p_idle_time;
1226 physics_time = p_physics_time;
1227 physics_frame_time = p_physics_frame_time;
1228 }
1229
set_skip_breakpoints(bool p_skip_breakpoints)1230 void ScriptDebuggerRemote::set_skip_breakpoints(bool p_skip_breakpoints) {
1231 skip_breakpoints = p_skip_breakpoints;
1232 }
1233
1234 ScriptDebuggerRemote::ResourceUsageFunc ScriptDebuggerRemote::resource_usage_func = NULL;
1235
ScriptDebuggerRemote()1236 ScriptDebuggerRemote::ScriptDebuggerRemote() :
1237 profiling(false),
1238 profiling_network(false),
1239 max_frame_functions(16),
1240 skip_profile_frame(false),
1241 reload_all_scripts(false),
1242 tcp_client(Ref<StreamPeerTCP>(memnew(StreamPeerTCP))),
1243 packet_peer_stream(Ref<PacketPeerStream>(memnew(PacketPeerStream))),
1244 last_perf_time(0),
1245 last_net_prof_time(0),
1246 last_net_bandwidth_time(0),
1247 performance(Engine::get_singleton()->get_singleton_object("Performance")),
1248 requested_quit(false),
1249 mutex(Mutex::create()),
1250 max_messages_per_frame(GLOBAL_GET("network/limits/debugger_stdout/max_messages_per_frame")),
1251 n_messages_dropped(0),
1252 max_errors_per_second(GLOBAL_GET("network/limits/debugger_stdout/max_errors_per_second")),
1253 max_warnings_per_second(GLOBAL_GET("network/limits/debugger_stdout/max_warnings_per_second")),
1254 n_errors_dropped(0),
1255 max_cps(GLOBAL_GET("network/limits/debugger_stdout/max_chars_per_second")),
1256 char_count(0),
1257 err_count(0),
1258 warn_count(0),
1259 last_msec(0),
1260 msec_count(0),
1261 locking(false),
1262 poll_every(0),
1263 scene_tree(NULL) {
1264
1265 packet_peer_stream->set_stream_peer(tcp_client);
1266 packet_peer_stream->set_output_buffer_max_size((1024 * 1024 * 8) - 4); // 8 MiB should be way more than enough, minus 4 bytes for separator.
1267
1268 phl.printfunc = _print_handler;
1269 phl.userdata = this;
1270 add_print_handler(&phl);
1271
1272 eh.errfunc = _err_handler;
1273 eh.userdata = this;
1274 add_error_handler(&eh);
1275
1276 profile_info.resize(GLOBAL_GET("debug/settings/profiler/max_functions"));
1277 network_profile_info.resize(GLOBAL_GET("debug/settings/profiler/max_functions"));
1278 profile_info_ptrs.resize(profile_info.size());
1279 }
1280
~ScriptDebuggerRemote()1281 ScriptDebuggerRemote::~ScriptDebuggerRemote() {
1282
1283 remove_print_handler(&phl);
1284 remove_error_handler(&eh);
1285 memdelete(mutex);
1286 }
1287