summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2015-08-02 12:29:37 -0300
committerJuan Linietsky <reduzio@gmail.com>2015-08-02 12:30:01 -0300
commit59961c99144523d7cc2881a4abe6d0a319a975df (patch)
tree556cd9053433a27bbbc34dfe0a3e9fe693957299 /tools
parent922356b903061cda7591090bf19e8346c3a78cf5 (diff)
Live edit WORK IN PROGRESS
1) press the heart while the game is running 2) select a scene to live edit from the opened scenes 3) edit/add/remove nodes or resources, change their properties, etc. 4) watch changes reflected in running game, in all places this scene is edited 5) It's not perfect obviously, but the aim of it is to try to reflect your changes as best as possible in the running game.
Diffstat (limited to 'tools')
-rw-r--r--tools/editor/editor_data.cpp18
-rw-r--r--tools/editor/editor_data.h3
-rw-r--r--tools/editor/editor_node.cpp18
-rw-r--r--tools/editor/editor_node.h2
-rw-r--r--tools/editor/icons/icon_live_debug.pngbin0 -> 583 bytes
-rw-r--r--tools/editor/plugins/script_editor_plugin.h2
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.cpp17
-rw-r--r--tools/editor/scene_tree_dock.cpp37
-rw-r--r--tools/editor/script_editor_debugger.cpp378
-rw-r--r--tools/editor/script_editor_debugger.h37
10 files changed, 502 insertions, 10 deletions
diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp
index f729a6c869..7f42f19a9b 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 14a50da082..cbec2295f6 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<ConfigFile> p_layout);
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 7789008c62..84107bdaf7 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 495f069b55..93b95034ff 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 0000000000..ad55646b9a
--- /dev/null
+++ b/tools/editor/icons/icon_live_debug.png
Binary files differ
diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h
index 0dd152cb25..59173068fb 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<ConfigFile> p_layout);
void get_window_layout(Ref<ConfigFile> 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 017a26441d..66c7a39096 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<Point2i,CellOp>::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<Point2i,CellOp>::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 49cbebdb43..111d307b8e 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 13734f2c4b..a0ff55e845 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<String,int>::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<Node>();
+
+ VARIANT_ARGPTRS
+
+ for(int i=0;i<VARIANT_ARG_MAX;i++) {
+ //no pointers, sorry
+ if (argptr[i] && (argptr[i]->get_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;i<VARIANT_ARG_MAX;i++) {
+ //no pointers, sorry
+ msg.push_back(*argptr[i]);
+ }
+ ppeer->put_var(msg);
+
+ return;
+
+ }
+
+ Resource *res = p_base->cast_to<Resource>();
+
+ 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;i<VARIANT_ARG_MAX;i++) {
+ //no pointers, sorry
+ msg.push_back(*argptr[i]);
+ }
+ ppeer->put_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<Node>();
+
+ 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<Resource> 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<Resource>();
+
+ if (res && res->get_path()!=String()) {
+
+ String respath = res->get_path();
+ int pathid = _get_res_path_cache(respath);
+
+
+ if (p_value.is_ref()) {
+ Ref<Resource> 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 c59cc1cf9d..e8ac0fddb3 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<NodePath,int> node_path_cache;
+ int last_path_id;
+ Map<String,int> 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();