Browse Source

Merge pull request #91265 from AeioMuch/fix_drop_reparent

Fix reparenting after hover delay
Rémi Verschelde 1 year ago
parent
commit
553f77674c
3 changed files with 33 additions and 8 deletions
  1. 0 1
      editor/gui/scene_tree_editor.h
  2. 30 7
      editor/scene_tree_dock.cpp
  3. 3 0
      editor/scene_tree_dock.h

+ 0 - 1
editor/gui/scene_tree_editor.h

@@ -160,7 +160,6 @@ public:
 
 	void set_marked(const HashSet<Node *> &p_marked, bool p_selectable = true, bool p_children_selectable = true);
 	void set_marked(Node *p_marked, bool p_selectable = true, bool p_children_selectable = true);
-	bool has_marked() const { return !marked.is_empty(); }
 	void set_selected(Node *p_node, bool p_emit_selected = true);
 	Node *get_selected();
 	void set_can_rename(bool p_can_rename) { can_rename = p_can_rename; }

+ 30 - 7
editor/scene_tree_dock.cpp

@@ -76,12 +76,15 @@ void SceneTreeDock::_quick_open() {
 }
 
 void SceneTreeDock::_inspect_hovered_node() {
-	scene_tree->set_selected(node_hovered_now);
-	scene_tree->set_marked(node_hovered_now);
+	select_node_hovered_at_end_of_drag = true;
+	if (tree_item_inspected != nullptr) {
+		tree_item_inspected->clear_custom_color(0);
+	}
 	Tree *tree = scene_tree->get_scene_tree();
-	TreeItem *item = tree->get_item_at_position(tree->get_local_mouse_position());
+	TreeItem *item = tree->get_item_with_metadata(node_hovered_now->get_path());
 	if (item) {
-		item->set_as_cursor(0);
+		tree_item_inspected = item;
+		tree_item_inspected->set_custom_color(0, get_theme_color(SNAME("accent_color"), EditorStringName(Editor)));
 	}
 	InspectorDock::get_inspector_singleton()->edit(node_hovered_now);
 	InspectorDock::get_inspector_singleton()->propagate_notification(NOTIFICATION_DRAG_BEGIN); // Enable inspector drag preview after it updated.
@@ -130,8 +133,8 @@ void SceneTreeDock::input(const Ref<InputEvent> &p_event) {
 		}
 
 		if (mb->is_released()) {
-			if (scene_tree->has_marked()) {
-				scene_tree->set_marked(nullptr);
+			if (tree_item_inspected != nullptr) {
+				tree_item_inspected->clear_custom_color(0);
 			}
 			_reset_hovering_timer();
 		}
@@ -1658,6 +1661,16 @@ void SceneTreeDock::_notification(int p_what) {
 
 		case NOTIFICATION_DRAG_END: {
 			_reset_hovering_timer();
+			if (select_node_hovered_at_end_of_drag && !hovered_but_reparenting) {
+				Node *node_inspected = Object::cast_to<Node>(InspectorDock::get_inspector_singleton()->get_edited_object());
+				if (node_inspected) {
+					editor_selection->clear();
+					editor_selection->add_node(node_inspected);
+					scene_tree->set_selected(node_inspected);
+					select_node_hovered_at_end_of_drag = false;
+				}
+			}
+			hovered_but_reparenting = false;
 		} break;
 	}
 }
@@ -2185,6 +2198,7 @@ void SceneTreeDock::_node_reparent(NodePath p_path, bool p_keep_global_xform) {
 	ERR_FAIL_NULL(new_parent);
 
 	List<Node *> selection = editor_selection->get_selected_node_list();
+	List<Node *> full_selection = editor_selection->get_full_selected_node_list();
 
 	if (selection.is_empty()) {
 		return; // Nothing to reparent.
@@ -2197,6 +2211,10 @@ void SceneTreeDock::_node_reparent(NodePath p_path, bool p_keep_global_xform) {
 	}
 
 	_do_reparent(new_parent, -1, nodes, p_keep_global_xform);
+
+	for (Node *E : full_selection) {
+		editor_selection->add_node(E);
+	}
 }
 
 void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, Vector<Node *> p_nodes, bool p_keep_global_xform) {
@@ -2238,6 +2256,9 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
 		return; // Position and parent didn't change.
 	}
 
+	// Prevent selecting the hovered node and keep the reparented node(s) selected instead.
+	hovered_but_reparenting = true;
+
 	Node *validate = new_parent;
 	while (validate) {
 		ERR_FAIL_COND_MSG(p_nodes.has(validate), "Selection changed at some point. Can't reparent.");
@@ -3400,6 +3421,7 @@ void SceneTreeDock::_nodes_dragged(const Array &p_nodes, NodePath p_to, int p_ty
 	}
 
 	List<Node *> selection = editor_selection->get_selected_node_list();
+	List<Node *> full_selection = editor_selection->get_full_selected_node_list();
 
 	if (selection.is_empty()) {
 		return; //nothing to reparent
@@ -3419,7 +3441,8 @@ void SceneTreeDock::_nodes_dragged(const Array &p_nodes, NodePath p_to, int p_ty
 
 	_normalize_drop(to_node, to_pos, p_type);
 	_do_reparent(to_node, to_pos, nodes, !Input::get_singleton()->is_key_pressed(Key::SHIFT));
-	for (Node *E : nodes) {
+
+	for (Node *E : full_selection) {
 		editor_selection->add_node(E);
 	}
 }

+ 3 - 0
editor/scene_tree_dock.h

@@ -239,8 +239,11 @@ class SceneTreeDock : public VBoxContainer {
 	void _inspect_hovered_node();
 	void _reset_hovering_timer();
 	Timer *inspect_hovered_node_delay = nullptr;
+	TreeItem *tree_item_inspected = nullptr;
 	Node *node_hovered_now = nullptr;
 	Node *node_hovered_previously = nullptr;
+	bool select_node_hovered_at_end_of_drag = false;
+	bool hovered_but_reparenting = false;
 
 	virtual void input(const Ref<InputEvent> &p_event) override;
 	virtual void shortcut_input(const Ref<InputEvent> &p_event) override;