Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/classes/Tree.xml
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@
The drop mode as an OR combination of flags. See [enum DropModeFlags] constants. Once dropping is done, reverts to [constant DROP_MODE_DISABLED]. Setting this during [method Control._can_drop_data] is recommended.
This controls the drop sections, i.e. the decision and drawing of possible drop locations based on the mouse position.
</member>
<member name="enable_recursive_folding" type="bool" setter="set_enable_recursive_folding" getter="is_recursive_folding_enabled" default="true">
If [code]true[/code], recursive folding is enabled for this [Tree]. Holding down Shift while clicking the fold arrow collapses or uncollapses the [TreeItem] and all its descendants.
</member>
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" />
<member name="hide_folding" type="bool" setter="set_hide_folding" getter="is_folding_hidden" default="false">
If [code]true[/code], the folding arrow is hidden.
Expand Down
15 changes: 15 additions & 0 deletions doc/classes/TreeItem.xml
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,14 @@
Returns the [Tree] that owns this TreeItem.
</description>
</method>
<method name="is_any_collapsed">
<return type="bool" />
<param index="0" name="only_visible" type="bool" default="false" />
<description>
Returns [code]true[/code] if this [TreeItem], or any of its descendants, is collapsed.
If [param only_visible] is [code]true[/code] it ignores non-visible [TreeItem]s.
</description>
</method>
<method name="is_button_disabled" qualifiers="const">
<return type="bool" />
<param index="0" name="column" type="int" />
Expand Down Expand Up @@ -442,6 +450,13 @@
If [code]true[/code], the given [param column] is checked. Clears column's indeterminate status.
</description>
</method>
<method name="set_collapsed_recursive">
<return type="void" />
<param index="0" name="enable" type="bool" />
<description>
Collapses or uncollapses this [TreeItem] and all the descendants of this item.
</description>
</method>
<method name="set_custom_as_button">
<return type="void" />
<param index="0" name="column" type="int" />
Expand Down
17 changes: 1 addition & 16 deletions editor/filesystem_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1751,22 +1751,7 @@ void FileSystemDock::_tree_rmb_option(int p_option) {
case FOLDER_COLLAPSE_ALL: {
// Expand or collapse the folder
if (selected_strings.size() == 1) {
bool is_collapsed = (p_option == FOLDER_COLLAPSE_ALL);

Vector<TreeItem *> needs_check;
needs_check.push_back(tree->get_selected());

while (needs_check.size()) {
needs_check[0]->set_collapsed(is_collapsed);

TreeItem *child = needs_check[0]->get_first_child();
while (child) {
needs_check.push_back(child);
child = child->get_next();
}

needs_check.remove_at(0);
}
tree->get_selected()->set_collapsed_recursive(p_option == FOLDER_COLLAPSE_ALL);
}
} break;
default: {
Expand Down
58 changes: 2 additions & 56 deletions editor/scene_tree_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
}

bool collapsed = _is_collapsed_recursive(selected_item);
_set_collapsed_recursive(selected_item, !collapsed);
bool collapsed = selected_item->is_any_collapsed();
selected_item->set_collapsed_recursive(!collapsed);

tree->ensure_cursor_is_visible();

Expand Down Expand Up @@ -1223,17 +1223,6 @@ void SceneTreeDock::add_root_node(Node *p_node) {
editor_data->get_undo_redo()->commit_action();
}

void SceneTreeDock::_node_collapsed(Object *p_obj) {
TreeItem *ti = Object::cast_to<TreeItem>(p_obj);
if (!ti) {
return;
}

if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
_set_collapsed_recursive(ti, ti->is_collapsed());
}
}

void SceneTreeDock::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
Expand Down Expand Up @@ -1945,48 +1934,6 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
editor_data->get_undo_redo()->commit_action();
}

bool SceneTreeDock::_is_collapsed_recursive(TreeItem *p_item) const {
bool is_branch_collapsed = false;

List<TreeItem *> needs_check;
needs_check.push_back(p_item);

while (!needs_check.is_empty()) {
TreeItem *item = needs_check.back()->get();
needs_check.pop_back();

TreeItem *child = item->get_first_child();
is_branch_collapsed = item->is_collapsed() && child;

if (is_branch_collapsed) {
break;
}
while (child) {
needs_check.push_back(child);
child = child->get_next();
}
}
return is_branch_collapsed;
}

