From f23e1aab34d1c29b00531d42abd9a18f37fe9257 Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Thu, 25 Oct 2018 10:39:02 +0200 Subject: [PATCH] Implemented remote scene tree filtering User can now filter the remote scene tree, like the local one is filtered, while the game is running --- editor/script_editor_debugger.cpp | 103 ++++++++++++++++++------------ editor/script_editor_debugger.h | 1 + scene/main/scene_tree.cpp | 2 +- 3 files changed, 64 insertions(+), 42 deletions(-) diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index a661c2cfc3d..5a95ac8e59f 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -381,6 +381,67 @@ void ScriptEditorDebugger::_scene_tree_request() { ppeer->put_var(msg); } +/// Populates inspect_scene_tree recursively given data in nodes. +/// Nodes is an array containing 4 elements for each node, it follows this pattern: +/// nodes[i] == number of direct children of this node +/// nodes[i + 1] == node name +/// nodes[i + 2] == node class +/// nodes[i + 3] == node instance id +/// +/// Returns the number of items parsed in nodes from current_index. +/// +/// Given a nodes array like [R,A,B,C,D,E] the following Tree will be generated, assuming +/// filter is an empty String, R and A child count are 2, B is 1 and C, D and E are 0. +/// +/// R +/// |-A +/// | |-B +/// | | |-C +/// | | +/// | |-D +/// | +/// |-E +/// +int ScriptEditorDebugger::_update_scene_tree(TreeItem *parent, const Array &nodes, int current_index) { + String filter = EditorNode::get_singleton()->get_scene_tree_dock()->get_filter(); + String item_text = nodes[current_index + 1]; + bool keep = filter.is_subsequence_ofi(item_text); + + TreeItem *item = inspect_scene_tree->create_item(parent); + item->set_text(0, item_text); + ObjectID id = ObjectID(nodes[current_index + 3]); + Ref icon = EditorNode::get_singleton()->get_class_icon(nodes[current_index + 2], ""); + if (icon.is_valid()) { + item->set_icon(0, icon); + } + item->set_metadata(0, id); + + int children_count = nodes[current_index]; + // Tracks the total number of items parsed in nodes, this is used to skips nodes that + // are not direct children of the current node since we can't know in advance the total + // number of children, direct and not, of a node without traversing the nodes array previously. + // Keeping track of this allows us to build our remote scene tree by traversing the node + // array just once. + int items_count = 1; + for (int i = 0; i < children_count; i++) { + // Called for each direct child of item. + // Direct children of current item might not be adjacent so items_count must + // be incremented by the number of items parsed until now, otherwise we would not + // be able to access the next child of the current item. + // items_count is multiplied by 4 since that's the number of elements in the nodes + // array needed to represent a single node. + items_count += _update_scene_tree(item, nodes, current_index + items_count * 4); + } + + // If item has not children and should not be kept delete it + if (!keep && !item->get_children() && parent) { + parent->remove_child(item); + memdelete(item); + } + + return items_count; +} + void ScriptEditorDebugger::_video_mem_request() { ERR_FAIL_COND(connection.is_null()); @@ -453,48 +514,8 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da updating_scene_tree = true; - for (int i = 0; i < p_data.size(); i += 4) { + _update_scene_tree(NULL, p_data, 0); - TreeItem *p; - int level = p_data[i]; - if (level == 0) { - p = NULL; - } else { - ERR_CONTINUE(!lv.has(level - 1)); - p = lv[level - 1]; - } - - TreeItem *it = inspect_scene_tree->create_item(p); - - ObjectID id = ObjectID(p_data[i + 3]); - - it->set_text(0, p_data[i + 1]); - Ref icon = EditorNode::get_singleton()->get_class_icon(p_data[i + 2], ""); - if (icon.is_valid()) - it->set_icon(0, icon); - it->set_metadata(0, id); - - if (id == inspected_object_id) { - TreeItem *cti = it->get_parent(); //ensure selected is always uncollapsed - while (cti) { - cti->set_collapsed(false); - cti = cti->get_parent(); - } - it->select(0); - } - - if (p) { - if (!unfold_cache.has(id)) { - it->set_collapsed(true); - } - } else { - if (unfold_cache.has(id)) { //reverse for root - it->set_collapsed(true); - } - } - - lv[level] = it; - } updating_scene_tree = false; le_clear->set_disabled(false); diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index 05dcab0f80d..505eab266f9 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -173,6 +173,7 @@ class ScriptEditorDebugger : public Control { void _set_reason_text(const String &p_reason, MessageType p_type); void _scene_tree_property_select_object(ObjectID p_object); void _scene_tree_property_value_edited(const String &p_prop, const Variant &p_value); + int _update_scene_tree(TreeItem *parent, const Array &items, int current_index); void _video_mem_request(); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 65cda73a231..12c86551094 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1091,7 +1091,7 @@ void SceneTree::get_nodes_in_group(const StringName &p_group, List *p_li static void _fill_array(Node *p_node, Array &array, int p_level) { - array.push_back(p_level); + array.push_back(p_node->get_child_count()); array.push_back(p_node->get_name()); array.push_back(p_node->get_class()); array.push_back(p_node->get_instance_id());