Browse Source

Merge pull request #84953 from rakkarage/asset-install-conflict

Fix conflicted indeterminate state in asset importer
Rémi Verschelde 1 year ago
parent
commit
a33a87d535
2 changed files with 41 additions and 13 deletions
  1. 40 12
      editor/editor_asset_installer.cpp
  2. 1 1
      editor/editor_asset_installer.h

+ 40 - 12
editor/editor_asset_installer.cpp

@@ -54,23 +54,51 @@ void EditorAssetInstaller::_item_checked_cbk() {
 	updating_source = true;
 	updating_source = true;
 	TreeItem *item = source_tree->get_edited();
 	TreeItem *item = source_tree->get_edited();
 	item->propagate_check(0);
 	item->propagate_check(0);
+	_fix_conflicted_indeterminate_state(source_tree->get_root(), 0);
 	_update_confirm_button();
 	_update_confirm_button();
 	_rebuild_destination_tree();
 	_rebuild_destination_tree();
 	updating_source = false;
 	updating_source = false;
 }
 }
 
 
-void EditorAssetInstaller::_check_propagated_to_item(Object *p_obj, int p_column) {
-	TreeItem *affected_item = Object::cast_to<TreeItem>(p_obj);
-	if (!affected_item) {
-		return;
+// Determine parent state based on non-conflict children, to avoid indeterminate state, and allow toggle dir with conflicts.
+bool EditorAssetInstaller::_fix_conflicted_indeterminate_state(TreeItem *p_item, int p_column) {
+	if (p_item->get_child_count() == 0) {
+		return false;
 	}
 	}
-
-	Dictionary item_meta = affected_item->get_metadata(0);
-	bool is_conflict = item_meta.get("is_conflict", false);
-	if (is_conflict) {
-		affected_item->set_checked(0, false);
-		affected_item->propagate_check(0, false);
+	bool all_non_conflict_checked = true;
+	bool all_non_conflict_unchecked = true;
+	bool has_conflict_child = false;
+	bool has_indeterminate_child = false;
+	TreeItem *child_item = p_item->get_first_child();
+	while (child_item) {
+		has_conflict_child |= _fix_conflicted_indeterminate_state(child_item, p_column);
+		Dictionary child_meta = child_item->get_metadata(p_column);
+		bool child_conflict = child_meta.get("is_conflict", false);
+		if (child_conflict) {
+			child_item->set_checked(p_column, false);
+			has_conflict_child = true;
+		} else {
+			bool child_checked = child_item->is_checked(p_column);
+			bool child_indeterminate = child_item->is_indeterminate(p_column);
+			all_non_conflict_checked &= (child_checked || child_indeterminate);
+			all_non_conflict_unchecked &= !child_checked;
+			has_indeterminate_child |= child_indeterminate;
+		}
+		child_item = child_item->get_next();
+	}
+	if (has_indeterminate_child) {
+		p_item->set_indeterminate(p_column, true);
+	} else if (all_non_conflict_checked) {
+		p_item->set_checked(p_column, true);
+	} else if (all_non_conflict_unchecked) {
+		p_item->set_checked(p_column, false);
+	}
+	if (has_conflict_child) {
+		p_item->set_custom_color(p_column, get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
+	} else {
+		p_item->clear_custom_color(p_column);
 	}
 	}
+	return has_conflict_child;
 }
 }
 
 
 bool EditorAssetInstaller::_is_item_checked(const String &p_source_path) const {
 bool EditorAssetInstaller::_is_item_checked(const String &p_source_path) const {
@@ -257,6 +285,7 @@ bool EditorAssetInstaller::_update_source_item_status(TreeItem *p_item, const St
 	}
 	}
 
 
 	p_item->propagate_check(0);
 	p_item->propagate_check(0);
+	_fix_conflicted_indeterminate_state(p_item->get_tree()->get_root(), 0);
 	return target_exists;
 	return target_exists;
 }
 }
 
 
@@ -311,6 +340,7 @@ TreeItem *EditorAssetInstaller::_create_dir_item(Tree *p_tree, TreeItem *p_paren
 		ti->set_editable(0, true);
 		ti->set_editable(0, true);
 		ti->set_checked(0, true);
 		ti->set_checked(0, true);
 		ti->propagate_check(0);
 		ti->propagate_check(0);
+		_fix_conflicted_indeterminate_state(ti->get_tree()->get_root(), 0);
 
 
 		Dictionary meta;
 		Dictionary meta;
 		meta["asset_path"] = p_path + "/";
 		meta["asset_path"] = p_path + "/";
@@ -707,7 +737,6 @@ EditorAssetInstaller::EditorAssetInstaller() {
 	source_tree = memnew(Tree);
 	source_tree = memnew(Tree);
 	source_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	source_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	source_tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_checked_cbk));
 	source_tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_checked_cbk));
-	source_tree->connect("check_propagated_to_item", callable_mp(this, &EditorAssetInstaller::_check_propagated_to_item));
 	source_tree_vb->add_child(source_tree);
 	source_tree_vb->add_child(source_tree);
 
 
 	VBoxContainer *destination_tree_vb = memnew(VBoxContainer);
 	VBoxContainer *destination_tree_vb = memnew(VBoxContainer);
@@ -722,7 +751,6 @@ EditorAssetInstaller::EditorAssetInstaller() {
 	destination_tree = memnew(Tree);
 	destination_tree = memnew(Tree);
 	destination_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	destination_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	destination_tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_checked_cbk));
 	destination_tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_checked_cbk));
-	destination_tree->connect("check_propagated_to_item", callable_mp(this, &EditorAssetInstaller::_check_propagated_to_item));
 	destination_tree_vb->add_child(destination_tree);
 	destination_tree_vb->add_child(destination_tree);
 
 
 	// Dialog configuration.
 	// Dialog configuration.

+ 1 - 1
editor/editor_asset_installer.h

@@ -88,7 +88,7 @@ class EditorAssetInstaller : public ConfirmationDialog {
 	void _toggle_source_tree(bool p_visible, bool p_scroll_to_error = false);
 	void _toggle_source_tree(bool p_visible, bool p_scroll_to_error = false);
 
 
 	void _item_checked_cbk();
 	void _item_checked_cbk();
-	void _check_propagated_to_item(Object *p_obj, int p_column);
+	bool _fix_conflicted_indeterminate_state(TreeItem *p_item, int p_column);
 	bool _is_item_checked(const String &p_source_path) const;
 	bool _is_item_checked(const String &p_source_path) const;
 
 
 	void _install_asset();
 	void _install_asset();