Skip to content
Draft
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
244 changes: 109 additions & 135 deletions editor/scene_tree_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,14 @@ void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) {
_tool_selected(TOOL_NEW);
} else if (ED_IS_SHORTCUT("scene_tree/instance_scene", p_event)) {
_tool_selected(TOOL_INSTANCE);
} else if (ED_IS_SHORTCUT("scene_tree/expand_collapse_all", p_event)) {
_tool_selected(TOOL_EXPAND_COLLAPSE);
} else if (ED_IS_SHORTCUT("scene_tree/expand_all", p_event)) {
_tool_selected(TOOL_EXPAND_ALL);
} else if (ED_IS_SHORTCUT("scene_tree/collapse_all", p_event)) {
_tool_selected(TOOL_COLLAPSE_ALL);
} else if (ED_IS_SHORTCUT("scene_tree/collapse_all_inactive", p_event)) {
_tool_selected(TOOL_COLLAPSE_INACTIVE);
} else if (ED_IS_SHORTCUT("scene_tree/expand_collapse_descendants", p_event)) {
_tool_selected(TOOL_EXPAND_COLLAPSE_DESCENDANTS);
} else if (ED_IS_SHORTCUT("scene_tree/change_node_type", p_event)) {
_tool_selected(TOOL_REPLACE);
} else if (ED_IS_SHORTCUT("scene_tree/duplicate", p_event)) {
Expand Down Expand Up @@ -389,21 +395,29 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
quick_open->set_title(TTR("Instance Child Scene"));

} break;
case TOOL_EXPAND_COLLAPSE: {
case TOOL_EXPAND_ALL: {

if (!scene_tree->get_selected())
break;
Tree *tree = scene_tree->get_scene_tree();
tree->set_collapsed_all(false, false);

} break;
case TOOL_COLLAPSE_ALL: {

Tree *tree = scene_tree->get_scene_tree();
TreeItem *selected_item = tree->get_selected();
tree->set_collapsed_all(true, false);

if (!selected_item)
selected_item = tree->get_root();
} break;
case TOOL_COLLAPSE_INACTIVE: {

bool collapsed = _is_collapsed_recursive(selected_item);
_set_collapsed_recursive(selected_item, !collapsed);
Tree *tree = scene_tree->get_scene_tree();
tree->set_collapsed_all(true, true);

tree->ensure_cursor_is_visible();
} break;
case TOOL_EXPAND_COLLAPSE_DESCENDANTS: {

Tree *tree = scene_tree->get_scene_tree();
TreeItem *selected_item = (!tree->get_selected()) ? tree->get_root() : tree->get_selected();
selected_item->toggle_collapsed_all_descendants();

} break;
case TOOL_REPLACE: {
Expand Down Expand Up @@ -1024,17 +1038,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
}

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) {
Expand Down Expand Up @@ -1066,7 +1069,6 @@ void SceneTreeDock::_notification(int p_what) {
filter->set_clear_button_enabled(true);

EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed", this, "_selection_changed");
scene_tree->get_scene_tree()->connect("item_collapsed", this, "_node_collapsed");

// create_root_dialog
HBoxContainer *top_row = memnew(HBoxContainer);
Expand Down Expand Up @@ -1666,52 +1668,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.empty()) {

TreeItem *item = needs_check.back()->get();
needs_check.pop_back();

TreeItem *child = item->get_children();
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.empty()) {

TreeItem *item = to_collapse.back()->get();
to_collapse.pop_back();

item->set_collapsed(p_collapsed);

TreeItem *child = item->get_children();
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 @@ -2386,6 +2342,7 @@ void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) {

void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {

// No edited scene -> This can happen?
if (!EditorNode::get_singleton()->get_edited_scene()) {

menu->clear();
Expand All @@ -2400,51 +2357,68 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
return;
}

// Standard Menu
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *> full_selection = editor_selection->get_full_selected_node_list(); // Above method only returns nodes with common parent.

if (selection.size() == 0)
return;

List<Node *> full_selection = editor_selection->get_full_selected_node_list(); // Above method only returns nodes with common parent.
menu->clear();

Ref<Script> existing_script;
bool exisiting_script_removable = true;
if (selection.size() == 1) {
if (selection.size() == 1 && profile_allow_editing) {

Node *selected = selection[0];
// Sub-Ressources Section
subresources.clear();
menu_subresources->clear();
menu_subresources->set_size(Size2(1, 1));

if (profile_allow_editing) {
subresources.clear();
menu_subresources->clear();
menu_subresources->set_size(Size2(1, 1));
_add_children_to_popup(selection.front()->get(), 0);
if (menu->get_item_count() > 0)
menu->add_separator();
_add_children_to_popup(selection.front()->get(), 0);

menu->add_icon_shortcut(get_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
menu->add_icon_shortcut(get_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
if (menu->get_item_count() > 0) {
menu->add_separator();
}
menu->add_icon_shortcut(get_icon("Collapse", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE);
menu->add_separator();

existing_script = selected->get_script();

if (EditorNode::get_singleton()->get_object_custom_type_base(selected) == existing_script) {
exisiting_script_removable = false;
}
// Node Manipulation Section
menu->add_icon_shortcut(get_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
menu->add_icon_shortcut(get_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
menu->add_icon_shortcut(get_icon("Blend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE);
menu->add_icon_shortcut(get_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
menu->add_icon_shortcut(get_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
menu->add_separator();
}

// Collapse/Expand Section
menu->add_icon_shortcut(get_icon("AnimationTrackGroup", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/expand_all"), TOOL_EXPAND_ALL);
menu->add_icon_shortcut(get_icon("AnimationTrackList", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/collapse_all"), TOOL_COLLAPSE_ALL);
menu->add_icon_shortcut(get_icon("Collapse", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/collapse_all_inactive"), TOOL_COLLAPSE_INACTIVE); // Only works for first selected item. TODO: FIX!
menu->add_icon_shortcut(get_icon("Collapse", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/expand_collapse_descendants"), TOOL_EXPAND_COLLAPSE_DESCENDANTS);
menu->add_separator();

// Script Section
if (profile_allow_script_editing) {

bool add_separator = false;
Ref<Script> existing_script;
bool exisiting_script_removable = true;

if (selection.size() == 1) {
Node *selected = selection[0];
existing_script = selected->get_script();

if (EditorNode::get_singleton()->get_object_custom_type_base(selected) == existing_script) {
exisiting_script_removable = false;
}
}

if (full_selection.size() == 1) {
add_separator = true;
menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);

if (existing_script.is_valid()) {
menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_EXTEND_SCRIPT);
}
}

if (existing_script.is_valid() && exisiting_script_removable) {
add_separator = true;
menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
Expand All @@ -2468,14 +2442,19 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
}
}

// TreeItem Manipulation Section
if (profile_allow_editing) {

if (full_selection.size() == 1) {
menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME);
menu->add_separator();
} else if (selection.size() > 1) {
// this should be in the same section as the usual single item rename
menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
menu->add_separator();
}
menu->add_icon_shortcut(get_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);

if (scene_tree->get_selected() != edited_scene) {
menu->add_separator();
menu->add_icon_shortcut(get_icon("MoveUp", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP);
menu->add_icon_shortcut(get_icon("MoveDown", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN);
menu->add_icon_shortcut(get_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE);
Expand All @@ -2484,60 +2463,53 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (selection.size() == 1) {
menu->add_icon_shortcut(get_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT);
}
menu->add_separator();
}
}
if (selection.size() == 1) {

if (profile_allow_editing) {
menu->add_separator();
menu->add_icon_shortcut(get_icon("Blend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE);
menu->add_icon_shortcut(get_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
}
if (full_selection.size() == 1) {
// Is-External Section
if (selection.size() == 1 && selection[0]->get_filename() != "") {

bool is_inherited = selection[0]->get_scene_inherited_state() != NULL;
bool is_top_level = selection[0]->get_owner() == NULL;

if (is_inherited && is_top_level) {
if (profile_allow_editing) {
menu->add_item(TTR("Clear Inheritance"), TOOL_SCENE_CLEAR_INHERITANCE);
}
menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN_INHERITED);
menu->add_separator();
menu->add_icon_shortcut(get_icon("CopyNodePath", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
}
} else if (!is_top_level) {
bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(selection[0]);
bool placeholder = selection[0]->get_scene_instance_load_placeholder();

bool is_external = (selection[0]->get_filename() != "");
if (is_external) {
bool is_inherited = selection[0]->get_scene_inherited_state() != NULL;
bool is_top_level = selection[0]->get_owner() == NULL;
if (is_inherited && is_top_level) {
menu->add_separator();
if (profile_allow_editing) {
menu->add_item(TTR("Clear Inheritance"), TOOL_SCENE_CLEAR_INHERITANCE);
}
menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN_INHERITED);
} else if (!is_top_level) {
menu->add_separator();
bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(selection[0]);
bool placeholder = selection[0]->get_scene_instance_load_placeholder();
if (profile_allow_editing) {
menu->add_check_item(TTR("Editable Children"), TOOL_SCENE_EDITABLE_CHILDREN);
menu->add_check_item(TTR("Load As Placeholder"), TOOL_SCENE_USE_PLACEHOLDER);
menu->add_item(TTR("Make Local"), TOOL_SCENE_MAKE_LOCAL);
}
menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN);
if (profile_allow_editing) {
menu->set_item_checked(menu->get_item_idx_from_text(TTR("Editable Children")), editable);
menu->set_item_checked(menu->get_item_idx_from_text(TTR("Load As Placeholder")), placeholder);
}
if (profile_allow_editing) {
menu->add_check_item(TTR("Editable Children"), TOOL_SCENE_EDITABLE_CHILDREN);
menu->add_check_item(TTR("Load As Placeholder"), TOOL_SCENE_USE_PLACEHOLDER);
menu->add_item(TTR("Make Local"), TOOL_SCENE_MAKE_LOCAL);
}

menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN);

if (profile_allow_editing) {
menu->set_item_checked(menu->get_item_idx_from_text(TTR("Editable Children")), editable);
menu->set_item_checked(menu->get_item_idx_from_text(TTR("Load As Placeholder")), placeholder);
}
menu->add_separator();
}
}

if (profile_allow_editing && selection.size() > 1) {
//this is not a commonly used action, it makes no sense for it to be where it was nor always present.
menu->add_separator();
menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
}
menu->add_separator();
// Information Section
menu->add_icon_shortcut(get_icon("CopyNodePath", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
menu->add_icon_item(get_icon("Help", "EditorIcons"), TTR("Open Documentation"), TOOL_OPEN_DOCUMENTATION);
menu->add_separator();

// Destructive operation section
if (profile_allow_editing) {
menu->add_separator();
menu->add_icon_shortcut(get_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
}

// Menu setup
menu->set_size(Size2(1, 1));
menu->set_position(p_menu_pos);
menu->popup();
Expand Down Expand Up @@ -2790,7 +2762,6 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_node_prerenamed"), &SceneTreeDock::_node_prerenamed);
ClassDB::bind_method(D_METHOD("_import_subscene"), &SceneTreeDock::_import_subscene);
ClassDB::bind_method(D_METHOD("_selection_changed"), &SceneTreeDock::_selection_changed);
ClassDB::bind_method(D_METHOD("_node_collapsed"), &SceneTreeDock::_node_collapsed);
ClassDB::bind_method(D_METHOD("_new_scene_from"), &SceneTreeDock::_new_scene_from);
ClassDB::bind_method(D_METHOD("_nodes_dragged"), &SceneTreeDock::_nodes_dragged);
ClassDB::bind_method(D_METHOD("_files_dropped"), &SceneTreeDock::_files_dropped);
Expand Down Expand Up @@ -2831,7 +2802,10 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
ED_SHORTCUT("scene_tree/batch_rename", TTR("Batch Rename"), KEY_MASK_CMD | KEY_F2);
ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KEY_MASK_CMD | KEY_A);
ED_SHORTCUT("scene_tree/instance_scene", TTR("Instance Child Scene"));
ED_SHORTCUT("scene_tree/expand_collapse_all", TTR("Expand/Collapse All"));
ED_SHORTCUT("scene_tree/expand_all", TTR("Expand All"));
ED_SHORTCUT("scene_tree/collapse_all", TTR("Collapse All"));
ED_SHORTCUT("scene_tree/collapse_all_inactive", TTR("Collapse Unselected"));
ED_SHORTCUT("scene_tree/expand_collapse_descendants", TTR("Expand/Collapse Descendants"));
ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type"));
ED_SHORTCUT("scene_tree/attach_script", TTR("Attach Script"));
ED_SHORTCUT("scene_tree/extend_script", TTR("Extend Script"));
Expand Down
Loading