Repository: godotengine/godot (language: cpp)

Issue:
Resource folding causes Resources to be modified even if loaded with `CACHE_MODE_IGNORE`
### Tested versions

4.4

### System information

W10

### Issue description

When you load a Resource in editor with CACHE_MODE_IGNORE, it will cause Resource folding to get loaded via loaded callback:
https://github.com/godotengine/godot/blob/134da374975114ef8e05cf81d1d30eff645e310e/editor/editor_node.cpp#L6706-L6708
Which marks the Resource as edited (the original one, not the one you just loaded):
https://github.com/godotengine/godot/blob/134da374975114ef8e05cf81d1d30eff645e310e/core/object/object.cpp#L1657-L1658
Which makes it subject to external save:
https://github.com/godotengine/godot/blob/134da374975114ef8e05cf81d1d30eff645e310e/editor/editor_node.cpp#L1851-L1854

While it's obvious that it can cause excessive saving, there is a particularly fun case where if you unfold a section, it will cause perpetual saving of that Resource. It happens with scripts:
https://github.com/godotengine/godot/blob/134da374975114ef8e05cf81d1d30eff645e310e/editor/plugins/script_editor_plugin.cpp#L2862-L2866
If Script resource has any section unfolded, it will be marked as edited when folding is loaded, which causes reload dialog to popup (bug) and when you chose to reload the script, the folding gets loaded again, marking the Script as edited and triggering another save etc.

This is the basic principle behind #103236

Ideally folding should not be handled by Object, because it leads to obscure behavior like described above.
Or at least loading folding should not mark the Resource as modified, because it makes no sense.

### Steps to reproduce

See description.

### Minimal reproduction project (MRP)

N/A


Discussion / hints:

Fix patch:
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 8df107ec696b..12d656f90eb6 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1654,8 +1654,11 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) {
 }
 
 #ifdef TOOLS_ENABLED
-void Object::editor_set_section_unfold(const String &p_section, bool p_unfolded) {
-	set_edited(true);
+void Object::editor_set_section_unfold(const String &p_section, bool p_unfolded, bool p_initializing) {
+	if (!p_initializing) {
+		set_edited(true);
+	}
+
 	if (p_unfolded) {
 		editor_section_folding.insert(p_section);
 	} else {
diff --git a/core/object/object.h b/core/object/object.h
index 16d8e19eaa01..c66f24d05d14 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -974,7 +974,7 @@ class Object {
 
 #ifdef TOOLS_ENABLED
 	virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
-	void editor_set_section_unfold(const String &p_section, bool p_unfolded);
+	void editor_set_section_unfold(const String &p_section, bool p_unfolded, bool p_initializing = false);
 	bool editor_is_section_unfolded(const String &p_section);
 	const HashSet<String> &editor_get_section_folding() const { return editor_section_folding; }
 	void editor_clear_section_folding() { editor_section_folding.clear(); }
diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp
index 5cb38fa87519..62f8f53fab62 100644
--- a/editor/editor_folding.cpp
+++ b/editor/editor_folding.cpp
@@ -65,7 +65,7 @@ void EditorFolding::_set_unfolds(Object *p_object, const Vector<String> &p_unfol
 	const String *r = p_unfolds.ptr();
 	p_object->editor_clear_section_folding();
 	for (int i = 0; i < uc; i++) {
-		p_object->editor_set_section_unfold(r[i], true);
+		p_object->editor_set_section_unfold(r[i], true, true);
 	}
 }
 


Test patch: