Add an option to center children around the new parent when reparenting

This commit is contained in:
Bitlytic 2023-11-16 20:58:23 -05:00 committed by Rémi Verschelde
parent 28258dfc48
commit f9e03459e8
No known key found for this signature in database
GPG key ID: C3336907360768E1
4 changed files with 60 additions and 0 deletions

View file

@ -220,6 +220,9 @@
<member name="docks/scene_tree/auto_expand_to_selected" type="bool" setter="" getter="">
If [code]true[/code], the scene tree dock will automatically unfold nodes when a node that has folded parents is selected.
</member>
<member name="docks/scene_tree/center_node_on_reparent" type="bool" setter="" getter="">
If [code]true[/code], new node created when reparenting node(s) will be positioned at the average position of the selected node(s).
</member>
<member name="docks/scene_tree/start_create_dialog_fully_expanded" type="bool" setter="" getter="">
If [code]true[/code], the Create dialog (Create New Node/Create New Resource) will start with all its sections expanded. Otherwise, sections will be collapsed until the user starts searching (which will automatically expand sections as needed).
</member>

View file

@ -538,6 +538,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// SceneTree
_initial_set("docks/scene_tree/start_create_dialog_fully_expanded", false);
_initial_set("docks/scene_tree/auto_expand_to_selected", true);
_initial_set("docks/scene_tree/center_node_on_reparent", false);
// FileSystem
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "docks/filesystem/thumbnail_size", 64, "32,128,16")

View file

@ -1059,6 +1059,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
case TOOL_AUTO_EXPAND: {
scene_tree->set_auto_expand_selected(!EDITOR_GET("docks/scene_tree/auto_expand_to_selected"), true);
} break;
case TOOL_CENTER_PARENT: {
EditorSettings::get_singleton()->set("docks/scene_tree/center_node_on_reparent", !EDITOR_GET("docks/scene_tree/center_node_on_reparent"));
} break;
case TOOL_SCENE_EDITABLE_CHILDREN: {
if (!profile_allow_editing) {
break;
@ -2687,6 +2690,9 @@ void SceneTreeDock::_create() {
int smaller_path_to_top = first->get_path_to(scene_root).get_name_count();
Node *top_node = first;
bool center_parent = EDITOR_GET("docks/scene_tree/center_node_on_reparent");
Vector<Node *> top_level_nodes;
for (List<Node *>::Element *E = selection.front()->next(); E; E = E->next()) {
Node *n = E->get();
ERR_FAIL_NULL(n);
@ -2698,10 +2704,17 @@ void SceneTreeDock::_create() {
top_node = n;
smaller_path_to_top = path_length;
only_one_top_node = true;
if (center_parent) {
top_level_nodes.clear();
top_level_nodes.append(n);
}
} else if (smaller_path_to_top == path_length) {
if (only_one_top_node && top_node->get_parent() != n->get_parent()) {
only_one_top_node = false;
}
if (center_parent) {
top_level_nodes.append(n);
}
}
}
}
@ -2722,6 +2735,44 @@ void SceneTreeDock::_create() {
// This works because editor_selection was cleared and populated with last created node in _do_create()
Node *last_created = editor_selection->get_selected_node_list().front()->get();
if (center_parent) {
// Find parent type and only average positions of relevant nodes.
Node3D *parent_node_3d = Object::cast_to<Node3D>(last_created);
if (parent_node_3d) {
Vector3 position;
uint32_t node_count = 0;
for (const Node *node : nodes) {
const Node3D *node_3d = Object::cast_to<Node3D>(node);
if (node_3d) {
position += node_3d->get_global_position();
node_count++;
}
}
if (node_count > 0) {
parent_node_3d->set_global_position(position / node_count);
}
}
Node2D *parent_node_2d = Object::cast_to<Node2D>(last_created);
if (parent_node_2d) {
Vector2 position;
uint32_t node_count = 0;
for (const Node *node : nodes) {
const Node2D *node_2d = Object::cast_to<Node2D>(node);
if (node_2d) {
position += node_2d->get_global_position();
node_count++;
}
}
if (node_count > 0) {
parent_node_2d->set_global_position(position / (real_t)node_count);
}
}
}
_do_reparent(last_created, -1, nodes, true);
}
@ -3446,6 +3497,10 @@ void SceneTreeDock::_update_tree_menu() {
tree_menu->add_check_item(TTR("Auto Expand to Selected"), TOOL_AUTO_EXPAND);
tree_menu->set_item_checked(tree_menu->get_item_index(TOOL_AUTO_EXPAND), EDITOR_GET("docks/scene_tree/auto_expand_to_selected"));
tree_menu->add_check_item(TTR("Center Node on Reparent"), TOOL_CENTER_PARENT);
tree_menu->set_item_checked(tree_menu->get_item_index(TOOL_CENTER_PARENT), EDITOR_GET("docks/scene_tree/center_node_on_reparent"));
tree_menu->set_item_tooltip(tree_menu->get_item_index(TOOL_CENTER_PARENT), TTR("If enabled, Reparent to New Node will create the new node in the center of the selected nodes, if possible."));
PopupMenu *resource_list = memnew(PopupMenu);
resource_list->set_name("AllResources");
resource_list->connect("about_to_popup", callable_mp(this, &SceneTreeDock::_list_all_subresources).bind(resource_list));

View file

@ -94,6 +94,7 @@ class SceneTreeDock : public VBoxContainer {
TOOL_CREATE_3D_SCENE,
TOOL_CREATE_USER_INTERFACE,
TOOL_CREATE_FAVORITE,
TOOL_CENTER_PARENT,
};