diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 33e9dc0fd98..15861ed4a16 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -127,7 +127,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { ERR_CONTINUE( cmd[0].get_type()!=Variant::STRING ); String command = cmd[0]; - cmd.remove(0); + if (command=="get_stack_dump") { @@ -150,7 +150,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { } else if (command=="get_stack_frame_vars") { - + cmd.remove(0); ERR_CONTINUE( cmd.size()!=1 ); int lv = cmd[0]; @@ -243,6 +243,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { if (request_scene_tree) request_scene_tree(request_scene_tree_ud); + } else { + _parse_live_edit(cmd); } @@ -301,6 +303,105 @@ void ScriptDebuggerRemote::line_poll() { } +bool ScriptDebuggerRemote::_parse_live_edit(const Array& cmd) { + + String cmdstr = cmd[0]; + if (!live_edit_funcs || !cmdstr.begins_with("live_")) + return false; + + + print_line(Variant(cmd).get_construct_string()); + if (cmdstr=="live_set_root") { + + if (!live_edit_funcs->root_func) + return true; + print_line("root: "+Variant(cmd).get_construct_string()); + live_edit_funcs->root_func(live_edit_funcs->udata,cmd[1],cmd[2]); + + } else if (cmdstr=="live_node_path") { + + if (!live_edit_funcs->node_path_func) + return true; + print_line("path: "+Variant(cmd).get_construct_string()); + + live_edit_funcs->node_path_func(live_edit_funcs->udata,cmd[1],cmd[2]); + + } else if (cmdstr=="live_res_path") { + + if (!live_edit_funcs->res_path_func) + return true; + live_edit_funcs->res_path_func(live_edit_funcs->udata,cmd[1],cmd[2]); + + } else if (cmdstr=="live_node_prop_res") { + if (!live_edit_funcs->node_set_res_func) + return true; + + live_edit_funcs->node_set_res_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_node_prop") { + + if (!live_edit_funcs->node_set_func) + return true; + live_edit_funcs->node_set_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_res_prop_res") { + + if (!live_edit_funcs->res_set_res_func) + return true; + live_edit_funcs->res_set_res_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_res_prop") { + + if (!live_edit_funcs->res_set_func) + return true; + live_edit_funcs->res_set_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_node_call") { + + if (!live_edit_funcs->node_call_func) + return true; + live_edit_funcs->node_call_func(live_edit_funcs->udata,cmd[1],cmd[2], cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]); + + } else if (cmdstr=="live_res_call") { + + if (!live_edit_funcs->res_call_func) + return true; + live_edit_funcs->res_call_func(live_edit_funcs->udata,cmd[1],cmd[2], cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]); + + } else if (cmdstr=="live_create_node") { + + live_edit_funcs->tree_create_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_instance_node") { + + live_edit_funcs->tree_instance_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_remove_node") { + + live_edit_funcs->tree_remove_node_func(live_edit_funcs->udata,cmd[1]); + + } else if (cmdstr=="live_remove_and_keep_node") { + + live_edit_funcs->tree_remove_and_keep_node_func(live_edit_funcs->udata,cmd[1],cmd[2]); + } else if (cmdstr=="live_restore_node") { + + live_edit_funcs->tree_restore_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_duplicate_node") { + + live_edit_funcs->tree_duplicate_node_func(live_edit_funcs->udata,cmd[1],cmd[2]); + } else if (cmdstr=="live_reparent_node") { + + live_edit_funcs->tree_reparent_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else { + + return false; + } + + return true; +} + void ScriptDebuggerRemote::_poll_events() { while(packet_peer_stream->get_available_packet_count()>0) { @@ -321,7 +422,7 @@ void ScriptDebuggerRemote::_poll_events() { ERR_CONTINUE( cmd[0].get_type()!=Variant::STRING ); String command = cmd[0]; - cmd.remove(0); + //cmd.remove(0); if (command=="break") { @@ -331,6 +432,8 @@ void ScriptDebuggerRemote::_poll_events() { if (request_scene_tree) request_scene_tree(request_scene_tree_ud); + } else { + _parse_live_edit(cmd); } } @@ -413,6 +516,11 @@ void ScriptDebuggerRemote::set_request_scene_tree_message_func(RequestSceneTreeM request_scene_tree_ud=p_udata; } +void ScriptDebuggerRemote::set_live_edit_funcs(LiveEditFuncs *p_funcs) { + + live_edit_funcs=p_funcs; +} + ScriptDebuggerRemote::ScriptDebuggerRemote() { tcp_client = StreamPeerTCP::create_ref(); @@ -429,6 +537,7 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() { last_perf_time=0; poll_every=0; request_scene_tree=NULL; + live_edit_funcs=NULL; } diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h index 89b9947c4b0..748b77eccd4 100644 --- a/core/script_debugger_remote.h +++ b/core/script_debugger_remote.h @@ -62,9 +62,12 @@ class ScriptDebuggerRemote : public ScriptDebugger { uint32_t poll_every; + bool _parse_live_edit(const Array &p_command); + RequestSceneTreeMessageFunc request_scene_tree; void *request_scene_tree_ud; + LiveEditFuncs *live_edit_funcs; public: @@ -79,6 +82,7 @@ public: virtual void send_message(const String& p_message, const Array& p_args); virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata); + virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs); ScriptDebuggerRemote(); ~ScriptDebuggerRemote(); diff --git a/core/script_language.h b/core/script_language.h index 7104fe45473..8b0ed2c33b8 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -238,6 +238,32 @@ public: typedef void (*RequestSceneTreeMessageFunc)(void *); + struct LiveEditFuncs { + + void *udata; + void (*node_path_func)(void *,const NodePath &p_path,int p_id); + void (*res_path_func)(void *,const String &p_path,int p_id); + + void (*node_set_func)(void *,int p_id,const StringName& p_prop,const Variant& p_value); + void (*node_set_res_func)(void *,int p_id,const StringName& p_prop,const String& p_value); + void (*node_call_func)(void *,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE); + void (*res_set_func)(void *,int p_id,const StringName& p_prop,const Variant& p_value); + void (*res_set_res_func)(void *,int p_id,const StringName& p_prop,const String& p_value); + void (*res_call_func)(void *,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE); + void (*root_func)(void*, const NodePath& p_scene_path,const String& p_scene_from); + + void (*tree_create_node_func)(void*,const NodePath& p_parent,const String& p_type,const String& p_name); + void (*tree_instance_node_func)(void*,const NodePath& p_parent,const String& p_path,const String& p_name); + void (*tree_remove_node_func)(void*,const NodePath& p_at); + void (*tree_remove_and_keep_node_func)(void*,const NodePath& p_at,ObjectID p_keep_id); + void (*tree_restore_node_func)(void*,ObjectID p_id,const NodePath& p_at,int p_at_pos); + void (*tree_duplicate_node_func)(void*,const NodePath& p_at,const String& p_new_name); + void (*tree_reparent_node_func)(void*,const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name); + + }; + + + _FORCE_INLINE_ static ScriptDebugger * get_singleton() { return singleton; } void set_lines_left(int p_left); int get_lines_left() const; @@ -252,10 +278,12 @@ public: bool is_breakpoint_line(int p_line) const; void clear_breakpoints(); + virtual void debug(ScriptLanguage *p_script,bool p_can_continue=true)=0; virtual void idle_poll(); virtual void line_poll(); + void set_break_language(ScriptLanguage *p_lang); ScriptLanguage* get_break_language() const; @@ -265,6 +293,7 @@ public: virtual void request_quit() {} virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata) {} + virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs) {} ScriptDebugger(); virtual ~ScriptDebugger() {singleton=NULL;} diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index f565070216a..85cc2bbc7f8 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -244,7 +244,12 @@ void UndoRedo::_process_operation_list(List::Element *E) { Resource* res = obj->cast_to(); if (res) res->set_edited(true); + #endif + + if (method_callback) { + method_callback(method_callbck_ud,obj,op.name,VARIANT_ARGS_FROM_ARRAY(op.args)); + } } break; case Operation::TYPE_PROPERTY: { @@ -254,6 +259,9 @@ void UndoRedo::_process_operation_list(List::Element *E) { if (res) res->set_edited(true); #endif + if (property_callback) { + property_callback(prop_callback_ud,obj,op.name,op.args[0]); + } } break; case Operation::TYPE_REFERENCE: { //do nothing @@ -325,6 +333,19 @@ void UndoRedo::set_commit_notify_callback(CommitNotifyCallback p_callback,void* callback_ud=p_ud; } +void UndoRedo::set_method_notify_callback(MethodNotifyCallback p_method_callback,void* p_ud) { + + method_callback=p_method_callback; + method_callbck_ud=p_ud; +} + +void UndoRedo::set_property_notify_callback(PropertyNotifyCallback p_property_callback,void* p_ud){ + + property_callback=p_property_callback; + prop_callback_ud=p_ud; +} + + UndoRedo::UndoRedo() { version=1; @@ -334,6 +355,12 @@ UndoRedo::UndoRedo() { merging=true; callback=NULL; callback_ud=NULL; + + method_callbck_ud=NULL; + prop_callback_ud=NULL; + method_callback=NULL; + property_callback=NULL; + } UndoRedo::~UndoRedo() { diff --git a/core/undo_redo.h b/core/undo_redo.h index a9187534c14..141a413c2a8 100644 --- a/core/undo_redo.h +++ b/core/undo_redo.h @@ -45,6 +45,9 @@ public: Variant _add_do_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error); Variant _add_undo_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error); + typedef void (*MethodNotifyCallback)(void *p_ud,Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE); + typedef void (*PropertyNotifyCallback)(void *p_ud,Object*p_base,const StringName& p_property,const Variant& p_value); + private: struct Operation { @@ -83,6 +86,11 @@ private: CommitNotifyCallback callback; void* callback_ud; + void* method_callbck_ud; + void* prop_callback_ud; + + MethodNotifyCallback method_callback; + PropertyNotifyCallback property_callback; protected: @@ -113,6 +121,9 @@ public: void set_commit_notify_callback(CommitNotifyCallback p_callback,void* p_ud); + void set_method_notify_callback(MethodNotifyCallback p_method_callback,void* p_ud); + void set_property_notify_callback(PropertyNotifyCallback p_property_callback,void* p_ud); + UndoRedo(); ~UndoRedo(); }; diff --git a/demos/2d/platformer/player.xml b/demos/2d/platformer/player.xml index 196881dee43..8c7b74ceae1 100644 --- a/demos/2d/platformer/player.xml +++ b/demos/2d/platformer/player.xml @@ -1,15 +1,15 @@ - - + + + - - + - - - + + + 0.5 20 @@ -19,6 +19,11 @@ 0 -19.902, -24.8691, 19.3625, -24.6056, -0.138023, 16.5036 + + + 0, 1 + 1, 1, 1, 1, 0, 0, 0, 0.0442478 + "idle" @@ -31,6 +36,8 @@ "cont" False + "times" + 0, 1.25, 1.5, 2, 4.5, 4.75, 5, 5.25 "transitions" 1, 1, 1, 1, 1, 1, 1, 1 "values" @@ -44,8 +51,6 @@ 19 16 - "times" - 0, 1.25, 1.5, 2, 4.5, 4.75, 5, 5.25 @@ -60,6 +65,8 @@ "cont" False + "times" + 0, 0.25, 0.5 "transitions" 1, 1, 1 "values" @@ -68,8 +75,6 @@ 24 23 - "times" - 0, 0.25, 0.5 @@ -84,14 +89,14 @@ "cont" False + "times" + 0 "transitions" 1 "values" 25 - "times" - 0 @@ -105,6 +110,8 @@ "cont" False + "times" + 0, 0.25, 0.5, 0.75, 1, 1.25 "transitions" 1, 1, 1, 1, 1, 1 "values" @@ -116,56 +123,10 @@ 4 0 - "times" - 0, 0.25, 0.5, 0.75, 1, 1.25 - - "crouch" - 0.01 - True - 0.25 - "value" - "sprite:frame" - 1 - - "cont" - False - "transitions" - 1 - "values" - - 22 - - "times" - 0 - - - - - "falling" - 0.01 - True - 0.25 - "value" - "sprite:frame" - 1 - - "cont" - False - "transitions" - 1 - "values" - - 21 - - "times" - 0 - - - - + 1.25 True 0.25 @@ -175,19 +136,19 @@ "cont" False + "times" + 0, 0.25, 0.5, 0.75, 1, 1.25 "transitions" 1, 1, 1, 1, 1, 1 "values" - 10 - 11 - 12 - 13 - 14 + 5 + 6 + 7 + 8 + 9 5 - "times" - 0, 0.25, 0.5, 0.75, 1, 1.25 @@ -202,18 +163,62 @@ "cont" False + "times" + 0 "transitions" 1 "values" 26 - "times" - 0 - + + "crouch" + 0.01 + True + 0.25 + "value" + "sprite:frame" + 1 + + "cont" + False + "times" + 0 + "transitions" + 1 + "values" + + 22 + + + + + + "falling" + 0.01 + True + 0.25 + "value" + "sprite:frame" + 1 + + "cont" + False + "times" + 0 + "transitions" + 1 + "values" + + 21 + + + + + 1.25 True 0.25 @@ -223,19 +228,19 @@ "cont" False + "times" + 0, 0.25, 0.5, 0.75, 1, 1.25 "transitions" 1, 1, 1, 1, 1, 1 "values" - 5 - 6 - 7 - 8 - 9 + 10 + 11 + 12 + 13 + 14 5 - "times" - 0, 0.25, 0.5, 0.75, 1, 1.25 @@ -249,14 +254,14 @@ "cont" False + "times" + 0 "transitions" 1 "values" 26 - "times" - 0 @@ -289,30 +294,28 @@ + "conn_count" + 0 + "conns" + "names" - + "player" "RigidBody2D" - "_import_path" - "visibility/visible" - "visibility/opacity" - "visibility/self_opacity" - "visibility/behind_parent" - "transform/pos" - "transform/rot" - "transform/scale" - "shape_count" + "input/pickable" "shapes/0/shape" "shapes/0/transform" "shapes/0/trigger" "shapes/1/shape" "shapes/1/transform" "shapes/1/trigger" - "layers" + "collision/layers" + "collision/mask" "mode" "mass" "friction" "bounce" + "gravity_scale" "custom_integrator" "continuous_cd" "contacts_reported" @@ -321,39 +324,28 @@ "can_sleep" "velocity/linear" "velocity/angular" + "damp_override/linear" + "damp_override/angular" "script/script" "__meta__" "sprite" "Sprite" "texture" - "centered" - "offset" - "flip_h" - "flip_v" "vframes" "hframes" - "frame" - "modulate" - "region" - "region_rect" "smoke" "Particles2D" + "visibility/self_opacity" "visibility/blend_mode" + "transform/pos" + "transform/rot" "config/amount" "config/lifetime" - "config/time_scale" - "config/preprocess" "config/emit_timeout" "config/emitting" - "config/offset" - "config/half_extents" "config/local_space" "config/explosiveness" - "config/flip_h" - "config/flip_v" "config/texture" - "config/h_frames" - "config/v_frames" "params/direction" "params/spread" "params/linear_velocity" @@ -370,32 +362,8 @@ "params/hue_variation" "params/anim_speed_scale" "params/anim_initial_pos" - "randomness/direction" - "randomness/spread" - "randomness/linear_velocity" "randomness/spin_velocity" - "randomness/orbit_velocity" - "randomness/gravity_direction" - "randomness/gravity_strength" - "randomness/radial_accel" - "randomness/tangential_accel" - "randomness/damping" - "randomness/initial_angle" - "randomness/initial_size" - "randomness/final_size" - "randomness/hue_variation" - "randomness/anim_speed_scale" - "randomness/anim_initial_pos" - "color_phases/count" - "phase_0/pos" - "phase_0/color" - "phase_1/pos" - "phase_1/color" - "phase_2/pos" - "phase_2/color" - "phase_3/pos" - "phase_3/color" - "emission_points" + "color/color_ramp" "anim" "AnimationPlayer" "playback/process_mode" @@ -405,11 +373,11 @@ "anims/jumping" "anims/idle_weapon" "anims/run" + "anims/run_weapon" + "anims/falling_weapon" "anims/crouch" "anims/falling" "anims/standing_weapon_ready" - "anims/falling_weapon" - "anims/run_weapon" "anims/jumping_weapon" "playback/active" "playback/speed" @@ -417,6 +385,7 @@ "autoplay" "camera" "Camera2D" + "anchor_mode" "rotating" "current" "smoothing" @@ -434,6 +403,7 @@ "bullet_shoot" "Position2D" "CollisionShape2D" + "transform/scale" "shape" "trigger" "sound" @@ -458,6 +428,7 @@ "ui" "CanvasLayer" "layer" + "offset" "rotation" "scale" "left" @@ -472,147 +443,149 @@ "jump" "fire" - "version" - 1 - "conn_count" - 0 "node_count" 14 + "nodes" + -1, -1, 1, 0, -1, 26, 2, 0, 3, 1, 4, 2, 5, 0, 6, 3, 7, 4, 8, 0, 9, 5, 10, 5, 11, 6, 12, 7, 13, 8, 14, 8, 15, 9, 16, 10, 17, 11, 18, 12, 19, 0, 20, 0, 21, 10, 22, 13, 23, 8, 24, 14, 25, 14, 26, 15, 27, 16, 0, 0, 0, 29, 28, -1, 3, 30, 17, 31, 6, 32, 18, 0, 1, 0, 34, 33, -1, 29, 35, 19, 36, 5, 37, 20, 38, 21, 39, 22, 40, 23, 41, 23, 42, 0, 43, 0, 44, 24, 45, 25, 46, 8, 47, 26, 48, 27, 49, 9, 50, 8, 51, 8, 52, 28, 53, 8, 54, 8, 55, 8, 56, 8, 57, 29, 58, 29, 59, 8, 60, 9, 61, 8, 62, 29, 63, 30, 0, 0, 0, 65, 64, -1, 17, 66, 5, 67, 8, 68, 31, 69, 32, 70, 33, 71, 34, 72, 35, 73, 36, 74, 37, 75, 38, 76, 39, 77, 40, 78, 41, 79, 10, 80, 29, 81, 42, 82, 43, 0, 0, 0, 84, 83, -1, 15, 85, 5, 86, 0, 87, 10, 88, 8, 89, 44, 90, 11, 91, 11, 92, 45, 93, 45, 94, 10, 95, 10, 96, 46, 97, 46, 98, 46, 99, 46, 0, 0, 0, 101, 100, -1, 1, 37, 47, 0, 0, 0, 102, 102, -1, 4, 37, 48, 103, 49, 104, 1, 105, 0, 0, 0, 0, 107, 106, -1, 14, 108, 12, 109, 50, 110, 8, 111, 9, 112, 8, 113, 8, 114, 8, 115, 51, 116, 51, 117, 51, 118, 51, 119, 6, 120, 8, 121, 8, 0, 0, 0, 122, 122, -1, 3, 123, 11, 124, 52, 105, 0, 0, 0, 0, 126, 125, -1, 4, 127, 11, 128, 13, 129, 8, 130, 44, 0, 9, 0, 132, 131, -1, 8, 37, 53, 103, 54, 133, 55, 134, 56, 135, 56, 136, 10, 137, 57, 138, 5, 0, 9, 0, 132, 139, -1, 8, 37, 58, 103, 54, 133, 59, 134, 56, 135, 56, 136, 10, 137, 60, 138, 5, 0, 9, 0, 132, 140, -1, 8, 37, 61, 103, 54, 133, 62, 134, 56, 135, 56, 136, 0, 137, 63, 138, 5, 0, 9, 0, 132, 141, -1, 8, 37, 64, 103, 54, 133, 65, 134, 56, 135, 56, 136, 0, 137, 66, 138, 5, 0 "variants" - - "" - True - 1 + False - 0, 0 - 0 - 1, 1 - 2 1, -0, 0, 1.76469, 0.291992, -12.1587 1, -0, 0, 1, 0, 0 1 + 2 3 + 0 + 1 + True 0 3 + 0, 0 + -1 + "__editor_plugin_screen__" + "2D" "__editor_plugin_states__" - "Script" - - "current" - 0 - "sources" - - "res://player.gd" - - "2D" - "pixel_snap" - False - "zoom" - 2.272073 - "use_snap" - False "ofs" - -181.946, -86.2812 - "snap" - 10 + -110.795, -101.2 + "snap_grid" + False + "snap_offset" + 0, 0 + "snap_pixel" + False + "snap_relative" + False + "snap_rotation" + False + "snap_rotation_offset" + 0 + "snap_rotation_step" + 0.261799 + "snap_show_grid" + False + "snap_step" + 10, 10 + "zoom" + 2.050546 "3D" + "ambient_light_color" + 0.15, 0.15, 0.15, 1 + "default_light" + True + "default_srgb" + False + "deflight_rot_x" + 0.942478 "deflight_rot_y" 0.628319 - "zfar" - 500 "fov" 45 + "show_grid" + True + "show_origin" + True + "viewport_mode" + 1 "viewports" "distance" 4 - "x_rot" - 0 - "y_rot" - 0 "listener" True + "pos" + 0, 0, 0 "use_environment" False "use_orthogonal" False - "pos" - 0, 0, 0 - - - "distance" - 4 "x_rot" 0 "y_rot" 0 - "listener" - False - "use_environment" - False - "use_orthogonal" - False - "pos" - 0, 0, 0 "distance" 4 - "x_rot" - 0 - "y_rot" - 0 "listener" False + "pos" + 0, 0, 0 "use_environment" False "use_orthogonal" False - "pos" - 0, 0, 0 + "x_rot" + 0 + "y_rot" + 0 "distance" 4 - "x_rot" - 0 - "y_rot" - 0 "listener" False + "pos" + 0, 0, 0 "use_environment" False "use_orthogonal" False + "x_rot" + 0 + "y_rot" + 0 + + + "distance" + 4 + "listener" + False "pos" 0, 0, 0 + "use_environment" + False + "use_orthogonal" + False + "x_rot" + 0 + "y_rot" + 0 - "viewport_mode" - 1 - "default_light" - True - "ambient_light_color" - 0.15, 0.15, 0.15, 1 - "show_grid" - True - "show_origin" - True + "zfar" + 500 "znear" 0.1 - "default_srgb" - False - "deflight_rot_x" - 0.942478 "__editor_run_settings__" @@ -622,13 +595,9 @@ "run_mode" 0 - "__editor_plugin_screen__" - "Script" 16 - 1, 1, 1, 1 - 0, 0, 0, 0 0.363636 20.7312, 3.21187 83.450417 @@ -640,24 +609,22 @@ 20 9.8 2 - 0, 0, 0, 0.0442478 - 1, 0, 0, 1 - 0, 0, 0, 1 - + ".." + + - - "" + 1, 1 10000000 0.2 31.2428, 4.08784 @@ -680,10 +647,8 @@ "shoot" - "nodes" - -1, -1, 1, 0, -1, 30, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 8, 12, 9, 13, 3, 14, 10, 15, 11, 16, 3, 17, 12, 18, 7, 19, 13, 20, 5, 21, 5, 22, 1, 23, 14, 24, 15, 25, 3, 26, 3, 27, 1, 28, 4, 29, 5, 30, 16, 31, 17, 0, 0, 0, 33, 32, -1, 19, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 34, 18, 35, 1, 36, 4, 37, 3, 38, 3, 39, 7, 40, 19, 41, 14, 42, 20, 43, 3, 44, 21, 0, 1, 0, 46, 45, -1, 66, 2, 0, 3, 1, 4, 2, 5, 22, 6, 3, 47, 12, 7, 23, 8, 24, 9, 6, 48, 25, 49, 26, 50, 2, 51, 5, 52, 26, 53, 3, 54, 4, 55, 4, 56, 3, 57, 27, 58, 3, 59, 3, 60, 28, 61, 12, 62, 12, 63, 5, 64, 29, 65, 30, 66, 2, 67, 5, 68, 5, 69, 31, 70, 5, 71, 5, 72, 5, 73, 5, 74, 32, 75, 32, 76, 5, 77, 2, 78, 5, 79, 5, 80, 5, 81, 5, 82, 32, 83, 5, 84, 5, 85, 5, 86, 5, 87, 5, 88, 5, 89, 5, 90, 5, 91, 5, 92, 5, 93, 5, 94, 5, 95, 7, 96, 5, 97, 20, 98, 2, 99, 33, 100, 2, 101, 34, 102, 2, 103, 35, 104, 36, 0, 0, 0, 106, 105, -1, 18, 2, 0, 107, 12, 108, 5, 109, 37, 110, 38, 111, 39, 112, 40, 113, 41, 114, 42, 115, 43, 116, 44, 117, 45, 118, 46, 119, 47, 120, 1, 121, 32, 122, 48, 123, 49, 0, 0, 0, 125, 124, -1, 23, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 35, 1, 126, 3, 127, 1, 128, 5, 129, 6, 130, 14, 131, 14, 132, 50, 133, 50, 134, 1, 135, 1, 136, 51, 137, 51, 138, 51, 139, 51, 0, 0, 0, 141, 140, -1, 8, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 52, 8, 5, 9, 6, 0, 0, 0, 142, 142, -1, 10, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 53, 8, 5, 9, 54, 143, 8, 144, 3, 0, 0, 0, 146, 145, -1, 15, 2, 0, 147, 15, 148, 55, 149, 5, 150, 2, 151, 5, 152, 5, 153, 5, 154, 56, 155, 56, 156, 56, 157, 56, 158, 7, 159, 5, 160, 5, 0, 0, 0, 161, 161, -1, 10, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 162, 14, 163, 57, 0, 0, 0, 165, 164, -1, 5, 2, 0, 166, 14, 36, 4, 167, 5, 168, 6, 0, 9, 0, 170, 169, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 58, 8, 5, 9, 59, 171, 60, 172, 61, 173, 61, 174, 1, 175, 62, 176, 12, 0, 9, 0, 170, 177, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 63, 8, 5, 9, 59, 171, 64, 172, 61, 173, 61, 174, 1, 175, 65, 176, 12, 0, 9, 0, 170, 178, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 66, 8, 5, 9, 59, 171, 67, 172, 61, 173, 61, 174, 3, 175, 68, 176, 12, 0, 9, 0, 170, 179, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 69, 8, 5, 9, 59, 171, 70, 172, 61, 173, 61, 174, 3, 175, 71, 176, 12, 0 - "conns" - + "version" + 1 diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 2fca1e67e86..17f93f816ff 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -579,6 +579,10 @@ void TileMap::_make_quadrant_dirty(Map::Element *Q) { call_deferred("_update_dirty_quadrants"); } +void TileMap::set_cellv(const Vector2& p_pos,int p_tile,bool p_flip_x,bool p_flip_y,bool p_transpose) { + + set_cell(p_pos.x,p_pos.y,p_tile,p_flip_x,p_flip_y,p_transpose); +} void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bool p_transpose) { @@ -1106,6 +1110,7 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_collision_bounce"),&TileMap::get_collision_bounce); ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("set_cellv","pos","tile","flip_x","flip_y","transpose"),&TileMap::set_cellv,DEFVAL(false),DEFVAL(false),DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell); ObjectTypeDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped); ObjectTypeDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 84ca65da4f6..60534cce151 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -207,6 +207,8 @@ public: bool is_cell_y_flipped(int p_x,int p_y) const; bool is_cell_transposed(int p_x,int p_y) const; + void set_cellv(const Vector2& p_pos,int p_tile,bool p_flip_x=false,bool p_flip_y=false,bool p_transpose=false); + Rect2 get_item_rect() const; void set_collision_layer(uint32_t p_layer); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 7e31bf8dd07..5e0faae0a27 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -196,6 +196,14 @@ void Node::_propagate_enter_tree() { } data.blocked--; + +#ifdef DEBUG_ENABLED + + if (ScriptDebugger::get_singleton() && data.filename!=String()) { + //used for live edit + data.tree->live_scene_edit_cache[data.filename].insert(this); + } +#endif // enter groups } @@ -205,6 +213,19 @@ void Node::_propagate_exit_tree() { //block while removing children +#ifdef DEBUG_ENABLED + + if (ScriptDebugger::get_singleton() && data.filename!=String()) { + //used for live edit + Map >::Element *E=data.tree->live_scene_edit_cache.find(data.filename); + if (E) { + E->get().erase(this); + if (E->get().size()==0) { + data.tree->live_scene_edit_cache.erase(E); + } + } + } +#endif data.blocked++; for (int i=data.children.size()-1;i>=0;i--) { @@ -552,6 +573,52 @@ void Node::set_human_readable_collision_renaming(bool p_enabled) { } + +String Node::validate_child_name(const String& p_name) const { + + //this approach to autoset node names is human readable but very slow + //it's turned on while running in the editor + + String basename = p_name; + + if (basename==String()) { + + return String(); + } + + int val=1; + + for(;;) { + + String attempted = val > 1 ? (basename + " " +itos(val) ) : basename; + + bool found=false; + + for (int i=0;iget_name() == attempted) { + found=true; + break; + } + + } + + if (found) { + + val++; + continue; + } + + return attempted; + break; + } + + return basename; + +} + void Node::_validate_child_name(Node *p_child) { /* Make sure the name is unique */ @@ -1323,18 +1390,31 @@ int Node::get_position_in_parent() const { -Node *Node::duplicate() const { +Node *Node::duplicate(bool p_use_instancing) const { Node *node=NULL; - Object *obj = ObjectTypeDB::instance(get_type()); - ERR_FAIL_COND_V(!obj,NULL); - node = obj->cast_to(); - if (!node) - memdelete(obj); - ERR_FAIL_COND_V(!node,NULL); + bool instanced=false; + if (p_use_instancing && get_filename()!=String()) { + + Ref res = ResourceLoader::load(get_filename()); + ERR_FAIL_COND_V(res.is_null(),NULL); + node=res->instance(); + ERR_FAIL_COND_V(!node,NULL); + + instanced=true; + + } else { + + Object *obj = ObjectTypeDB::instance(get_type()); + ERR_FAIL_COND_V(!obj,NULL); + node = obj->cast_to(); + if (!node) + memdelete(obj); + ERR_FAIL_COND_V(!node,NULL); + } if (get_filename()!="") { //an instance @@ -1360,7 +1440,10 @@ Node *Node::duplicate() const { if (get_child(i)->data.parent_owned) continue; - Node *dup = get_child(i)->duplicate(); + if (instanced && get_child(i)->data.owner==this) + continue; //part of instance + + Node *dup = get_child(i)->duplicate(p_use_instancing); if (!dup) { memdelete(node); @@ -1882,7 +1965,7 @@ void Node::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_tree:SceneTree"),&Node::get_tree); - ObjectTypeDB::bind_method(_MD("duplicate:Node"),&Node::duplicate); + ObjectTypeDB::bind_method(_MD("duplicate:Node","use_instancing"),&Node::duplicate,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("replace_by","node:Node","keep_data"),&Node::replace_by,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_viewport"),&Node::get_viewport); diff --git a/scene/main/node.h b/scene/main/node.h index be91c6e1bbd..a6d5bfbd9fd 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -255,8 +255,9 @@ public: int get_position_in_parent() const; - Node *duplicate() const; + Node *duplicate(bool p_use_instancing=false) const; Node *duplicate_and_reown(const Map& p_reown_map) const; + //Node *clone_tree() const; // used by editors, to save what has changed only @@ -275,6 +276,8 @@ public: static void print_stray_nodes(); + String validate_child_name(const String& p_name) const; + void queue_delete(); //shitty hacks for speed diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index 1664a9bea12..9a05d6d4d0a 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -1044,7 +1044,300 @@ void SceneTree::add_current_scene(Node * p_current) { current_scene=p_current; root->add_child(p_current); } +#ifdef DEBUG_ENABLED +void SceneTree::_live_edit_node_path_func(const NodePath &p_path,int p_id) { + + live_edit_node_path_cache[p_id]=p_path; +} + +void SceneTree::_live_edit_res_path_func(const String &p_path,int p_id) { + + live_edit_resource_cache[p_id]=p_path; +} + +void SceneTree::_live_edit_node_set_func(int p_id,const StringName& p_prop,const Variant& p_value) { + + if (!live_edit_node_path_cache.has(p_id)) + return; + + NodePath np = live_edit_node_path_cache[p_id]; + Node *base = NULL; + if (root->has_node(live_edit_root)) + base = root->get_node(live_edit_root); + + Map >::Element *E=live_scene_edit_cache.find(live_edit_scene); + if (!E) + return; //scene not editable + + for(Set::Element *F=E->get().front();F;F=F->next()) { + + Node *n=F->get(); + + if (base && !base->is_a_parent_of(n)) + continue; + + if (!n->has_node(np)) + continue; + Node *n2 = n->get_node(np); + + n2->set(p_prop,p_value); + } + +} + +void SceneTree::_live_edit_node_set_res_func(int p_id,const StringName& p_prop,const String& p_value) { + + RES r = ResourceLoader::load(p_value); + if (!r.is_valid()) + return; + _live_edit_node_set_func(p_id,p_prop,r); + +} +void SceneTree::_live_edit_node_call_func(int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) { + + if (!live_edit_node_path_cache.has(p_id)) + return; + + NodePath np = live_edit_node_path_cache[p_id]; + Node *base = NULL; + if (root->has_node(live_edit_root)) + base = root->get_node(live_edit_root); + + Map >::Element *E=live_scene_edit_cache.find(live_edit_scene); + if (!E) + return; //scene not editable + + for(Set::Element *F=E->get().front();F;F=F->next()) { + + Node *n=F->get(); + + if (base && !base->is_a_parent_of(n)) + continue; + + if (!n->has_node(np)) + continue; + Node *n2 = n->get_node(np); + + n2->call(p_method,VARIANT_ARG_PASS); + } +} +void SceneTree::_live_edit_res_set_func(int p_id,const StringName& p_prop,const Variant& p_value) { + + if (!live_edit_resource_cache.has(p_id)) + return; + + String resp = live_edit_resource_cache[p_id]; + + if (!ResourceCache::has(resp)) + return; + + RES r = ResourceCache::get(resp); + if (!r.is_valid()) + return; + + r->set(p_prop,p_value); +} +void SceneTree::_live_edit_res_set_res_func(int p_id,const StringName& p_prop,const String& p_value) { + + RES r = ResourceLoader::load(p_value); + if (!r.is_valid()) + return; + _live_edit_res_set_func(p_id,p_prop,r); + +} +void SceneTree::_live_edit_res_call_func(int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) { + + if (!live_edit_resource_cache.has(p_id)) + return; + + String resp = live_edit_resource_cache[p_id]; + + if (!ResourceCache::has(resp)) + return; + + RES r = ResourceCache::get(resp); + if (!r.is_valid()) + return; + + r->call(p_method,VARIANT_ARG_PASS); +} + +void SceneTree::_live_edit_root_func(const NodePath& p_scene_path,const String& p_scene_from) { + + live_edit_root=p_scene_path; + live_edit_scene=p_scene_from; +} + +void SceneTree::_live_edit_create_node_func(const NodePath& p_parent,const String& p_type,const String& p_name) { + + + Node *base = NULL; + if (root->has_node(live_edit_root)) + base = root->get_node(live_edit_root); + + Map >::Element *E=live_scene_edit_cache.find(live_edit_scene); + if (!E) + return; //scene not editable + + for(Set::Element *F=E->get().front();F;F=F->next()) { + + Node *n=F->get(); + + if (base && !base->is_a_parent_of(n)) + continue; + + if (!n->has_node(p_parent)) + continue; + Node *n2 = n->get_node(p_parent); + + Object *o = ObjectTypeDB::instance(p_type); + if (!o) + continue; + Node *no=o->cast_to(); + no->set_name(p_name); + + n2->add_child(no); + } +} +void SceneTree::_live_edit_instance_node_func(const NodePath& p_parent,const String& p_path,const String& p_name){ + + Ref ps = ResourceLoader::load(p_path); + print_line("instance node?"); + if (!ps.is_valid()) + return; + + Node *base = NULL; + if (root->has_node(live_edit_root)) + base = root->get_node(live_edit_root); + + Map >::Element *E=live_scene_edit_cache.find(live_edit_scene); + if (!E) + return; //scene not editable + + for(Set::Element *F=E->get().front();F;F=F->next()) { + + Node *n=F->get(); + + if (base && !base->is_a_parent_of(n)) + continue; + + if (!n->has_node(p_parent)) + continue; + Node *n2 = n->get_node(p_parent); + + + + Node *no=ps->instance(); + no->set_name(p_name); + + n2->add_child(no); + } +} +void SceneTree::_live_edit_remove_node_func(const NodePath& p_at){ + + Node *base = NULL; + if (root->has_node(live_edit_root)) + base = root->get_node(live_edit_root); + + Map >::Element *E=live_scene_edit_cache.find(live_edit_scene); + if (!E) + return; //scene not editable + + for(Set::Element *F=E->get().front();F;) { + + Set::Element *N=F->next(); + + Node *n=F->get(); + + if (base && !base->is_a_parent_of(n)) + continue; + + if (!n->has_node(p_at)) + continue; + Node *n2 = n->get_node(p_at); + + memdelete(n2); + + F=N; + + } +} +void SceneTree::_live_edit_remove_and_keep_node_func(const NodePath& p_at,ObjectID p_keep_id){ + + +} +void SceneTree::_live_edit_restore_node_func(ObjectID p_id,const NodePath& p_at,int p_at_pos){ + + +} +void SceneTree::_live_edit_duplicate_node_func(const NodePath& p_at,const String& p_new_name){ + + Node *base = NULL; + if (root->has_node(live_edit_root)) + base = root->get_node(live_edit_root); + + Map >::Element *E=live_scene_edit_cache.find(live_edit_scene); + if (!E) + return; //scene not editable + + for(Set::Element *F=E->get().front();F;F=F->next()) { + + Node *n=F->get(); + + if (base && !base->is_a_parent_of(n)) + continue; + + if (!n->has_node(p_at)) + continue; + Node *n2 = n->get_node(p_at); + + Node *dup = n2->duplicate(true); + + if (!dup) + continue; + + dup->set_name(p_new_name); + + n2->get_parent()->add_child(dup); + + } +} +void SceneTree::_live_edit_reparent_node_func(const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name){ + + Node *base = NULL; + if (root->has_node(live_edit_root)) + base = root->get_node(live_edit_root); + + Map >::Element *E=live_scene_edit_cache.find(live_edit_scene); + if (!E) + return; //scene not editable + + for(Set::Element *F=E->get().front();F;F=F->next()) { + + Node *n=F->get(); + + if (base && !base->is_a_parent_of(n)) + continue; + + if (!n->has_node(p_at)) + continue; + Node *nfrom = n->get_node(p_at); + + if (!n->has_node(p_new_place)) + continue; + Node *nto = n->get_node(p_new_place); + + nfrom->get_parent()->remove_child(nfrom); + nfrom->set_name(p_new_name); + + nto->add_child(nfrom); + + } +} + + +#endif void SceneTree::_bind_methods() { @@ -1169,6 +1462,35 @@ SceneTree::SceneTree() { edited_scene_root=NULL; #endif +#ifdef DEBUG_ENABLED + + + live_edit_funcs.udata=this; + live_edit_funcs.node_path_func=_live_edit_node_path_funcs; + live_edit_funcs.res_path_func=_live_edit_res_path_funcs; + live_edit_funcs.node_set_func=_live_edit_node_set_funcs; + live_edit_funcs.node_set_res_func=_live_edit_node_set_res_funcs; + live_edit_funcs.node_call_func=_live_edit_node_call_funcs; + live_edit_funcs.res_set_func=_live_edit_res_set_funcs; + live_edit_funcs.res_set_res_func=_live_edit_res_set_res_funcs; + live_edit_funcs.res_call_func=_live_edit_res_call_funcs; + live_edit_funcs.root_func=_live_edit_root_funcs; + + live_edit_funcs.tree_create_node_func=_live_edit_create_node_funcs; + live_edit_funcs.tree_instance_node_func=_live_edit_instance_node_funcs; + live_edit_funcs.tree_remove_node_func=_live_edit_remove_node_funcs; + live_edit_funcs.tree_remove_and_keep_node_func=_live_edit_remove_and_keep_node_funcs; + live_edit_funcs.tree_restore_node_func=_live_edit_restore_node_funcs; + live_edit_funcs.tree_duplicate_node_func=_live_edit_duplicate_node_funcs; + live_edit_funcs.tree_reparent_node_func=_live_edit_reparent_node_funcs; + + if (ScriptDebugger::get_singleton()) { + ScriptDebugger::get_singleton()->set_live_edit_funcs(&live_edit_funcs); + } + + live_edit_root=NodePath("/root"); + +#endif } diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h index e49c150fbf6..94d0abe50f2 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_main_loop.h @@ -164,6 +164,57 @@ friend class Viewport; SelfList::List xform_change_list; +#ifdef DEBUG_ENABLED + + Map live_edit_node_path_cache; + Map live_edit_resource_cache; + + NodePath live_edit_root; + String live_edit_scene; + + Map > live_scene_edit_cache; + + ScriptDebugger::LiveEditFuncs live_edit_funcs; + + void _live_edit_node_path_func(const NodePath &p_path,int p_id) ; + void _live_edit_res_path_func(const String &p_path,int p_id) ; + + void _live_edit_node_set_func(int p_id,const StringName& p_prop,const Variant& p_value) ; + void _live_edit_node_set_res_func(int p_id,const StringName& p_prop,const String& p_value) ; + void _live_edit_node_call_func(int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) ; + void _live_edit_res_set_func(int p_id,const StringName& p_prop,const Variant& p_value) ; + void _live_edit_res_set_res_func(int p_id,const StringName& p_prop,const String& p_value) ; + void _live_edit_res_call_func(int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) ; + void _live_edit_root_func(const NodePath& p_scene_path,const String& p_scene_from) ; + + void _live_edit_create_node_func(const NodePath& p_parent,const String& p_type,const String& p_name); + void _live_edit_instance_node_func(const NodePath& p_parent,const String& p_path,const String& p_name); + void _live_edit_remove_node_func(const NodePath& p_at); + void _live_edit_remove_and_keep_node_func(const NodePath& p_at,ObjectID p_keep_id); + void _live_edit_restore_node_func(ObjectID p_id,const NodePath& p_at,int p_at_pos); + void _live_edit_duplicate_node_func(const NodePath& p_at,const String& p_new_name); + void _live_edit_reparent_node_func(const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name); + + static void _live_edit_node_path_funcs(void *self,const NodePath &p_path,int p_id) { reinterpret_cast(self)->_live_edit_node_path_func(p_path,p_id); } + static void _live_edit_res_path_funcs(void *self,const String &p_path,int p_id) { reinterpret_cast(self)->_live_edit_res_path_func(p_path,p_id); } + + static void _live_edit_node_set_funcs(void *self,int p_id,const StringName& p_prop,const Variant& p_value) { reinterpret_cast(self)->_live_edit_node_set_func(p_id,p_prop,p_value); } + static void _live_edit_node_set_res_funcs(void *self,int p_id,const StringName& p_prop,const String& p_value) { reinterpret_cast(self)->_live_edit_node_set_res_func(p_id,p_prop,p_value); } + static void _live_edit_node_call_funcs(void *self,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) { reinterpret_cast(self)->_live_edit_node_call_func(p_id,p_method,VARIANT_ARG_PASS); } + static void _live_edit_res_set_funcs(void *self,int p_id,const StringName& p_prop,const Variant& p_value) { reinterpret_cast(self)->_live_edit_res_set_func(p_id,p_prop,p_value); } + static void _live_edit_res_set_res_funcs(void *self,int p_id,const StringName& p_prop,const String& p_value) { reinterpret_cast(self)->_live_edit_res_set_res_func(p_id,p_prop,p_value); } + static void _live_edit_res_call_funcs(void *self,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) { reinterpret_cast(self)->_live_edit_res_call_func(p_id,p_method,VARIANT_ARG_PASS); } + static void _live_edit_root_funcs(void *self, const NodePath& p_scene_path,const String& p_scene_from) { reinterpret_cast(self)->_live_edit_root_func(p_scene_path,p_scene_from); } + + static void _live_edit_create_node_funcs(void* self,const NodePath& p_parent,const String& p_type,const String& p_name) { reinterpret_cast(self)->_live_edit_create_node_func(p_parent,p_type,p_name); } + static void _live_edit_instance_node_funcs(void* self,const NodePath& p_parent,const String& p_path,const String& p_name) { reinterpret_cast(self)->_live_edit_instance_node_func(p_parent,p_path,p_name); } + static void _live_edit_remove_node_funcs(void* self,const NodePath& p_at) { reinterpret_cast(self)->_live_edit_remove_node_func(p_at); } + static void _live_edit_remove_and_keep_node_funcs(void* self,const NodePath& p_at,ObjectID p_keep_id) { reinterpret_cast(self)->_live_edit_remove_and_keep_node_func(p_at,p_keep_id); } + static void _live_edit_restore_node_funcs(void* self,ObjectID p_id,const NodePath& p_at,int p_at_pos) { reinterpret_cast(self)->_live_edit_restore_node_func(p_id,p_at,p_at_pos); } + static void _live_edit_duplicate_node_funcs(void* self,const NodePath& p_at,const String& p_new_name) { reinterpret_cast(self)->_live_edit_duplicate_node_func(p_at,p_new_name); } + static void _live_edit_reparent_node_funcs(void* self,const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name) { reinterpret_cast(self)->_live_edit_reparent_node_func(p_at,p_new_place,p_new_name); } + +#endif protected: void _notification(int p_notification); diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp index f729a6c8696..7f42f19a9b4 100644 --- a/tools/editor/editor_data.cpp +++ b/tools/editor/editor_data.cpp @@ -432,6 +432,7 @@ int EditorData::add_edited_scene(int p_at_pos) { es.root=NULL; es.history_current=-1; es.version=0; + es.live_edit_root=NodePath(String("/root")); if (p_at_pos==edited_scene.size()) edited_scene.push_back(es); @@ -552,6 +553,23 @@ String EditorData::get_scene_path(int p_idx) const { } +void EditorData::set_edited_scene_live_edit_root(const NodePath& p_root) { + ERR_FAIL_INDEX(current_edited_scene,edited_scene.size()); + + edited_scene[current_edited_scene].live_edit_root=p_root; + +} +NodePath EditorData::get_edited_scene_live_edit_root() { + + ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),String()); + + return edited_scene[current_edited_scene].live_edit_root; + + + +} + + void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history, const Dictionary& p_custom) { ERR_FAIL_INDEX(current_edited_scene,edited_scene.size()); diff --git a/tools/editor/editor_data.h b/tools/editor/editor_data.h index 14a50da0821..cbec2295f69 100644 --- a/tools/editor/editor_data.h +++ b/tools/editor/editor_data.h @@ -129,6 +129,7 @@ private: int history_current; Dictionary custom_state; uint64_t version; + NodePath live_edit_root; }; @@ -183,6 +184,8 @@ public: uint64_t get_edited_scene_version() const; uint64_t get_scene_version(int p_idx) const; void clear_edited_scenes(); + void set_edited_scene_live_edit_root(const NodePath& p_root); + NodePath get_edited_scene_live_edit_root(); void set_plugin_window_layout(Ref p_layout); diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 7789008c621..84107bdaf7d 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -93,6 +93,7 @@ #include "plugins/light_occluder_2d_editor_plugin.h" #include "plugins/color_ramp_editor_plugin.h" #include "plugins/collision_shape_2d_editor_plugin.h" + // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" @@ -103,6 +104,7 @@ #include "plugins/editor_preview_plugins.h" +#include "script_editor_debugger.h" EditorNode *EditorNode::singleton=NULL; @@ -2410,6 +2412,11 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { fileserver_menu->get_popup()->set_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_FILE_SERVER),!ischecked); } break; + case RUN_LIVE_DEBUG: { + + ScriptEditor::get_singleton()->get_debugger()->set_live_debugging(live_debug_button->is_pressed()); + } break; + case RUN_DEPLOY_DUMB_CLIENTS: { bool ischecked = fileserver_menu->get_popup()->is_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS)); @@ -3018,6 +3025,7 @@ void EditorNode::set_current_scene(int p_idx) { call_deferred("_set_main_scene_state",state); //do after everything else is done setting up //print_line("set current 6 "); changing_scene=false; + ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root(); } @@ -3155,6 +3163,8 @@ Error EditorNode::load_scene(const String& p_scene) { prev_scene->set_disabled(previous_scenes.size()==0); opening_prev=false; + ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root(); + //top_pallete->set_current_tab(0); //always go to scene push_item(new_scene); @@ -4614,6 +4624,14 @@ EditorNode::EditorNode() { play_custom_scene_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY_CUSTOM_SCENE)); play_custom_scene_button->set_tooltip("Play custom scene ("+keycode_get_string(KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_F5)+")."); + live_debug_button = memnew( ToolButton ); + play_hb->add_child(live_debug_button); + live_debug_button->set_toggle_mode(true); + live_debug_button->set_focus_mode(Control::FOCUS_NONE); + live_debug_button->set_icon(gui_base->get_icon("LiveDebug","EditorIcons")); + live_debug_button->connect("pressed", this,"_menu_option",make_binds(RUN_LIVE_DEBUG)); + live_debug_button->set_tooltip("Toggle Live Debugging On/Off"); + fileserver_menu = memnew( MenuButton ); play_hb->add_child(fileserver_menu); fileserver_menu->set_flat(true); diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 495f069b55a..93b95034ff0 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -152,6 +152,7 @@ class EditorNode : public Node { RUN_PROJECT_MANAGER, RUN_FILE_SERVER, RUN_DEPLOY_DUMB_CLIENTS, + RUN_LIVE_DEBUG, SETTINGS_UPDATE_ALWAYS, SETTINGS_UPDATE_CHANGES, SETTINGS_IMPORT, @@ -239,6 +240,7 @@ class EditorNode : public Node { ToolButton *animation_menu; ToolButton *play_scene_button; ToolButton *play_custom_scene_button; + ToolButton *live_debug_button; TextureProgress *audio_vu; MenuButton *fileserver_menu; diff --git a/tools/editor/icons/icon_live_debug.png b/tools/editor/icons/icon_live_debug.png new file mode 100644 index 00000000000..ad55646b9ab Binary files /dev/null and b/tools/editor/icons/icon_live_debug.png differ diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h index 0dd152cb255..59173068fbc 100644 --- a/tools/editor/plugins/script_editor_plugin.h +++ b/tools/editor/plugins/script_editor_plugin.h @@ -250,6 +250,8 @@ public: void set_window_layout(Ref p_layout); void get_window_layout(Ref p_layout); + ScriptEditorDebugger *get_debugger() { return debugger; } + ScriptEditor(EditorNode *p_editor); ~ScriptEditor(); }; diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index 017a26441d1..66c7a39096e 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -107,8 +107,8 @@ void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bo if (p_with_undo) { - undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose); - undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose); + undo_redo->add_do_method(node,"set_cellv",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose); + undo_redo->add_undo_method(node,"set_cellv",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose); } else { node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v,p_transpose); @@ -314,8 +314,8 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for(Map::Element *E=paint_undo.front();E;E=E->next()) { Point2i p=E->key(); - undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p),node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); - undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); + undo_redo->add_do_method(node,"set_cellv",Point2(p),node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); + undo_redo->add_undo_method(node,"set_cellv",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); } undo_redo->commit_action(); @@ -344,7 +344,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { //return true; _set_cell(local,TileMap::INVALID_CELL); return true; - } else { + } else if (!mb.pressed) { if (tool==TOOL_ERASING) { @@ -353,9 +353,10 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for(Map::Element *E=paint_undo.front();E;E=E->next()) { Point2i p=E->key(); - //undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); - _set_cell(p,TileMap::INVALID_CELL,false,false,false,true); - undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); + //undo_redo->add_do_method(node,"set_cell",p,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); + //_set_cell(p,TileMap::INVALID_CELL,false,false,false,true); + undo_redo->add_do_method(node,"set_cellv",Point2(p),TileMap::INVALID_CELL,false,false,false); + undo_redo->add_undo_method(node,"set_cellv",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); } undo_redo->commit_action(); diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index 49cbebdb43a..111d307b8e9 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -33,7 +33,8 @@ #include "scene/resources/packed_scene.h" #include "editor_settings.h" #include "tools/editor/plugins/canvas_item_editor_plugin.h" - +#include "script_editor_debugger.h" +#include "tools/editor/plugins/script_editor_plugin.h" void SceneTreeDock::_unhandled_key_input(InputEvent p_event) { @@ -105,6 +106,13 @@ Node* SceneTreeDock::instance(const String& p_file) { editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",instanced_scene); editor_data->get_undo_redo().add_do_reference(instanced_scene); editor_data->get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene); + + + String new_name = parent->validate_child_name(instanced_scene->get_name()); + ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); + editor_data->get_undo_redo().add_do_method(sed,"live_debug_instance_node",edited_scene->get_path_to(parent),p_file,new_name); + editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name)); + editor_data->get_undo_redo().commit_action(); @@ -389,9 +397,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().add_do_method(d,"set_owner",node->get_owner()); } editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",dup); - editor_data->get_undo_redo().add_undo_method(parent,"remove_child",dup); + editor_data->get_undo_redo().add_undo_method(parent,"remove_child",dup); editor_data->get_undo_redo().add_do_reference(dup); + ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); + + editor_data->get_undo_redo().add_do_method(sed,"live_debug_duplicate_node",edited_scene->get_path_to(node),edited_scene->get_path_to(parent),attempt); + editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+attempt)); + //parent->add_child(dup); //reselect.push_back(dup); } @@ -903,6 +916,13 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_node_only) { editor_data->get_undo_redo().add_do_method(node->get_parent(),"remove_child",node); editor_data->get_undo_redo().add_do_method(new_parent,"add_child",node); + + ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); + String new_name = new_parent->validate_child_name(node->get_name()); + editor_data->get_undo_redo().add_do_method(sed,"live_debug_reparent_node",edited_scene->get_path_to(node),edited_scene->get_path_to(new_parent),new_name); + editor_data->get_undo_redo().add_undo_method(sed,"live_debug_reparent_node",NodePath(String(edited_scene->get_path_to(new_parent))+"/"+new_name),node->get_parent(),node->get_name()); + + editor_data->get_undo_redo().add_do_method(this,"_set_owners",edited_scene,owners); if (editor->get_animation_editor()->get_root()==node) @@ -1025,6 +1045,11 @@ void SceneTreeDock::_delete_confirm() { editor_data->get_undo_redo().add_undo_method(this,"_set_owners",edited_scene,owners); //editor_data->get_undo_redo().add_undo_method(n,"set_owner",n->get_owner()); editor_data->get_undo_redo().add_undo_reference(n); + + ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); + editor_data->get_undo_redo().add_do_method(sed,"live_debug_remove_and_keep_node",edited_scene->get_path_to(n),n->get_instance_ID()); + editor_data->get_undo_redo().add_undo_method(sed,"live_debug_restore_node",n->get_instance_ID(),edited_scene->get_path_to(n->get_parent()),n->get_index()); + } @@ -1082,12 +1107,20 @@ void SceneTreeDock::_create() { editor_data->get_undo_redo().create_action("Create Node"); if (edited_scene) { + editor_data->get_undo_redo().add_do_method(parent,"add_child",child); editor_data->get_undo_redo().add_do_method(child,"set_owner",edited_scene); editor_data->get_undo_redo().add_do_method(editor_selection,"clear"); editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",child); editor_data->get_undo_redo().add_do_reference(child); editor_data->get_undo_redo().add_undo_method(parent,"remove_child",child); + + + String new_name = parent->validate_child_name(child->get_type()); + ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); + editor_data->get_undo_redo().add_do_method(sed,"live_debug_create_node",edited_scene->get_path_to(parent),child->get_type(),new_name); + editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name)); + } else { editor_data->get_undo_redo().add_do_method(editor,"set_edited_scene",child); diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp index 13734f2c4b7..a0ff55e8455 100644 --- a/tools/editor/script_editor_debugger.cpp +++ b/tools/editor/script_editor_debugger.cpp @@ -241,6 +241,8 @@ void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_dat lv[level]=it; } + le_clear->set_disabled(false); + le_set->set_disabled(false); } else if (p_msg=="stack_dump") { @@ -443,6 +445,8 @@ void ScriptEditorDebugger::_notification(int p_what) { tb->set_hover_texture( get_icon("CloseHover","EditorIcons")); tb->set_pressed_texture( get_icon("Close","EditorIcons")); scene_tree_refresh->set_icon( get_icon("Reload","EditorIcons")); + le_set->connect("pressed",this,"_live_edit_set"); + le_clear->connect("pressed",this,"_live_edit_clear"); } break; case NOTIFICATION_PROCESS: { @@ -468,6 +472,12 @@ void ScriptEditorDebugger::_notification(int p_what) { emit_signal("show_debugger",true); reason->set_text("Child Process Connected"); reason->set_tooltip("Child Process Connected"); + scene_tree->clear(); + le_set->set_disabled(true); + le_clear->set_disabled(false); + //live_edit_root->set_text("/root"); + + update_live_edit_root(); } else { @@ -613,6 +623,10 @@ void ScriptEditorDebugger::stop(){ log_forced_visible=false; } + node_path_cache.clear(); + res_path_cache.clear(); + le_clear->set_disabled(false); + le_set->set_disabled(true); hide(); @@ -664,6 +678,335 @@ String ScriptEditorDebugger::get_var_value(const String& p_var) const { return variables->get_var_value(p_var); } +int ScriptEditorDebugger::_get_node_path_cache(const NodePath& p_path) { + + const int *r = node_path_cache.getptr(p_path); + if (r) + return *r; + + last_path_id++; + + node_path_cache[p_path]=last_path_id; + Array msg; + msg.push_back("live_node_path"); + msg.push_back(p_path); + msg.push_back(last_path_id); + ppeer->put_var(msg); + + + return last_path_id; +} + +int ScriptEditorDebugger::_get_res_path_cache(const String& p_path) { + + Map::Element *E=res_path_cache.find(p_path); + + if (E) + return E->get(); + + last_path_id++; + + res_path_cache[p_path]=last_path_id; + Array msg; + msg.push_back("live_res_path"); + msg.push_back(p_path); + msg.push_back(last_path_id); + ppeer->put_var(msg); + + + return last_path_id; +} + +void ScriptEditorDebugger::_method_changed(Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE) { + + if (!p_base || !live_debug || !connection.is_valid() || !editor->get_edited_scene()) + return; + + Node *node = p_base->cast_to(); + + VARIANT_ARGPTRS + + for(int i=0;iget_type()==Variant::OBJECT || argptr[i]->get_type()==Variant::_RID)) + return; + } + + if (node) { + + NodePath path = editor->get_edited_scene()->get_path_to(node); + int pathid = _get_node_path_cache(path); + + + + Array msg; + msg.push_back("live_node_call"); + msg.push_back(pathid); + msg.push_back(p_name); + for(int i=0;iput_var(msg); + + return; + + } + + Resource *res = p_base->cast_to(); + + if (res && res->get_path()!=String()) { + + String respath = res->get_path(); + int pathid = _get_res_path_cache(respath); + + Array msg; + msg.push_back("live_res_call"); + msg.push_back(pathid); + msg.push_back(p_name); + for(int i=0;iput_var(msg); + + return; + } + + //print_line("method"); +} + +void ScriptEditorDebugger::_property_changed(Object*p_base,const StringName& p_property,const Variant& p_value){ + + if (!p_base || !live_debug || !connection.is_valid() || !editor->get_edited_scene()) + return; + + Node *node = p_base->cast_to(); + + if (node) { + + NodePath path = editor->get_edited_scene()->get_path_to(node); + int pathid = _get_node_path_cache(path); + + + if (p_value.is_ref()) { + Ref res = p_value; + if (res.is_valid() && res->get_path()!=String()) { + + Array msg; + msg.push_back("live_node_prop_res"); + msg.push_back(pathid); + msg.push_back(p_property); + msg.push_back(res->get_path()); + ppeer->put_var(msg); + } + } else { + + Array msg; + msg.push_back("live_node_prop"); + msg.push_back(pathid); + msg.push_back(p_property); + msg.push_back(p_value); + ppeer->put_var(msg); + } + + + return; + + } + + Resource *res = p_base->cast_to(); + + if (res && res->get_path()!=String()) { + + String respath = res->get_path(); + int pathid = _get_res_path_cache(respath); + + + if (p_value.is_ref()) { + Ref res = p_value; + if (res.is_valid() && res->get_path()!=String()) { + + Array msg; + msg.push_back("live_res_prop_res"); + msg.push_back(pathid); + msg.push_back(p_property); + msg.push_back(res->get_path()); + ppeer->put_var(msg); + } + } else { + + Array msg; + msg.push_back("live_res_prop"); + msg.push_back(pathid); + msg.push_back(p_property); + msg.push_back(p_value); + ppeer->put_var(msg); + } + + + return; + } + + + //print_line("prop"); +} + +void ScriptEditorDebugger::_method_changeds(void *p_ud,Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE) { + + ScriptEditorDebugger *sed = (ScriptEditorDebugger*)p_ud; + sed->_method_changed(p_base,p_name,VARIANT_ARG_PASS); + + +} + +void ScriptEditorDebugger::_property_changeds(void *p_ud,Object*p_base,const StringName& p_property,const Variant& p_value){ + + ScriptEditorDebugger *sed = (ScriptEditorDebugger*)p_ud; + sed->_property_changed(p_base,p_property,p_value); + +} + +void ScriptEditorDebugger::set_live_debugging(bool p_enable) { + + live_debug=p_enable; +} + +void ScriptEditorDebugger::_live_edit_set() { + + if (!connection.is_valid()) + return; + + TreeItem* ti = scene_tree->get_selected(); + if (!ti) + return; + String path; + + while(ti) { + String lp=ti->get_text(0); + path="/"+lp+path; + ti=ti->get_parent(); + + } + + NodePath np = path; + + editor->get_editor_data().set_edited_scene_live_edit_root(np); + + update_live_edit_root(); + + +} + +void ScriptEditorDebugger::_live_edit_clear() { + + NodePath np = NodePath("/root"); + editor->get_editor_data().set_edited_scene_live_edit_root(np); + + update_live_edit_root(); + +} + +void ScriptEditorDebugger::update_live_edit_root() { + + NodePath np = editor->get_editor_data().get_edited_scene_live_edit_root(); + + if (connection.is_valid()) { + Array msg; + msg.push_back("live_set_root"); + msg.push_back(np); + if (editor->get_edited_scene()) + msg.push_back(editor->get_edited_scene()->get_filename()); + else + msg.push_back(""); + ppeer->put_var(msg); + } + live_edit_root->set_text(np); + +} + +void ScriptEditorDebugger::live_debug_create_node(const NodePath& p_parent,const String& p_type,const String& p_name) { + + if (connection.is_valid()) { + Array msg; + msg.push_back("live_create_node"); + msg.push_back(p_parent); + msg.push_back(p_type); + msg.push_back(p_name); + ppeer->put_var(msg); + } +} + +void ScriptEditorDebugger::live_debug_instance_node(const NodePath& p_parent,const String& p_path,const String& p_name){ + + if (connection.is_valid()) { + Array msg; + msg.push_back("live_instance_node"); + msg.push_back(p_parent); + msg.push_back(p_path); + msg.push_back(p_name); + ppeer->put_var(msg); + } + +} +void ScriptEditorDebugger::live_debug_remove_node(const NodePath& p_at){ + + if (connection.is_valid()) { + Array msg; + msg.push_back("live_remove_node"); + msg.push_back(p_at); + ppeer->put_var(msg); + } + +} +void ScriptEditorDebugger::live_debug_remove_and_keep_node(const NodePath& p_at,ObjectID p_keep_id) { + + if (connection.is_valid()) { + Array msg; + msg.push_back("live_remove_and_keep_mode"); + msg.push_back(p_at); + msg.push_back(p_keep_id); + ppeer->put_var(msg); + } + +} +void ScriptEditorDebugger::live_debug_restore_node(ObjectID p_id, const NodePath& p_at, int p_at_pos){ + + if (connection.is_valid()) { + Array msg; + msg.push_back("live_restore_node"); + msg.push_back(p_id); + msg.push_back(p_at); + msg.push_back(p_at_pos); + ppeer->put_var(msg); + } + +} +void ScriptEditorDebugger::live_debug_duplicate_node(const NodePath& p_at,const String& p_new_name){ + + if (connection.is_valid()) { + Array msg; + msg.push_back("live_duplicate_node"); + msg.push_back(p_at); + msg.push_back(p_new_name); + ppeer->put_var(msg); + } + +} +void ScriptEditorDebugger::live_debug_reparent_node(const NodePath& p_at, const NodePath& p_new_place, const String &p_new_name){ + + if (connection.is_valid()) { + Array msg; + msg.push_back("live_reparent_node"); + msg.push_back(p_at); + msg.push_back(p_new_place); + msg.push_back(p_new_name); + ppeer->put_var(msg); + } + +} + + void ScriptEditorDebugger::_bind_methods() { ObjectTypeDB::bind_method(_MD("_stack_dump_frame_selected"),&ScriptEditorDebugger::_stack_dump_frame_selected); @@ -676,6 +1019,16 @@ void ScriptEditorDebugger::_bind_methods() { ObjectTypeDB::bind_method(_MD("_performance_draw"),&ScriptEditorDebugger::_performance_draw); ObjectTypeDB::bind_method(_MD("_performance_select"),&ScriptEditorDebugger::_performance_select); ObjectTypeDB::bind_method(_MD("_scene_tree_request"),&ScriptEditorDebugger::_scene_tree_request); + ObjectTypeDB::bind_method(_MD("_live_edit_set"),&ScriptEditorDebugger::_live_edit_set); + ObjectTypeDB::bind_method(_MD("_live_edit_clear"),&ScriptEditorDebugger::_live_edit_clear); + + ObjectTypeDB::bind_method(_MD("live_debug_create_node"),&ScriptEditorDebugger::live_debug_create_node); + ObjectTypeDB::bind_method(_MD("live_debug_instance_node"),&ScriptEditorDebugger::live_debug_instance_node); + ObjectTypeDB::bind_method(_MD("live_debug_remove_node"),&ScriptEditorDebugger::live_debug_remove_node); + ObjectTypeDB::bind_method(_MD("live_debug_remove_and_keep_node"),&ScriptEditorDebugger::live_debug_remove_and_keep_node); + ObjectTypeDB::bind_method(_MD("live_debug_restore_node"),&ScriptEditorDebugger::live_debug_restore_node); + ObjectTypeDB::bind_method(_MD("live_debug_duplicate_node"),&ScriptEditorDebugger::live_debug_duplicate_node); + ObjectTypeDB::bind_method(_MD("live_debug_reparent_node"),&ScriptEditorDebugger::live_debug_reparent_node); ADD_SIGNAL(MethodInfo("goto_script_line")); ADD_SIGNAL(MethodInfo("breaked",PropertyInfo(Variant::BOOL,"reallydid"))); @@ -843,6 +1196,26 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){ info_left->add_margin_child("Clicked Control:",clicked_ctrl); clicked_ctrl_type = memnew( LineEdit ); info_left->add_margin_child("Clicked Control Type:",clicked_ctrl_type); + + live_edit_root = memnew( LineEdit ); + + { + HBoxContainer *lehb = memnew( HBoxContainer ); + Label *l = memnew( Label("Live Edit Root:") ); + lehb->add_child(l); + l->set_h_size_flags(SIZE_EXPAND_FILL); + le_set = memnew( Button("Set From Tree") ); + lehb->add_child(le_set); + le_clear = memnew( Button("Clear") ); + lehb->add_child(le_clear); + info_left->add_child(lehb); + MarginContainer *mc = memnew( MarginContainer ); + mc->add_child(live_edit_root); + info_left->add_child(mc); + le_set->set_disabled(true); + le_clear->set_disabled(true); + } + VBoxContainer *info_right = memnew(VBoxContainer); info_right->set_h_size_flags(SIZE_EXPAND_FILL); info->add_child(info_right); @@ -868,6 +1241,11 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){ hide(); log_forced_visible=false; + p_editor->get_undo_redo()->set_method_notify_callback(_method_changeds,this); + p_editor->get_undo_redo()->set_property_notify_callback(_property_changeds,this); + live_debug=false; + last_path_id=false; + } ScriptEditorDebugger::~ScriptEditorDebugger() { diff --git a/tools/editor/script_editor_debugger.h b/tools/editor/script_editor_debugger.h index c59cc1cf9d5..e8ac0fddb33 100644 --- a/tools/editor/script_editor_debugger.h +++ b/tools/editor/script_editor_debugger.h @@ -56,9 +56,13 @@ class ScriptEditorDebugger : public Control { LineEdit *clicked_ctrl; LineEdit *clicked_ctrl_type; + LineEdit *live_edit_root; Tree *scene_tree; HSplitContainer *info; Button *scene_tree_refresh; + Button *le_set; + Button *le_clear; + TextureButton *tb; @@ -94,11 +98,17 @@ class ScriptEditorDebugger : public Control { Array message; int pending_in_queue; + HashMap node_path_cache; + int last_path_id; + Map res_path_cache; + EditorNode *editor; bool breaked; + bool live_debug; + void _performance_draw(); void _performance_select(Object *, int, bool); void _stack_dump_frame_selected(); @@ -108,6 +118,20 @@ class ScriptEditorDebugger : public Control { void _scene_tree_request(); void _parse_message(const String& p_msg,const Array& p_data); + + int _get_node_path_cache(const NodePath& p_path); + + int _get_res_path_cache(const String& p_path); + + void _live_edit_set(); + void _live_edit_clear(); + + void _method_changed(Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE); + void _property_changed(Object*p_base,const StringName& p_property,const Variant& p_value); + + static void _method_changeds(void *p_ud,Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE); + static void _property_changeds(void *p_ud,Object*p_base,const StringName& p_property,const Variant& p_value); + protected: void _notification(int p_what); @@ -127,6 +151,19 @@ public: String get_var_value(const String& p_var) const; + void set_live_debugging(bool p_enable); + + void live_debug_create_node(const NodePath& p_parent,const String& p_type,const String& p_name); + void live_debug_instance_node(const NodePath& p_parent,const String& p_path,const String& p_name); + void live_debug_remove_node(const NodePath& p_at); + void live_debug_remove_and_keep_node(const NodePath& p_at,ObjectID p_keep_id); + void live_debug_restore_node(ObjectID p_id,const NodePath& p_at,int p_at_pos); + void live_debug_duplicate_node(const NodePath& p_at,const String& p_new_name); + void live_debug_reparent_node(const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name); + + void update_live_edit_root(); + + virtual Size2 get_minimum_size() const; ScriptEditorDebugger(EditorNode *p_editor=NULL); ~ScriptEditorDebugger();