void SceneTreeDock::_set_collapsed_recursive(TreeItem *p_item, bool p_collapsed) {
List<TreeItem *> to_collapse;
to_collapse.push_back(p_item);

while (!to_collapse.is_empty()) {
TreeItem *item = to_collapse.back()->get();
to_collapse.pop_back();

item->set_collapsed(p_collapsed);

TreeItem *child = item->get_first_child();
while (child) {
to_collapse.push_back(child);
child = child->get_next();
}
}
}

void SceneTreeDock::_script_created(Ref<Script> p_script) {
List<Node *> selected = editor_selection->get_selected_node_list();

Expand Down Expand Up @@ -3532,7 +3479,6 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
scene_tree->connect("nodes_dragged", callable_mp(this, &SceneTreeDock::_nodes_drag_begin));

scene_tree->get_scene_tree()->connect("item_double_clicked", callable_mp(this, &SceneTreeDock::_focus_node));
scene_tree->get_scene_tree()->connect("item_collapsed", callable_mp(this, &SceneTreeDock::_node_collapsed));

editor_selection->connect("selection_changed", callable_mp(this, &SceneTreeDock::_selection_changed));

Expand Down
4 changes: 0 additions & 4 deletions editor/scene_tree_dock.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ class SceneTreeDock : public VBoxContainer {
HBoxContainer *tool_hbc = nullptr;
void _tool_selected(int p_tool, bool p_confirm_override = false);
void _property_selected(int p_idx);
void _node_collapsed(Object *p_obj);

Node *property_drop_node = nullptr;
String resource_drop_path;
Expand Down Expand Up @@ -188,9 +187,6 @@ class SceneTreeDock : public VBoxContainer {
void _node_reparent(NodePath p_path, bool p_keep_global_xform);
void _do_reparent(Node *p_new_parent, int p_position_in_parent, Vector<Node *> p_nodes, bool p_keep_global_xform);

bool _is_collapsed_recursive(TreeItem *p_item) const;
void _set_collapsed_recursive(TreeItem *p_item, bool p_collapsed);

void _set_owners(Node *p_owner, const Array &p_nodes);

enum ReplaceOwnerMode {
Expand Down
78 changes: 76 additions & 2 deletions scene/gui/tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,57 @@ bool TreeItem::is_collapsed() {
return collapsed;
}

void TreeItem::set_collapsed_recursive(bool p_collapsed) {
if (!tree) {
return;
}

set_collapsed(p_collapsed);

TreeItem *child = get_first_child();
while (child) {
child->set_collapsed_recursive(p_collapsed);
child = child->get_next();
}
}

bool TreeItem::_is_any_collapsed(bool p_only_visible) {
TreeItem *child = get_first_child();

// Check on children directly first (avoid recursing if possible).
while (child) {
if (child->get_first_child() && child->is_collapsed() && (!p_only_visible || (child->is_visible() && child->get_visible_child_count()))) {
return true;
}
child = child->get_next();
}

child = get_first_child();

// Otherwise recurse on children.
while (child) {
if (child->get_first_child() && (!p_only_visible || (child->is_visible() && child->get_visible_child_count())) && child->_is_any_collapsed(p_only_visible)) {
return true;
}
child = child->get_next();
}

return false;
}

bool TreeItem::is_any_collapsed(bool p_only_visible) {
if (p_only_visible && !is_visible()) {
return false;
}

// Collapsed if this is collapsed and it has children (only considers visible if only visible is set).
if (is_collapsed() && get_first_child() && (!p_only_visible || get_visible_child_count())) {
return true;
}

return _is_any_collapsed(p_only_visible);
}

void TreeItem::set_visible(bool p_visible) {
if (visible == p_visible) {
return;
Expand Down Expand Up @@ -1406,6 +1457,9 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collapsed", "enable"), &TreeItem::set_collapsed);
ClassDB::bind_method(D_METHOD("is_collapsed"), &TreeItem::is_collapsed);

ClassDB::bind_method(D_METHOD("set_collapsed_recursive", "enable"), &TreeItem::set_collapsed_recursive);
ClassDB::bind_method(D_METHOD("is_any_collapsed", "only_visible"), &TreeItem::is_any_collapsed, DEFVAL(false));

ClassDB::bind_method(D_METHOD("set_visible", "enable"), &TreeItem::set_visible);
ClassDB::bind_method(D_METHOD("is_visible"), &TreeItem::is_visible);

Expand Down Expand Up @@ -2572,7 +2626,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}

if (!p_item->disable_folding && !hide_folding && p_item->first_child && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + theme_cache.item_margin))) {
p_item->set_collapsed(!p_item->is_collapsed());
if (enable_recursive_folding && p_mod->is_shift_pressed()) {
p_item->set_collapsed_recursive(!p_item->is_collapsed());
} else {
p_item->set_collapsed(!p_item->is_collapsed());
}
return -1;
}

Expand Down Expand Up @@ -2623,7 +2681,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}

if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_first_child()) {
p_item->set_collapsed(!p_item->is_collapsed());
if (enable_recursive_folding && p_mod->is_shift_pressed()) {
p_item->set_collapsed_recursive(!p_item->is_collapsed());
} else {
p_item->set_collapsed(!p_item->is_collapsed());
}
return -1; //collapse/uncollapse because nothing can be done with item
}

Expand Down Expand Up @@ -5026,6 +5088,14 @@ bool Tree::is_folding_hidden() const {
return hide_folding;
}

void Tree::set_enable_recursive_folding(bool p_enable) {
enable_recursive_folding = p_enable;
}

bool Tree::is_recursive_folding_enabled() const {
return enable_recursive_folding;
}

void Tree::set_drop_mode_flags(int p_flags) {
if (drop_mode_flags == p_flags) {
return;
Expand Down Expand Up @@ -5129,6 +5199,9 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hide_folding", "hide"), &Tree::set_hide_folding);
ClassDB::bind_method(D_METHOD("is_folding_hidden"), &Tree::is_folding_hidden);

ClassDB::bind_method(D_METHOD("set_enable_recursive_folding", "enable"), &Tree::set_enable_recursive_folding);
ClassDB::bind_method(D_METHOD("is_recursive_folding_enabled"), &Tree::is_recursive_folding_enabled);

ClassDB::bind_method(D_METHOD("set_drop_mode_flags", "flags"), &Tree::set_drop_mode_flags);
ClassDB::bind_method(D_METHOD("get_drop_mode_flags"), &Tree::get_drop_mode_flags);

Expand All @@ -5143,6 +5216,7 @@ void Tree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_reselect"), "set_allow_reselect", "get_allow_reselect");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_folding"), "set_hide_folding", "is_folding_hidden");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_recursive_folding"), "set_enable_recursive_folding", "is_recursive_folding_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_root"), "set_hide_root", "is_root_hidden");
ADD_PROPERTY(PropertyInfo(Variant::INT, "drop_mode_flags", PROPERTY_HINT_FLAGS, "On Item,In Between"), "set_drop_mode_flags", "get_drop_mode_flags");
ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Row,Multi"), "set_select_mode", "get_select_mode");
Expand Down
10 changes: 10 additions & 0 deletions scene/gui/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ class TreeItem : public Object {
}
}

bool _is_any_collapsed(bool p_only_visible);

protected:
static void _bind_methods();

Expand Down Expand Up @@ -272,6 +274,9 @@ class TreeItem : public Object {
void set_collapsed(bool p_collapsed);
bool is_collapsed();

void set_collapsed_recursive(bool p_collapsed);
bool is_any_collapsed(bool p_only_visible = false);

void set_visible(bool p_visible);
bool is_visible();

Expand Down Expand Up @@ -613,6 +618,8 @@ class Tree : public Control {

bool hide_folding = false;

bool enable_recursive_folding = true;

int _count_selected_items(TreeItem *p_from) const;
bool _is_branch_selected(TreeItem *p_from) const;
bool _is_sibling_branch_selected(TreeItem *p_from) const;
Expand Down Expand Up @@ -712,6 +719,9 @@ class Tree : public Control {
void set_hide_folding(bool p_hide);
bool is_folding_hidden() const;

void set_enable_recursive_folding(bool p_enable);
bool is_recursive_folding_enabled() const;

void set_drop_mode_flags(int p_flags);
int get_drop_mode_flags() const;

Expand Down