script_debugger_remote.cpp 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. /*************************************************************************/
  2. /* script_debugger_remote.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "script_debugger_remote.h"
  30. #include "os/os.h"
  31. #include "io/ip.h"
  32. #include "globals.h"
  33. #include "os/input.h"
  34. void ScriptDebuggerRemote::_send_video_memory() {
  35. List<ResourceUsage> usage;
  36. if (resource_usage_func)
  37. resource_usage_func(&usage);
  38. usage.sort();
  39. packet_peer_stream->put_var("message:video_mem");
  40. packet_peer_stream->put_var(usage.size()*4);
  41. for(List<ResourceUsage>::Element *E=usage.front();E;E=E->next()) {
  42. packet_peer_stream->put_var(E->get().path);
  43. packet_peer_stream->put_var(E->get().type);
  44. packet_peer_stream->put_var(E->get().format);
  45. packet_peer_stream->put_var(E->get().vram);
  46. }
  47. }
  48. Error ScriptDebuggerRemote::connect_to_host(const String& p_host,uint16_t p_port) {
  49. IP_Address ip;
  50. if (p_host.is_valid_ip_address())
  51. ip=p_host;
  52. else
  53. ip = IP::get_singleton()->resolve_hostname(p_host);
  54. int port = p_port;
  55. int tries = 3;
  56. tcp_client->connect(ip, port);
  57. while (tries--) {
  58. if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
  59. break;
  60. } else {
  61. OS::get_singleton()->delay_usec(1000000);
  62. print_line("Remote Debugger: Connection failed with status: " + String::num(tcp_client->get_status())+"'', retrying in 1 sec.");
  63. };
  64. };
  65. if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
  66. print_line("Remote Debugger: Unable to connect");
  67. return FAILED;
  68. };
  69. // print_line("Remote Debugger: Connection OK!");
  70. packet_peer_stream->set_stream_peer(tcp_client);
  71. return OK;
  72. }
  73. static int _ScriptDebuggerRemote_found_id=0;
  74. static Object* _ScriptDebuggerRemote_find=NULL;
  75. static void _ScriptDebuggerRemote_debug_func(Object *p_obj) {
  76. if (_ScriptDebuggerRemote_find==p_obj) {
  77. _ScriptDebuggerRemote_found_id=p_obj->get_instance_ID();
  78. }
  79. }
  80. static ObjectID safe_get_instance_id(const Variant& p_v) {
  81. Object *o = p_v;
  82. if (o==NULL)
  83. return 0;
  84. else {
  85. REF r = p_v;
  86. if (r.is_valid()) {
  87. return r->get_instance_ID();
  88. } else {
  89. _ScriptDebuggerRemote_found_id=0;
  90. _ScriptDebuggerRemote_find=NULL;
  91. ObjectDB::debug_objects(_ScriptDebuggerRemote_debug_func);
  92. return _ScriptDebuggerRemote_found_id;
  93. }
  94. }
  95. }
  96. void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
  97. //this function is called when there is a debugger break (bug on script)
  98. //or when execution is paused from editor
  99. if (!tcp_client->is_connected()) {
  100. ERR_EXPLAIN("Script Debugger failed to connect, but being used anyway.");
  101. ERR_FAIL();
  102. }
  103. packet_peer_stream->put_var("debug_enter");
  104. packet_peer_stream->put_var(2);
  105. packet_peer_stream->put_var(p_can_continue);
  106. packet_peer_stream->put_var(p_script->debug_get_error());
  107. skip_profile_frame=true; // to avoid super long frame time for the frame
  108. Input::MouseMode mouse_mode=Input::get_singleton()->get_mouse_mode();
  109. if (mouse_mode!=Input::MOUSE_MODE_VISIBLE)
  110. Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
  111. while(true) {
  112. _get_output();
  113. if (packet_peer_stream->get_available_packet_count()>0) {
  114. Variant var;
  115. Error err = packet_peer_stream->get_var(var);
  116. ERR_CONTINUE( err != OK);
  117. ERR_CONTINUE( var.get_type()!=Variant::ARRAY );
  118. Array cmd = var;
  119. ERR_CONTINUE( cmd.size()==0);
  120. ERR_CONTINUE( cmd[0].get_type()!=Variant::STRING );
  121. String command = cmd[0];
  122. if (command=="get_stack_dump") {
  123. packet_peer_stream->put_var("stack_dump");
  124. int slc = p_script->debug_get_stack_level_count();
  125. packet_peer_stream->put_var( slc );
  126. for(int i=0;i<slc;i++) {
  127. Dictionary d;
  128. d["file"]=p_script->debug_get_stack_level_source(i);
  129. d["line"]=p_script->debug_get_stack_level_line(i);
  130. d["function"]=p_script->debug_get_stack_level_function(i);
  131. //d["id"]=p_script->debug_get_stack_level_
  132. d["id"]=0;
  133. packet_peer_stream->put_var( d );
  134. }
  135. } else if (command=="get_stack_frame_vars") {
  136. cmd.remove(0);
  137. ERR_CONTINUE( cmd.size()!=1 );
  138. int lv = cmd[0];
  139. List<String> members;
  140. List<Variant> member_vals;
  141. p_script->debug_get_stack_level_members(lv,&members,&member_vals);
  142. ERR_CONTINUE( members.size() !=member_vals.size() );
  143. List<String> locals;
  144. List<Variant> local_vals;
  145. p_script->debug_get_stack_level_locals(lv,&locals,&local_vals);
  146. ERR_CONTINUE( locals.size() !=local_vals.size() );
  147. packet_peer_stream->put_var("stack_frame_vars");
  148. packet_peer_stream->put_var(2+locals.size()*2+members.size()*2);
  149. { //members
  150. packet_peer_stream->put_var(members.size());
  151. List<String>::Element *E=members.front();
  152. List<Variant>::Element *F=member_vals.front();
  153. while(E) {
  154. if (F->get().get_type()==Variant::OBJECT) {
  155. packet_peer_stream->put_var("*"+E->get());
  156. packet_peer_stream->put_var(safe_get_instance_id(F->get()));
  157. } else {
  158. packet_peer_stream->put_var(E->get());
  159. packet_peer_stream->put_var(F->get());
  160. }
  161. E=E->next();
  162. F=F->next();
  163. }
  164. }
  165. { //locals
  166. packet_peer_stream->put_var(locals.size());
  167. List<String>::Element *E=locals.front();
  168. List<Variant>::Element *F=local_vals.front();
  169. while(E) {
  170. if (F->get().get_type()==Variant::OBJECT) {
  171. packet_peer_stream->put_var("*"+E->get());
  172. packet_peer_stream->put_var(safe_get_instance_id(F->get()));
  173. } else {
  174. packet_peer_stream->put_var(E->get());
  175. packet_peer_stream->put_var(F->get());
  176. }
  177. E=E->next();
  178. F=F->next();
  179. }
  180. }
  181. } else if (command=="step") {
  182. set_depth(-1);
  183. set_lines_left(1);
  184. break;
  185. } else if (command=="next") {
  186. set_depth(0);
  187. set_lines_left(1);
  188. break;
  189. } else if (command=="continue") {
  190. set_depth(-1);
  191. set_lines_left(-1);
  192. break;
  193. } else if (command=="break") {
  194. ERR_PRINT("Got break when already broke!");
  195. break;
  196. } else if (command=="request_scene_tree") {
  197. if (request_scene_tree)
  198. request_scene_tree(request_scene_tree_ud);
  199. } else if (command=="request_video_mem") {
  200. _send_video_memory();
  201. } else if (command=="inspect_object") {
  202. ObjectID id = cmd[1];
  203. _send_object_id(id);
  204. } else if (command=="set_object_property") {
  205. _set_object_property(cmd[1],cmd[2],cmd[3]);
  206. } else if (command=="reload_scripts") {
  207. reload_all_scripts=true;
  208. } else if (command=="breakpoint") {
  209. bool set = cmd[3];
  210. if (set)
  211. insert_breakpoint(cmd[2],cmd[1]);
  212. else
  213. remove_breakpoint(cmd[2],cmd[1]);
  214. } else {
  215. _parse_live_edit(cmd);
  216. }
  217. } else {
  218. OS::get_singleton()->delay_usec(10000);
  219. }
  220. }
  221. packet_peer_stream->put_var("debug_exit");
  222. packet_peer_stream->put_var(0);
  223. if (mouse_mode!=Input::MOUSE_MODE_VISIBLE)
  224. Input::get_singleton()->set_mouse_mode(mouse_mode);
  225. }
  226. void ScriptDebuggerRemote::_get_output() {
  227. mutex->lock();
  228. if (output_strings.size()) {
  229. locking=true;
  230. packet_peer_stream->put_var("output");
  231. packet_peer_stream->put_var(output_strings .size());
  232. while(output_strings.size()) {
  233. packet_peer_stream->put_var(output_strings.front()->get());
  234. output_strings.pop_front();
  235. }
  236. locking=false;
  237. }
  238. while (messages.size()) {
  239. locking=true;
  240. packet_peer_stream->put_var("message:"+messages.front()->get().message);
  241. packet_peer_stream->put_var(messages.front()->get().data.size());
  242. for(int i=0;i<messages.front()->get().data.size();i++) {
  243. packet_peer_stream->put_var(messages.front()->get().data[i]);
  244. }
  245. messages.pop_front();
  246. locking=false;
  247. }
  248. while (errors.size()) {
  249. locking=true;
  250. packet_peer_stream->put_var("error");
  251. OutputError oe = errors.front()->get();
  252. packet_peer_stream->put_var(oe.callstack.size()+2);
  253. Array error_data;
  254. error_data.push_back(oe.hr);
  255. error_data.push_back(oe.min);
  256. error_data.push_back(oe.sec);
  257. error_data.push_back(oe.msec);
  258. error_data.push_back(oe.source_func);
  259. error_data.push_back(oe.source_file);
  260. error_data.push_back(oe.source_line);
  261. error_data.push_back(oe.error);
  262. error_data.push_back(oe.error_descr);
  263. error_data.push_back(oe.warning);
  264. packet_peer_stream->put_var(error_data);
  265. packet_peer_stream->put_var(oe.callstack.size());
  266. for(int i=0;i<oe.callstack.size();i++) {
  267. packet_peer_stream->put_var(oe.callstack[i]);
  268. }
  269. errors.pop_front();
  270. locking=false;
  271. }
  272. mutex->unlock();
  273. }
  274. void ScriptDebuggerRemote::line_poll() {
  275. //the purpose of this is just processing events every now and then when the script might get too busy
  276. //otherwise bugs like infinite loops cant be catched
  277. if (poll_every%2048==0)
  278. _poll_events();
  279. poll_every++;
  280. }
  281. 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) {
  282. if (p_type==ERR_HANDLER_SCRIPT)
  283. return; //ignore script errors, those go through debugger
  284. ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote*)ud;
  285. OutputError oe;
  286. oe.error=p_err;
  287. oe.error_descr=p_descr;
  288. oe.source_file=p_file;
  289. oe.source_line=p_line;
  290. oe.source_func=p_func;
  291. oe.warning=p_type==ERR_HANDLER_WARNING;
  292. uint64_t time = OS::get_singleton()->get_ticks_msec();
  293. oe.hr=time/3600000;
  294. oe.min=(time/60000)%60;
  295. oe.sec=(time/1000)%60;
  296. oe.msec=time%1000;
  297. Array cstack;
  298. Vector<ScriptLanguage::StackInfo> si;
  299. for(int i=0;i<ScriptServer::get_language_count();i++) {
  300. si=ScriptServer::get_language(i)->debug_get_current_stack_info();
  301. if (si.size())
  302. break;
  303. }
  304. cstack.resize(si.size()*2);
  305. for(int i=0;i<si.size();i++) {
  306. String path;
  307. int line=0;
  308. if (si[i].script.is_valid()) {
  309. path=si[i].script->get_path();
  310. line=si[i].line;
  311. }
  312. cstack[i*2+0]=path;
  313. cstack[i*2+1]=line;
  314. }
  315. oe.callstack=cstack;
  316. sdr->mutex->lock();
  317. if (!sdr->locking && sdr->tcp_client->is_connected()) {
  318. sdr->errors.push_back(oe);
  319. }
  320. sdr->mutex->unlock();
  321. }
  322. bool ScriptDebuggerRemote::_parse_live_edit(const Array& cmd) {
  323. String cmdstr = cmd[0];
  324. if (!live_edit_funcs || !cmdstr.begins_with("live_"))
  325. return false;
  326. //print_line(Variant(cmd).get_construct_string());
  327. if (cmdstr=="live_set_root") {
  328. if (!live_edit_funcs->root_func)
  329. return true;
  330. //print_line("root: "+Variant(cmd).get_construct_string());
  331. live_edit_funcs->root_func(live_edit_funcs->udata,cmd[1],cmd[2]);
  332. } else if (cmdstr=="live_node_path") {
  333. if (!live_edit_funcs->node_path_func)
  334. return true;
  335. //print_line("path: "+Variant(cmd).get_construct_string());
  336. live_edit_funcs->node_path_func(live_edit_funcs->udata,cmd[1],cmd[2]);
  337. } else if (cmdstr=="live_res_path") {
  338. if (!live_edit_funcs->res_path_func)
  339. return true;
  340. live_edit_funcs->res_path_func(live_edit_funcs->udata,cmd[1],cmd[2]);
  341. } else if (cmdstr=="live_node_prop_res") {
  342. if (!live_edit_funcs->node_set_res_func)
  343. return true;
  344. live_edit_funcs->node_set_res_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
  345. } else if (cmdstr=="live_node_prop") {
  346. if (!live_edit_funcs->node_set_func)
  347. return true;
  348. live_edit_funcs->node_set_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
  349. } else if (cmdstr=="live_res_prop_res") {
  350. if (!live_edit_funcs->res_set_res_func)
  351. return true;
  352. live_edit_funcs->res_set_res_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
  353. } else if (cmdstr=="live_res_prop") {
  354. if (!live_edit_funcs->res_set_func)
  355. return true;
  356. live_edit_funcs->res_set_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
  357. } else if (cmdstr=="live_node_call") {
  358. if (!live_edit_funcs->node_call_func)
  359. return true;
  360. live_edit_funcs->node_call_func(live_edit_funcs->udata,cmd[1],cmd[2], cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]);
  361. } else if (cmdstr=="live_res_call") {
  362. if (!live_edit_funcs->res_call_func)
  363. return true;
  364. live_edit_funcs->res_call_func(live_edit_funcs->udata,cmd[1],cmd[2], cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]);
  365. } else if (cmdstr=="live_create_node") {
  366. live_edit_funcs->tree_create_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
  367. } else if (cmdstr=="live_instance_node") {
  368. live_edit_funcs->tree_instance_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
  369. } else if (cmdstr=="live_remove_node") {
  370. live_edit_funcs->tree_remove_node_func(live_edit_funcs->udata,cmd[1]);
  371. } else if (cmdstr=="live_remove_and_keep_node") {
  372. live_edit_funcs->tree_remove_and_keep_node_func(live_edit_funcs->udata,cmd[1],cmd[2]);
  373. } else if (cmdstr=="live_restore_node") {
  374. live_edit_funcs->tree_restore_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
  375. } else if (cmdstr=="live_duplicate_node") {
  376. live_edit_funcs->tree_duplicate_node_func(live_edit_funcs->udata,cmd[1],cmd[2]);
  377. } else if (cmdstr=="live_reparent_node") {
  378. live_edit_funcs->tree_reparent_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3],cmd[4]);
  379. } else {
  380. return false;
  381. }
  382. return true;
  383. }
  384. void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
  385. Object* obj = ObjectDB::get_instance(p_id);
  386. if (!obj)
  387. return;
  388. List<PropertyInfo> pinfo;
  389. obj->get_property_list(&pinfo,true);
  390. int props_to_send=0;
  391. for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
  392. if (E->get().usage&(PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CATEGORY)) {
  393. props_to_send++;
  394. }
  395. }
  396. packet_peer_stream->put_var("message:inspect_object");
  397. packet_peer_stream->put_var(props_to_send*5+4);
  398. packet_peer_stream->put_var(p_id);
  399. packet_peer_stream->put_var(obj->get_type());
  400. if (obj->is_type("Resource") || obj->is_type("Node"))
  401. packet_peer_stream->put_var(obj->call("get_path"));
  402. else
  403. packet_peer_stream->put_var("");
  404. packet_peer_stream->put_var(props_to_send);
  405. for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
  406. if (E->get().usage&(PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CATEGORY)) {
  407. if (E->get().usage&PROPERTY_USAGE_CATEGORY) {
  408. packet_peer_stream->put_var("*"+E->get().name);
  409. } else {
  410. packet_peer_stream->put_var(E->get().name);
  411. }
  412. Variant var = obj->get(E->get().name);
  413. if (E->get().type==Variant::OBJECT || var.get_type()==Variant::OBJECT) {
  414. ObjectID id2;
  415. Object *obj=var;
  416. if (obj) {
  417. id2=obj->get_instance_ID();
  418. } else {
  419. id2=0;
  420. }
  421. packet_peer_stream->put_var(Variant::INT); //hint string
  422. packet_peer_stream->put_var(PROPERTY_HINT_OBJECT_ID); //hint
  423. packet_peer_stream->put_var(E->get().hint_string); //hint string
  424. packet_peer_stream->put_var(id2); //value
  425. } else {
  426. packet_peer_stream->put_var(E->get().type);
  427. packet_peer_stream->put_var(E->get().hint);
  428. packet_peer_stream->put_var(E->get().hint_string);
  429. //only send information that can be sent..
  430. if (var.get_type()==Variant::IMAGE) {
  431. var=Image();
  432. }
  433. if (var.get_type()>=Variant::DICTIONARY) {
  434. var=Array(); //send none for now, may be to big
  435. }
  436. packet_peer_stream->put_var(var);
  437. }
  438. }
  439. }
  440. }
  441. void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String& p_property, const Variant& p_value) {
  442. Object* obj = ObjectDB::get_instance(p_id);
  443. if (!obj)
  444. return;
  445. obj->set(p_property,p_value);
  446. }
  447. void ScriptDebuggerRemote::_poll_events() {
  448. //this si called from ::idle_poll, happens only when running the game,
  449. //does not get called while on debug break
  450. while(packet_peer_stream->get_available_packet_count()>0) {
  451. _get_output();
  452. //send over output_strings
  453. Variant var;
  454. Error err = packet_peer_stream->get_var(var);
  455. ERR_CONTINUE( err != OK);
  456. ERR_CONTINUE( var.get_type()!=Variant::ARRAY );
  457. Array cmd = var;
  458. ERR_CONTINUE( cmd.size()==0);
  459. ERR_CONTINUE( cmd[0].get_type()!=Variant::STRING );
  460. String command = cmd[0];
  461. //cmd.remove(0);
  462. if (command=="break") {
  463. if (get_break_language())
  464. debug(get_break_language());
  465. } else if (command=="request_scene_tree") {
  466. if (request_scene_tree)
  467. request_scene_tree(request_scene_tree_ud);
  468. } else if (command=="request_video_mem") {
  469. _send_video_memory();
  470. } else if (command=="inspect_object") {
  471. ObjectID id = cmd[1];
  472. _send_object_id(id);
  473. } else if (command=="set_object_property") {
  474. _set_object_property(cmd[1],cmd[2],cmd[3]);
  475. } else if (command=="start_profiling") {
  476. for(int i=0;i<ScriptServer::get_language_count();i++) {
  477. ScriptServer::get_language(i)->profiling_start();
  478. }
  479. max_frame_functions=cmd[1];
  480. profiler_function_signature_map.clear();
  481. profiling=true;
  482. frame_time=0;
  483. idle_time=0;
  484. fixed_time=0;
  485. fixed_frame_time=0;
  486. print_line("PROFILING ALRIGHT!");
  487. } else if (command=="stop_profiling") {
  488. for(int i=0;i<ScriptServer::get_language_count();i++) {
  489. ScriptServer::get_language(i)->profiling_stop();
  490. }
  491. profiling=false;
  492. _send_profiling_data(false);
  493. print_line("PROFILING END!");
  494. } else if (command=="reload_scripts") {
  495. reload_all_scripts=true;
  496. } else if (command=="breakpoint") {
  497. bool set = cmd[3];
  498. if (set)
  499. insert_breakpoint(cmd[2],cmd[1]);
  500. else
  501. remove_breakpoint(cmd[2],cmd[1]);
  502. } else {
  503. _parse_live_edit(cmd);
  504. }
  505. }
  506. }
  507. void ScriptDebuggerRemote::_send_profiling_data(bool p_for_frame) {
  508. int ofs=0;
  509. for(int i=0;i<ScriptServer::get_language_count();i++) {
  510. if (p_for_frame)
  511. ofs+=ScriptServer::get_language(i)->profiling_get_frame_data(&profile_info[ofs],profile_info.size()-ofs);
  512. else
  513. ofs+=ScriptServer::get_language(i)->profiling_get_accumulated_data(&profile_info[ofs],profile_info.size()-ofs);
  514. }
  515. for(int i=0;i<ofs;i++) {
  516. profile_info_ptrs[i]=&profile_info[i];
  517. }
  518. SortArray<ScriptLanguage::ProfilingInfo*,ProfileInfoSort> sa;
  519. sa.sort(profile_info_ptrs.ptr(),ofs);
  520. int to_send=MIN(ofs,max_frame_functions);
  521. //check signatures first
  522. uint64_t total_script_time=0;
  523. for(int i=0;i<to_send;i++) {
  524. if (!profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) {
  525. int idx = profiler_function_signature_map.size();
  526. packet_peer_stream->put_var("profile_sig");
  527. packet_peer_stream->put_var(2);
  528. packet_peer_stream->put_var(profile_info_ptrs[i]->signature);
  529. packet_peer_stream->put_var(idx);
  530. profiler_function_signature_map[profile_info_ptrs[i]->signature]=idx;
  531. }
  532. total_script_time+=profile_info_ptrs[i]->self_time;
  533. }
  534. //send frames then
  535. if (p_for_frame) {
  536. packet_peer_stream->put_var("profile_frame");
  537. packet_peer_stream->put_var(8+profile_frame_data.size()*2+to_send*4);
  538. } else {
  539. packet_peer_stream->put_var("profile_total");
  540. packet_peer_stream->put_var(8+to_send*4);
  541. }
  542. packet_peer_stream->put_var(OS::get_singleton()->get_frames_drawn()); //total frame time
  543. packet_peer_stream->put_var(frame_time); //total frame time
  544. packet_peer_stream->put_var(idle_time); //idle frame time
  545. packet_peer_stream->put_var(fixed_time); //fixed frame time
  546. packet_peer_stream->put_var(fixed_frame_time); //fixed frame time
  547. packet_peer_stream->put_var(USEC_TO_SEC(total_script_time)); //total script execution time
  548. if (p_for_frame) {
  549. packet_peer_stream->put_var(profile_frame_data.size()); //how many profile framedatas to send
  550. packet_peer_stream->put_var(to_send); //how many script functions to send
  551. for (int i=0;i<profile_frame_data.size();i++) {
  552. packet_peer_stream->put_var(profile_frame_data[i].name);
  553. packet_peer_stream->put_var(profile_frame_data[i].data);
  554. }
  555. } else {
  556. packet_peer_stream->put_var(0); //how many script functions to send
  557. packet_peer_stream->put_var(to_send); //how many script functions to send
  558. }
  559. for(int i=0;i<to_send;i++) {
  560. int sig_id=-1;
  561. if (profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) {
  562. sig_id=profiler_function_signature_map[profile_info_ptrs[i]->signature];
  563. }
  564. packet_peer_stream->put_var(sig_id);
  565. packet_peer_stream->put_var(profile_info_ptrs[i]->call_count);
  566. packet_peer_stream->put_var(profile_info_ptrs[i]->total_time/1000000.0);
  567. packet_peer_stream->put_var(profile_info_ptrs[i]->self_time/1000000.0);
  568. }
  569. if (p_for_frame) {
  570. profile_frame_data.clear();
  571. }
  572. }
  573. void ScriptDebuggerRemote::idle_poll() {
  574. // this function is called every frame, except when there is a debugger break (::debug() in this class)
  575. // execution stops and remains in the ::debug function
  576. _get_output();
  577. if (requested_quit) {
  578. packet_peer_stream->put_var("kill_me");
  579. packet_peer_stream->put_var(0);
  580. requested_quit=false;
  581. }
  582. if (performance) {
  583. uint64_t pt = OS::get_singleton()->get_ticks_msec();
  584. if (pt-last_perf_time > 1000) {
  585. last_perf_time=pt;
  586. int max = performance->get("MONITOR_MAX");
  587. Array arr;
  588. arr.resize(max);
  589. for(int i=0;i<max;i++) {
  590. arr[i]=performance->call("get_monitor",i);
  591. }
  592. packet_peer_stream->put_var("performance");
  593. packet_peer_stream->put_var(1);
  594. packet_peer_stream->put_var(arr);
  595. }
  596. }
  597. if (profiling) {
  598. if (skip_profile_frame) {
  599. skip_profile_frame=false;
  600. } else {
  601. //send profiling info normally
  602. _send_profiling_data(true);
  603. }
  604. }
  605. if (reload_all_scripts) {
  606. for(int i=0;i<ScriptServer::get_language_count();i++) {
  607. ScriptServer::get_language(i)->reload_all_scripts();
  608. }
  609. reload_all_scripts=false;
  610. }
  611. _poll_events();
  612. }
  613. void ScriptDebuggerRemote::send_message(const String& p_message, const Array &p_args) {
  614. mutex->lock();
  615. if (!locking && tcp_client->is_connected()) {
  616. Message msg;
  617. msg.message=p_message;
  618. msg.data=p_args;
  619. messages.push_back(msg);
  620. }
  621. mutex->unlock();
  622. }
  623. void ScriptDebuggerRemote::_print_handler(void *p_this,const String& p_string) {
  624. ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote*)p_this;
  625. uint64_t ticks = OS::get_singleton()->get_ticks_usec()/1000;
  626. sdr->msec_count+=ticks-sdr->last_msec;
  627. sdr->last_msec=ticks;
  628. if (sdr->msec_count>1000) {
  629. sdr->char_count=0;
  630. sdr->msec_count=0;
  631. }
  632. String s = p_string;
  633. int allowed_chars = MIN(MAX(sdr->max_cps - sdr->char_count,0), s.length());
  634. if (allowed_chars==0)
  635. return;
  636. if (allowed_chars<s.length()) {
  637. s=s.substr(0,allowed_chars);
  638. }
  639. sdr->char_count+=allowed_chars;
  640. if (sdr->char_count>=sdr->max_cps) {
  641. s+="\n[output overflow, print less text!]\n";
  642. }
  643. sdr->mutex->lock();
  644. if (!sdr->locking && sdr->tcp_client->is_connected()) {
  645. sdr->output_strings.push_back(s);
  646. }
  647. sdr->mutex->unlock();
  648. }
  649. void ScriptDebuggerRemote::request_quit() {
  650. requested_quit=true;
  651. }
  652. void ScriptDebuggerRemote::set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata) {
  653. request_scene_tree=p_func;
  654. request_scene_tree_ud=p_udata;
  655. }
  656. void ScriptDebuggerRemote::set_live_edit_funcs(LiveEditFuncs *p_funcs) {
  657. live_edit_funcs=p_funcs;
  658. }
  659. bool ScriptDebuggerRemote::is_profiling() const {
  660. return profiling;
  661. }
  662. void ScriptDebuggerRemote::add_profiling_frame_data(const StringName& p_name,const Array& p_data){
  663. int idx=-1;
  664. for(int i=0;i<profile_frame_data.size();i++) {
  665. if (profile_frame_data[i].name==p_name) {
  666. idx=i;
  667. break;
  668. }
  669. }
  670. FrameData fd;
  671. fd.name=p_name;
  672. fd.data=p_data;
  673. if (idx==-1) {
  674. profile_frame_data.push_back(fd);
  675. } else {
  676. profile_frame_data[idx]=fd;
  677. }
  678. }
  679. void ScriptDebuggerRemote::profiling_start() {
  680. //ignores this, uses it via connnection
  681. }
  682. void ScriptDebuggerRemote::profiling_end() {
  683. //ignores this, uses it via connnection
  684. }
  685. void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time) {
  686. frame_time=p_frame_time;
  687. idle_time=p_idle_time;
  688. fixed_time=p_fixed_time;
  689. fixed_frame_time=p_fixed_frame_time;
  690. }
  691. ScriptDebuggerRemote::ResourceUsageFunc ScriptDebuggerRemote::resource_usage_func=NULL;
  692. ScriptDebuggerRemote::ScriptDebuggerRemote() {
  693. tcp_client = StreamPeerTCP::create_ref();
  694. packet_peer_stream = Ref<PacketPeerStream>( memnew(PacketPeerStream) );
  695. packet_peer_stream->set_stream_peer(tcp_client);
  696. mutex = Mutex::create();
  697. locking=false;
  698. phl.printfunc=_print_handler;
  699. phl.userdata=this;
  700. add_print_handler(&phl);
  701. requested_quit=false;
  702. performance = Globals::get_singleton()->get_singleton_object("Performance");
  703. last_perf_time=0;
  704. poll_every=0;
  705. request_scene_tree=NULL;
  706. live_edit_funcs=NULL;
  707. max_cps = GLOBAL_DEF("debug/max_remote_stdout_chars_per_second",2048);
  708. char_count=0;
  709. msec_count=0;
  710. last_msec=0;
  711. skip_profile_frame=false;
  712. eh.errfunc=_err_handler;
  713. eh.userdata=this;
  714. add_error_handler(&eh);
  715. profile_info.resize(CLAMP(int(Globals::get_singleton()->get("debug/profiler_max_functions")),128,65535));
  716. profile_info_ptrs.resize(profile_info.size());
  717. profiling=false;
  718. max_frame_functions=16;
  719. reload_all_scripts=false;
  720. }
  721. ScriptDebuggerRemote::~ScriptDebuggerRemote() {
  722. remove_print_handler(&phl);
  723. remove_error_handler(&eh);
  724. memdelete(mutex);
  725. }