Просмотр исходного кода

Merge pull request #60166 from bruvzg/narrow_file_access

Rémi Verschelde 3 лет назад
Родитель
Сommit
f586e06f7b

+ 1 - 1
core/core_bind.cpp

@@ -1088,7 +1088,7 @@ void File::flush() {
 
 void File::close() {
 	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened.");
-	f = Ref<FileAccess>();
+	f.unref();
 }
 
 bool File::is_open() const {

+ 22 - 20
core/io/dir_access.cpp

@@ -275,27 +275,29 @@ String DirAccess::get_full_path(const String &p_path, AccessType p_access) {
 Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
 	//printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data());
 	Error err;
-	Ref<FileAccess> fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_from);
-
-	Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to);
-
-	fsrc->seek_end(0);
-	int size = fsrc->get_position();
-	fsrc->seek(0);
-	err = OK;
-	while (size--) {
-		if (fsrc->get_error() != OK) {
-			err = fsrc->get_error();
-			break;
-		}
-		if (fdst->get_error() != OK) {
-			err = fdst->get_error();
-			break;
-		}
+	{
+		Ref<FileAccess> fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_from);
+
+		Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to);
+
+		fsrc->seek_end(0);
+		int size = fsrc->get_position();
+		fsrc->seek(0);
+		err = OK;
+		while (size--) {
+			if (fsrc->get_error() != OK) {
+				err = fsrc->get_error();
+				break;
+			}
+			if (fdst->get_error() != OK) {
+				err = fdst->get_error();
+				break;
+			}
 
-		fdst->store_8(fsrc->get_8());
+			fdst->store_8(fsrc->get_8());
+		}
 	}
 
 	if (err == OK && p_chmod_flags != -1) {

+ 1 - 1
core/io/file_access.cpp

@@ -105,7 +105,7 @@ Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error *
 		*r_error = err;
 	}
 	if (err != OK) {
-		ret = Ref<FileAccess>();
+		ret.unref();
 	}
 
 	return ret;

+ 4 - 4
core/io/file_access_compressed.cpp

@@ -63,7 +63,7 @@ Error FileAccessCompressed::open_after_magic(Ref<FileAccess> p_base) {
 	cmode = (Compression::Mode)f->get_32();
 	block_size = f->get_32();
 	if (block_size == 0) {
-		f = Ref<FileAccess>();
+		f.unref();
 		ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted.");
 	}
 	read_total = f->get_32();
@@ -106,7 +106,7 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
 	f = FileAccess::open(p_path, p_mode_flags, &err);
 	if (err != OK) {
 		//not openable
-		f = Ref<FileAccess>();
+		f.unref();
 		return err;
 	}
 
@@ -126,7 +126,7 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
 		rmagic[4] = 0;
 		err = ERR_FILE_UNRECOGNIZED;
 		if (magic != rmagic || (err = open_after_magic(f)) != OK) {
-			f = Ref<FileAccess>();
+			f.unref();
 			return err;
 		}
 	}
@@ -180,7 +180,7 @@ void FileAccessCompressed::close() {
 		buffer.clear();
 		read_blocks.clear();
 	}
-	f = Ref<FileAccess>();
+	f.unref();
 }
 
 bool FileAccessCompressed::is_open() const {

+ 2 - 4
core/io/file_access_encrypted.cpp

@@ -122,9 +122,7 @@ void FileAccessEncrypted::close() {
 
 	_release();
 
-	file->close();
-
-	file = Ref<FileAccess>();
+	file.unref();
 }
 
 void FileAccessEncrypted::release() {
@@ -134,7 +132,7 @@ void FileAccessEncrypted::release() {
 
 	_release();
 
-	file = Ref<FileAccess>();
+	file.unref();
 }
 
 void FileAccessEncrypted::_release() {

+ 12 - 2
core/io/file_access_pack.cpp

@@ -227,14 +227,20 @@ Error FileAccessPack::_open(const String &p_path, int p_mode_flags) {
 }
 
 void FileAccessPack::close() {
-	f->close();
+	f.unref();
 }
 
 bool FileAccessPack::is_open() const {
-	return f->is_open();
+	if (f.is_valid()) {
+		return f->is_open();
+	} else {
+		return false;
+	}
 }
 
 void FileAccessPack::seek(uint64_t p_position) {
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
+
 	if (p_position > pf.size) {
 		eof = true;
 	} else {
@@ -262,6 +268,7 @@ bool FileAccessPack::eof_reached() const {
 }
 
 uint8_t FileAccessPack::get_8() const {
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
 	if (pos >= pf.size) {
 		eof = true;
 		return 0;
@@ -272,6 +279,7 @@ uint8_t FileAccessPack::get_8() const {
 }
 
 uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
+	ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
 	ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
 
 	if (eof) {
@@ -295,6 +303,8 @@ uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
 }
 
 void FileAccessPack::set_big_endian(bool p_big_endian) {
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
+
 	FileAccess::set_big_endian(p_big_endian);
 	f->set_big_endian(p_big_endian);
 }

+ 1 - 1
core/io/logger.cpp

@@ -148,7 +148,7 @@ void RotatedFileLogger::clear_old_backups() {
 }
 
 void RotatedFileLogger::rotate_file() {
-	file = Ref<FileAccess>();
+	file.unref();
 
 	if (FileAccess::exists(base_path)) {
 		if (max_files > 1) {

+ 2 - 2
core/io/pck_packer.cpp

@@ -216,7 +216,7 @@ Error PCKPacker::flush(bool p_verbose) {
 		Ref<FileAccess> src = FileAccess::open(files[i].src_path, FileAccess::READ);
 		uint64_t to_write = files[i].size;
 
-		fae = Ref<FileAccess>();
+		fae.unref();
 		Ref<FileAccess> ftmp = file;
 		if (files[i].encrypted) {
 			fae.instantiate();
@@ -253,7 +253,7 @@ Error PCKPacker::flush(bool p_verbose) {
 		printf("\n");
 	}
 
-	file = Ref<FileAccess>();
+	file.unref();
 	memdelete_arr(buf);
 
 	return OK;

+ 8 - 7
core/io/resource_format_binary.cpp

@@ -789,7 +789,7 @@ Error ResourceLoaderBinary::load() {
 		resource_cache.push_back(res);
 
 		if (main) {
-			f = Ref<FileAccess>();
+			f.unref();
 			resource = res;
 			resource->set_as_translation_remapped(translation_remapped);
 			error = OK;
@@ -868,7 +868,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
 		fac.instantiate();
 		error = fac->open_after_magic(f);
 		if (error != OK) {
-			f = Ref<FileAccess>();
+			f.unref();
 			ERR_FAIL_MSG("Failed to open binary resource file: " + local_path + ".");
 		}
 		f = fac;
@@ -876,7 +876,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 		// Not normal.
 		error = ERR_FILE_UNRECOGNIZED;
-		f = Ref<FileAccess>();
+		f.unref();
 		ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + ".");
 	}
 
@@ -901,7 +901,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
 	print_bl("format: " + itos(ver_format));
 
 	if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
-		f = Ref<FileAccess>();
+		f.unref();
 		ERR_FAIL_MSG(vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).",
 				local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH));
 	}
@@ -978,6 +978,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
 
 	if (f->eof_reached()) {
 		error = ERR_FILE_CORRUPT;
+		f.unref();
 		ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + ".");
 	}
 }
@@ -994,7 +995,7 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) {
 		fac.instantiate();
 		error = fac->open_after_magic(f);
 		if (error != OK) {
-			f = Ref<FileAccess>();
+			f.unref();
 			return "";
 		}
 		f = fac;
@@ -1002,7 +1003,7 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) {
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 		// Not normal.
 		error = ERR_FILE_UNRECOGNIZED;
-		f = Ref<FileAccess>();
+		f.unref();
 		return "";
 	}
 
@@ -1016,7 +1017,7 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) {
 	uint32_t ver_format = f->get_32();
 
 	if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
-		f = Ref<FileAccess>();
+		f.unref();
 		return "";
 	}
 

+ 1 - 1
core/io/resource_uid.cpp

@@ -220,7 +220,7 @@ Error ResourceUID::update_cache() {
 		}
 	}
 
-	if (f != nullptr) {
+	if (f.is_valid()) {
 		f->seek(0);
 		f->store_32(cache_entries); //update amount of entries
 	}

+ 2 - 2
core/os/os.cpp

@@ -201,14 +201,14 @@ void OS::print_all_resources(String p_to_file) {
 		Error err;
 		_OSPRF = FileAccess::open(p_to_file, FileAccess::WRITE, &err);
 		if (err != OK) {
-			_OSPRF = Ref<FileAccess>();
+			_OSPRF.unref();
 			ERR_FAIL_MSG("Can't print all resources to file: " + String(p_to_file) + ".");
 		}
 	}
 
 	ObjectDB::debug_objects(_OS_printres);
 
-	_OSPRF = Ref<FileAccess>();
+	_OSPRF.unref();
 }
 
 void OS::print_resources_in_use(bool p_short) {

+ 26 - 22
editor/create_dialog.cpp

@@ -377,13 +377,15 @@ void CreateDialog::_confirmed() {
 		return;
 	}
 
-	Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
-	if (f.is_valid()) {
-		f->store_line(selected_item);
-
-		for (int i = 0; i < MIN(32, recent->get_item_count()); i++) {
-			if (recent->get_item_text(i) != selected_item) {
-				f->store_line(recent->get_item_text(i));
+	{
+		Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
+		if (f.is_valid()) {
+			f->store_line(selected_item);
+
+			for (int i = 0; i < MIN(32, recent->get_item_count()); i++) {
+				if (recent->get_item_text(i) != selected_item) {
+					f->store_line(recent->get_item_text(i));
+				}
 			}
 		}
 	}
@@ -645,23 +647,25 @@ void CreateDialog::_save_and_update_favorite_list() {
 	favorites->clear();
 	TreeItem *root = favorites->create_item();
 
-	Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
-	if (f.is_valid()) {
-		for (int i = 0; i < favorite_list.size(); i++) {
-			String l = favorite_list[i];
-			String name = l.get_slicec(' ', 0);
-			if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) {
-				continue;
-			}
-			f->store_line(l);
+	{
+		Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
+		if (f.is_valid()) {
+			for (int i = 0; i < favorite_list.size(); i++) {
+				String l = favorite_list[i];
+				String name = l.get_slicec(' ', 0);
+				if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) {
+					continue;
+				}
+				f->store_line(l);
 
-			if (_is_class_disabled_by_feature_profile(name)) {
-				continue;
-			}
+				if (_is_class_disabled_by_feature_profile(name)) {
+					continue;
+				}
 
-			TreeItem *ti = favorites->create_item(root);
-			ti->set_text(0, l);
-			ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
+				TreeItem *ti = favorites->create_item(root);
+				ti->set_text(0, l);
+				ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
+			}
 		}
 	}
 

+ 6 - 0
editor/editor_export.cpp

@@ -1142,6 +1142,10 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 
 	Error err = export_project_files(p_preset, p_debug, _save_pack_file, &pd, _add_shared_object);
 
+	// Close temp file.
+	pd.f.unref();
+	ftmp.unref();
+
 	if (err != OK) {
 		DirAccess::remove_file_or_error(tmppath);
 		ERR_PRINT("Failed to export project files");
@@ -1301,6 +1305,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 		f->store_buffer(buf, got);
 	}
 
+	ftmp.unref(); // Close temp file.
+
 	if (p_embed) {
 		// Ensure embedded data ends at a 64-bit multiple
 		uint64_t embed_end = f->get_position() - embed_pos + 12;

+ 190 - 182
editor/editor_file_system.cpp

@@ -218,69 +218,71 @@ void EditorFileSystem::_scan_filesystem() {
 	String project = ProjectSettings::get_singleton()->get_resource_path();
 
 	String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
-	Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ);
-
-	bool first = true;
-	if (f.is_valid()) {
-		//read the disk cache
-		while (!f->eof_reached()) {
-			String l = f->get_line().strip_edges();
-			if (first) {
-				if (first_scan) {
-					// only use this on first scan, afterwards it gets ignored
-					// this is so on first reimport we synchronize versions, then
-					// we don't care until editor restart. This is for usability mainly so
-					// your workflow is not killed after changing a setting by forceful reimporting
-					// everything there is.
-					filesystem_settings_version_for_import = l.strip_edges();
-					if (filesystem_settings_version_for_import != ResourceFormatImporter::get_singleton()->get_import_settings_hash()) {
-						revalidate_import_files = true;
+	{
+		Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ);
+
+		bool first = true;
+		if (f.is_valid()) {
+			//read the disk cache
+			while (!f->eof_reached()) {
+				String l = f->get_line().strip_edges();
+				if (first) {
+					if (first_scan) {
+						// only use this on first scan, afterwards it gets ignored
+						// this is so on first reimport we synchronize versions, then
+						// we don't care until editor restart. This is for usability mainly so
+						// your workflow is not killed after changing a setting by forceful reimporting
+						// everything there is.
+						filesystem_settings_version_for_import = l.strip_edges();
+						if (filesystem_settings_version_for_import != ResourceFormatImporter::get_singleton()->get_import_settings_hash()) {
+							revalidate_import_files = true;
+						}
 					}
+					first = false;
+					continue;
+				}
+				if (l.is_empty()) {
+					continue;
 				}
-				first = false;
-				continue;
-			}
-			if (l.is_empty()) {
-				continue;
-			}
 
-			if (l.begins_with("::")) {
-				Vector<String> split = l.split("::");
-				ERR_CONTINUE(split.size() != 3);
-				String name = split[1];
+				if (l.begins_with("::")) {
+					Vector<String> split = l.split("::");
+					ERR_CONTINUE(split.size() != 3);
+					String name = split[1];
 
-				cpath = name;
+					cpath = name;
 
-			} else {
-				Vector<String> split = l.split("::");
-				ERR_CONTINUE(split.size() != 9);
-				String name = split[0];
-				String file;
-
-				file = name;
-				name = cpath.plus_file(name);
-
-				FileCache fc;
-				fc.type = split[1];
-				fc.uid = split[2].to_int();
-				fc.modification_time = split[3].to_int();
-				fc.import_modification_time = split[4].to_int();
-				fc.import_valid = split[5].to_int() != 0;
-				fc.import_group_file = split[6].strip_edges();
-				fc.script_class_name = split[7].get_slice("<>", 0);
-				fc.script_class_extends = split[7].get_slice("<>", 1);
-				fc.script_class_icon_path = split[7].get_slice("<>", 2);
-
-				String deps = split[8].strip_edges();
-				if (deps.length()) {
-					Vector<String> dp = deps.split("<>");
-					for (int i = 0; i < dp.size(); i++) {
-						String path = dp[i];
-						fc.deps.push_back(path);
+				} else {
+					Vector<String> split = l.split("::");
+					ERR_CONTINUE(split.size() != 9);
+					String name = split[0];
+					String file;
+
+					file = name;
+					name = cpath.plus_file(name);
+
+					FileCache fc;
+					fc.type = split[1];
+					fc.uid = split[2].to_int();
+					fc.modification_time = split[3].to_int();
+					fc.import_modification_time = split[4].to_int();
+					fc.import_valid = split[5].to_int() != 0;
+					fc.import_group_file = split[6].strip_edges();
+					fc.script_class_name = split[7].get_slice("<>", 0);
+					fc.script_class_extends = split[7].get_slice("<>", 1);
+					fc.script_class_icon_path = split[7].get_slice("<>", 2);
+
+					String deps = split[8].strip_edges();
+					if (deps.length()) {
+						Vector<String> dp = deps.split("<>");
+						for (int i = 0; i < dp.size(); i++) {
+							String path = dp[i];
+							fc.deps.push_back(path);
+						}
 					}
-				}
 
-				file_cache[name] = fc;
+					file_cache[name] = fc;
+				}
 			}
 		}
 	}
@@ -1700,74 +1702,77 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
 	for (const KeyValue<String, Map<StringName, Variant>> &E : source_file_options) {
 		const String &file = E.key;
 		String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(file);
-		Ref<FileAccess> f = FileAccess::open(file + ".import", FileAccess::WRITE);
-		ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'.");
-
-		//write manually, as order matters ([remap] has to go first for performance).
-		f->store_line("[remap]");
-		f->store_line("");
-		f->store_line("importer=\"" + importer->get_importer_name() + "\"");
-		int version = importer->get_format_version();
-		if (version > 0) {
-			f->store_line("importer_version=" + itos(version));
-		}
-		if (!importer->get_resource_type().is_empty()) {
-			f->store_line("type=\"" + importer->get_resource_type() + "\"");
-		}
-
 		Vector<String> dest_paths;
+		{
+			Ref<FileAccess> f = FileAccess::open(file + ".import", FileAccess::WRITE);
+			ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'.");
+
+			//write manually, as order matters ([remap] has to go first for performance).
+			f->store_line("[remap]");
+			f->store_line("");
+			f->store_line("importer=\"" + importer->get_importer_name() + "\"");
+			int version = importer->get_format_version();
+			if (version > 0) {
+				f->store_line("importer_version=" + itos(version));
+			}
+			if (!importer->get_resource_type().is_empty()) {
+				f->store_line("type=\"" + importer->get_resource_type() + "\"");
+			}
 
-		if (err == OK) {
-			String path = base_path + "." + importer->get_save_extension();
-			f->store_line("path=\"" + path + "\"");
-			dest_paths.push_back(path);
-		}
-
-		f->store_line("group_file=" + Variant(p_group_file).get_construct_string());
-
-		if (err == OK) {
-			f->store_line("valid=true");
-		} else {
-			f->store_line("valid=false");
-		}
-		f->store_line("[deps]\n");
+			if (err == OK) {
+				String path = base_path + "." + importer->get_save_extension();
+				f->store_line("path=\"" + path + "\"");
+				dest_paths.push_back(path);
+			}
 
-		f->store_line("");
+			f->store_line("group_file=" + Variant(p_group_file).get_construct_string());
 
-		f->store_line("source_file=" + Variant(file).get_construct_string());
-		if (dest_paths.size()) {
-			Array dp;
-			for (int i = 0; i < dest_paths.size(); i++) {
-				dp.push_back(dest_paths[i]);
+			if (err == OK) {
+				f->store_line("valid=true");
+			} else {
+				f->store_line("valid=false");
 			}
-			f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
-		}
-		f->store_line("[params]");
-		f->store_line("");
+			f->store_line("[deps]\n");
 
-		//store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
+			f->store_line("");
 
-		List<ResourceImporter::ImportOption> options;
-		importer->get_import_options(file, &options);
-		//set default values
-		for (const ResourceImporter::ImportOption &F : options) {
-			String base = F.option.name;
-			Variant v = F.default_value;
-			if (source_file_options[file].has(base)) {
-				v = source_file_options[file][base];
+			f->store_line("source_file=" + Variant(file).get_construct_string());
+			if (dest_paths.size()) {
+				Array dp;
+				for (int i = 0; i < dest_paths.size(); i++) {
+					dp.push_back(dest_paths[i]);
+				}
+				f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
+			}
+			f->store_line("[params]");
+			f->store_line("");
+
+			//store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
+
+			List<ResourceImporter::ImportOption> options;
+			importer->get_import_options(file, &options);
+			//set default values
+			for (const ResourceImporter::ImportOption &F : options) {
+				String base = F.option.name;
+				Variant v = F.default_value;
+				if (source_file_options[file].has(base)) {
+					v = source_file_options[file][base];
+				}
+				String value;
+				VariantWriter::write_to_string(v, value);
+				f->store_line(base + "=" + value);
 			}
-			String value;
-			VariantWriter::write_to_string(v, value);
-			f->store_line(base + "=" + value);
 		}
 
 		// Store the md5's of the various files. These are stored separately so that the .import files can be version controlled.
-		Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
-		ERR_FAIL_COND_V_MSG(md5s.is_null(), ERR_FILE_CANT_OPEN, "Cannot open MD5 file '" + base_path + ".md5'.");
+		{
+			Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
+			ERR_FAIL_COND_V_MSG(md5s.is_null(), ERR_FILE_CANT_OPEN, "Cannot open MD5 file '" + base_path + ".md5'.");
 
-		md5s->store_line("source_md5=\"" + FileAccess::get_md5(file) + "\"");
-		if (dest_paths.size()) {
-			md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+			md5s->store_line("source_md5=\"" + FileAccess::get_md5(file) + "\"");
+			if (dest_paths.size()) {
+				md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+			}
 		}
 
 		EditorFileSystemDirectory *fs = nullptr;
@@ -1914,100 +1919,103 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
 
 	//as import is complete, save the .import file
 
-	Ref<FileAccess> f = FileAccess::open(p_file + ".import", FileAccess::WRITE);
-	ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file from path '" + p_file + ".import'.");
-
-	//write manually, as order matters ([remap] has to go first for performance).
-	f->store_line("[remap]");
-	f->store_line("");
-	f->store_line("importer=\"" + importer->get_importer_name() + "\"");
-	int version = importer->get_format_version();
-	if (version > 0) {
-		f->store_line("importer_version=" + itos(version));
-	}
-	if (!importer->get_resource_type().is_empty()) {
-		f->store_line("type=\"" + importer->get_resource_type() + "\"");
-	}
-
-	if (uid == ResourceUID::INVALID_ID) {
-		uid = ResourceUID::get_singleton()->create_id();
-	}
+	Vector<String> dest_paths;
+	{
+		Ref<FileAccess> f = FileAccess::open(p_file + ".import", FileAccess::WRITE);
+		ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file from path '" + p_file + ".import'.");
 
-	f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format
+		//write manually, as order matters ([remap] has to go first for performance).
+		f->store_line("[remap]");
+		f->store_line("");
+		f->store_line("importer=\"" + importer->get_importer_name() + "\"");
+		int version = importer->get_format_version();
+		if (version > 0) {
+			f->store_line("importer_version=" + itos(version));
+		}
+		if (!importer->get_resource_type().is_empty()) {
+			f->store_line("type=\"" + importer->get_resource_type() + "\"");
+		}
 
-	Vector<String> dest_paths;
+		if (uid == ResourceUID::INVALID_ID) {
+			uid = ResourceUID::get_singleton()->create_id();
+		}
 
-	if (err == OK) {
-		if (importer->get_save_extension().is_empty()) {
-			//no path
-		} else if (import_variants.size()) {
-			//import with variants
-			for (const String &E : import_variants) {
-				String path = base_path.c_escape() + "." + E + "." + importer->get_save_extension();
+		f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format
 
-				f->store_line("path." + E + "=\"" + path + "\"");
+		if (err == OK) {
+			if (importer->get_save_extension().is_empty()) {
+				//no path
+			} else if (import_variants.size()) {
+				//import with variants
+				for (const String &E : import_variants) {
+					String path = base_path.c_escape() + "." + E + "." + importer->get_save_extension();
+
+					f->store_line("path." + E + "=\"" + path + "\"");
+					dest_paths.push_back(path);
+				}
+			} else {
+				String path = base_path + "." + importer->get_save_extension();
+				f->store_line("path=\"" + path + "\"");
 				dest_paths.push_back(path);
 			}
+
 		} else {
-			String path = base_path + "." + importer->get_save_extension();
-			f->store_line("path=\"" + path + "\"");
-			dest_paths.push_back(path);
+			f->store_line("valid=false");
 		}
 
-	} else {
-		f->store_line("valid=false");
-	}
+		if (metadata != Variant()) {
+			f->store_line("metadata=" + metadata.get_construct_string());
+		}
 
-	if (metadata != Variant()) {
-		f->store_line("metadata=" + metadata.get_construct_string());
-	}
+		f->store_line("");
 
-	f->store_line("");
+		f->store_line("[deps]\n");
 
-	f->store_line("[deps]\n");
+		if (gen_files.size()) {
+			Array genf;
+			for (const String &E : gen_files) {
+				genf.push_back(E);
+				dest_paths.push_back(E);
+			}
 
-	if (gen_files.size()) {
-		Array genf;
-		for (const String &E : gen_files) {
-			genf.push_back(E);
-			dest_paths.push_back(E);
+			String value;
+			VariantWriter::write_to_string(genf, value);
+			f->store_line("files=" + value);
+			f->store_line("");
 		}
 
-		String value;
-		VariantWriter::write_to_string(genf, value);
-		f->store_line("files=" + value);
-		f->store_line("");
-	}
+		f->store_line("source_file=" + Variant(p_file).get_construct_string());
 
-	f->store_line("source_file=" + Variant(p_file).get_construct_string());
-
-	if (dest_paths.size()) {
-		Array dp;
-		for (int i = 0; i < dest_paths.size(); i++) {
-			dp.push_back(dest_paths[i]);
+		if (dest_paths.size()) {
+			Array dp;
+			for (int i = 0; i < dest_paths.size(); i++) {
+				dp.push_back(dest_paths[i]);
+			}
+			f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
 		}
-		f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
-	}
 
-	f->store_line("[params]");
-	f->store_line("");
+		f->store_line("[params]");
+		f->store_line("");
 
-	//store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
+		//store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
 
-	for (const ResourceImporter::ImportOption &E : opts) {
-		String base = E.option.name;
-		String value;
-		VariantWriter::write_to_string(params[base], value);
-		f->store_line(base + "=" + value);
+		for (const ResourceImporter::ImportOption &E : opts) {
+			String base = E.option.name;
+			String value;
+			VariantWriter::write_to_string(params[base], value);
+			f->store_line(base + "=" + value);
+		}
 	}
 
 	// Store the md5's of the various files. These are stored separately so that the .import files can be version controlled.
-	Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
-	ERR_FAIL_COND_MSG(md5s.is_null(), "Cannot open MD5 file '" + base_path + ".md5'.");
+	{
+		Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
+		ERR_FAIL_COND_MSG(md5s.is_null(), "Cannot open MD5 file '" + base_path + ".md5'.");
 
-	md5s->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\"");
-	if (dest_paths.size()) {
-		md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+		md5s->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\"");
+		if (dest_paths.size()) {
+			md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+		}
 	}
 
 	//update modified times, to avoid reimport

+ 10 - 7
editor/editor_resource_preview.cpp

@@ -263,28 +263,31 @@ void EditorResourcePreview::_iterate() {
 
 					if (tsize != thumbnail_size) {
 						cache_valid = false;
+						f.unref();
 					} else if (last_modtime != modtime) {
 						String last_md5 = f->get_line();
 						String md5 = FileAccess::get_md5(item.path);
+						f.unref();
 
 						if (last_md5 != md5) {
 							cache_valid = false;
-
 						} else {
 							//update modified time
 
-							f = FileAccess::open(file, FileAccess::WRITE);
-							if (f.is_null()) {
+							Ref<FileAccess> f2 = FileAccess::open(file, FileAccess::WRITE);
+							if (f2.is_null()) {
 								// Not returning as this would leave the thread hanging and would require
 								// some proper cleanup/disabling of resource preview generation.
 								ERR_PRINT("Cannot create file '" + file + "'. Check user write permissions.");
 							} else {
-								f->store_line(itos(thumbnail_size));
-								f->store_line(itos(has_small_texture));
-								f->store_line(itos(modtime));
-								f->store_line(md5);
+								f2->store_line(itos(thumbnail_size));
+								f2->store_line(itos(has_small_texture));
+								f2->store_line(itos(modtime));
+								f2->store_line(md5);
 							}
 						}
+					} else {
+						f.unref();
 					}
 
 					if (cache_valid) {

+ 2 - 1
editor/export_template_manager.cpp

@@ -514,7 +514,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
 		}
 
 		f->store_buffer(data.ptr(), data.size());
-
+		f.unref(); // close file.
 #ifndef WINDOWS_ENABLED
 		FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF);
 #endif
@@ -728,6 +728,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
 			Ref<FileAccess> f = FileAccess::open(to_write, FileAccess::WRITE);
 			if (f.is_valid()) {
 				f->store_buffer(data.ptr(), data.size());
+				f.unref(); // close file.
 #ifndef WINDOWS_ENABLED
 				FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF);
 #endif

+ 13 - 9
editor/plugins/script_editor_plugin.cpp

@@ -1091,10 +1091,12 @@ void ScriptEditor::_file_dialog_action(String p_file) {
 	switch (file_dialog_option) {
 		case FILE_NEW_TEXTFILE: {
 			Error err;
-			Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
-			if (err) {
-				EditorNode::get_singleton()->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!"));
-				break;
+			{
+				Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+				if (err) {
+					EditorNode::get_singleton()->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!"));
+					break;
+				}
 			}
 
 			if (EditorFileSystem::get_singleton()) {
@@ -2209,13 +2211,15 @@ Error ScriptEditor::_save_text_file(Ref<TextFile> p_text_file, const String &p_p
 	String source = sqscr->get_text();
 
 	Error err;
-	Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+	{
+		Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
 
-	ERR_FAIL_COND_V_MSG(err, err, "Cannot save text file '" + p_path + "'.");
+		ERR_FAIL_COND_V_MSG(err, err, "Cannot save text file '" + p_path + "'.");
 
-	file->store_string(source);
-	if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
-		return ERR_CANT_CREATE;
+		file->store_string(source);
+		if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+			return ERR_CANT_CREATE;
+		}
 	}
 
 	if (ResourceSaver::get_timestamp_on_save()) {

+ 8 - 6
modules/gdscript/gdscript.cpp

@@ -2353,14 +2353,16 @@ Error ResourceFormatSaverGDScript::save(const String &p_path, const RES &p_resou
 
 	String source = sqscr->get_source_code();
 
-	Error err;
-	Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+	{
+		Error err;
+		Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
 
-	ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'.");
+		ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'.");
 
-	file->store_string(source);
-	if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
-		return ERR_CANT_CREATE;
+		file->store_string(source);
+		if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+			return ERR_CANT_CREATE;
+		}
 	}
 
 	if (ScriptServer::is_reload_scripts_on_save_enabled()) {

+ 8 - 6
modules/mono/csharp_script.cpp

@@ -3641,14 +3641,16 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r
 	}
 #endif
 
-	Error err;
-	Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'.");
+	{
+		Error err;
+		Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'.");
 
-	file->store_string(source);
+		file->store_string(source);
 
-	if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
-		return ERR_CANT_CREATE;
+		if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+			return ERR_CANT_CREATE;
+		}
 	}
 
 #ifdef TOOLS_ENABLED

+ 4 - 6
modules/mono/mono_gd/gd_mono_log.cpp

@@ -77,22 +77,20 @@ static String make_text(const char *log_domain, const char *log_level, const cha
 }
 
 void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *) {
-	Ref<FileAccess> f = GDMonoLog::get_singleton()->log_file;
-
 	if (GDMonoLog::get_singleton()->log_level_id >= get_log_level_id(log_level)) {
 		String text = make_text(log_domain, log_level, message);
 		text += "\n";
 
-		f->seek_end();
-		f->store_string(text);
+		GDMonoLog::get_singleton()->log_file->seek_end();
+		GDMonoLog::get_singleton()->log_file->store_string(text);
 	}
 
 	if (fatal) {
 		String text = make_text(log_domain, log_level, message);
 		ERR_PRINT("Mono: FATAL ERROR '" + text + "', ABORTING! Logfile: '" + GDMonoLog::get_singleton()->log_file_path + "'.");
 		// Make sure to flush before aborting
-		f->flush();
-		f->close();
+		GDMonoLog::get_singleton()->log_file->flush();
+		GDMonoLog::get_singleton()->log_file.unref();
 
 		abort();
 	}

+ 1 - 1
modules/theora/video_stream_theora.cpp

@@ -152,7 +152,7 @@ void VideoStreamPlaybackTheora::clear() {
 	theora_eos = false;
 	vorbis_eos = false;
 
-	file = Ref<FileAccess>();
+	file.unref();
 	playing = false;
 };
 

+ 17 - 13
platform/iphone/export/export_plugin.cpp

@@ -1570,13 +1570,15 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
 			}
 
 			/* write the file */
-			Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE);
-			if (f.is_null()) {
-				ERR_PRINT("Can't write '" + file + "'.");
-				unzClose(src_pkg_zip);
-				return ERR_CANT_CREATE;
-			};
-			f->store_buffer(data.ptr(), data.size());
+			{
+				Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE);
+				if (f.is_null()) {
+					ERR_PRINT("Can't write '" + file + "'.");
+					unzClose(src_pkg_zip);
+					return ERR_CANT_CREATE;
+				};
+				f->store_buffer(data.ptr(), data.size());
+			}
 
 #if defined(OSX_ENABLED) || defined(X11_ENABLED)
 			if (is_execute) {
@@ -1714,12 +1716,14 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
 	_export_additional_assets(dest_dir + binary_name, libraries, assets);
 	_add_assets_to_project(p_preset, project_file_data, assets);
 	String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj";
-	Ref<FileAccess> f = FileAccess::open(project_file_name, FileAccess::WRITE);
-	if (f.is_null()) {
-		ERR_PRINT("Can't write '" + project_file_name + "'.");
-		return ERR_CANT_CREATE;
-	};
-	f->store_buffer(project_file_data.ptr(), project_file_data.size());
+	{
+		Ref<FileAccess> f = FileAccess::open(project_file_name, FileAccess::WRITE);
+		if (f.is_null()) {
+			ERR_PRINT("Can't write '" + project_file_name + "'.");
+			return ERR_CANT_CREATE;
+		};
+		f->store_buffer(project_file_data.ptr(), project_file_data.size());
+	}
 
 #ifdef OSX_ENABLED
 	{

+ 8 - 6
platform/javascript/api/javascript_tools_editor_plugin.cpp

@@ -81,12 +81,14 @@ void JavaScriptToolsEditorPlugin::_download_zip(Variant p_v) {
 	const String base_path = resource_path.substr(0, resource_path.rfind("/")) + "/";
 	_zip_recursive(resource_path, base_path, zip);
 	zipClose(zip, nullptr);
-	Ref<FileAccess> f = FileAccess::open(output_path, FileAccess::READ);
-	ERR_FAIL_COND_MSG(f.is_null(), "Unable to create ZIP file.");
-	Vector<uint8_t> buf;
-	buf.resize(f->get_length());
-	f->get_buffer(buf.ptrw(), buf.size());
-	godot_js_os_download_buffer(buf.ptr(), buf.size(), output_name.utf8().get_data(), "application/zip");
+	{
+		Ref<FileAccess> f = FileAccess::open(output_path, FileAccess::READ);
+		ERR_FAIL_COND_MSG(f.is_null(), "Unable to create ZIP file.");
+		Vector<uint8_t> buf;
+		buf.resize(f->get_length());
+		f->get_buffer(buf.ptrw(), buf.size());
+		godot_js_os_download_buffer(buf.ptr(), buf.size(), output_name.utf8().get_data(), "application/zip");
+	}
 
 	// Remove the temporary file since it was sent to the user's native filesystem as a download.
 	DirAccess::remove_file_or_error(output_path);

+ 5 - 3
platform/linuxbsd/os_linuxbsd.cpp

@@ -511,9 +511,11 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
 	String trash_info = "[Trash Info]\nPath=" + path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
 	{
 		Error err;
-		Ref<FileAccess> file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
-		ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file: \"" + trash_path + "/info/" + file_name + ".trashinfo\"");
-		file->store_string(trash_info);
+		{
+			Ref<FileAccess> file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
+			ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file: \"" + trash_path + "/info/" + file_name + ".trashinfo\"");
+			file->store_string(trash_info);
+		}
 
 		// Rename our resource before moving it to the trash can.
 		Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);

+ 16 - 14
platform/osx/export/export_plugin.cpp

@@ -256,21 +256,23 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
 			String path = EditorPaths::get_singleton()->get_cache_dir().plus_file("icon.png");
 			ResourceSaver::save(path, it);
 
-			Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
-			if (f.is_null()) {
-				// Clean up generated file.
-				DirAccess::remove_file_or_error(path);
-				ERR_FAIL();
-			}
+			{
+				Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
+				if (f.is_null()) {
+					// Clean up generated file.
+					DirAccess::remove_file_or_error(path);
+					ERR_FAIL();
+				}
 
-			int ofs = data.size();
-			uint64_t len = f->get_length();
-			data.resize(data.size() + len + 8);
-			f->get_buffer(&data.write[ofs + 8], len);
-			len += 8;
-			len = BSWAP32(len);
-			memcpy(&data.write[ofs], icon_infos[i].name, 4);
-			encode_uint32(len, &data.write[ofs + 4]);
+				int ofs = data.size();
+				uint64_t len = f->get_length();
+				data.resize(data.size() + len + 8);
+				f->get_buffer(&data.write[ofs + 8], len);
+				len += 8;
+				len = BSWAP32(len);
+				memcpy(&data.write[ofs], icon_infos[i].name, 4);
+				encode_uint32(len, &data.write[ofs + 4]);
+			}
 
 			// Clean up generated file.
 			DirAccess::remove_file_or_error(path);

+ 1 - 1
platform/uwp/export/app_packager.cpp

@@ -457,7 +457,7 @@ void AppxPackager::finish() {
 	Vector<uint8_t> end_record = make_end_of_central_record();
 	package->store_buffer(end_record.ptr(), end_record.size());
 
-	package = Ref<FileAccess>();
+	package.unref();
 }
 
 AppxPackager::AppxPackager() {}

+ 12 - 10
platform/uwp/export/export_plugin.h

@@ -346,19 +346,21 @@ class EditorExportPlatformUWP : public EditorExportPlatform {
 			ERR_FAIL_V_MSG(data, err_string);
 		}
 
-		Ref<FileAccess> f = FileAccess::open(tmp_path, FileAccess::READ, &err);
+		{
+			Ref<FileAccess> f = FileAccess::open(tmp_path, FileAccess::READ, &err);
+
+			if (err != OK) {
+				String err_string = "Couldn't open temp logo file.";
+				// Cleanup generated file.
+				DirAccess::remove_file_or_error(tmp_path);
+				EditorNode::add_io_error(err_string);
+				ERR_FAIL_V_MSG(data, err_string);
+			}
 
-		if (err != OK) {
-			String err_string = "Couldn't open temp logo file.";
-			// Cleanup generated file.
-			DirAccess::remove_file_or_error(tmp_path);
-			EditorNode::add_io_error(err_string);
-			ERR_FAIL_V_MSG(data, err_string);
+			data.resize(f->get_length());
+			f->get_buffer(data.ptrw(), data.size());
 		}
 
-		data.resize(f->get_length());
-		f->get_buffer(data.ptrw(), data.size());
-
 		DirAccess::remove_file_or_error(tmp_path);
 
 		return data;

+ 1 - 1
scene/main/http_request.cpp

@@ -197,7 +197,7 @@ void HTTPRequest::cancel_request() {
 		thread.wait_to_finish();
 	}
 
-	file = Ref<FileAccess>();
+	file.unref();
 	client->close();
 	body.clear();
 	got_response = false;

+ 104 - 103
scene/resources/resource_format_text.cpp

@@ -890,7 +890,7 @@ Error ResourceLoaderText::rename_dependencies(Ref<FileAccess> p_f, const String
 		fw->store_8(c);
 		c = f->get_8();
 	}
-	f = Ref<FileAccess>();
+	f.unref();
 
 	bool all_ok = fw->get_error() == OK;
 
@@ -1098,142 +1098,143 @@ Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_pa
 	wf->store_32(0); //zero sub resources, still parsing them
 
 	String temp_file = p_path + ".temp";
-	Ref<FileAccess> wf2 = FileAccess::open(temp_file, FileAccess::WRITE);
-	if (wf2.is_null()) {
-		return ERR_CANT_OPEN;
-	}
-
 	Vector<uint64_t> local_offsets;
 	Vector<uint64_t> local_pointers_pos;
+	{
+		Ref<FileAccess> wf2 = FileAccess::open(temp_file, FileAccess::WRITE);
+		if (wf2.is_null()) {
+			return ERR_CANT_OPEN;
+		}
 
-	while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
-		String type;
-		int id = -1;
-		bool main_res;
+		while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
+			String type;
+			int id = -1;
+			bool main_res;
 
-		if (next_tag.name == "sub_resource") {
-			if (!next_tag.fields.has("type")) {
-				error = ERR_FILE_CORRUPT;
-				error_text = "Missing 'type' in external resource tag";
-				_printerr();
-				return error;
-			}
+			if (next_tag.name == "sub_resource") {
+				if (!next_tag.fields.has("type")) {
+					error = ERR_FILE_CORRUPT;
+					error_text = "Missing 'type' in external resource tag";
+					_printerr();
+					return error;
+				}
 
-			if (!next_tag.fields.has("id")) {
-				error = ERR_FILE_CORRUPT;
-				error_text = "Missing 'id' in external resource tag";
-				_printerr();
-				return error;
+				if (!next_tag.fields.has("id")) {
+					error = ERR_FILE_CORRUPT;
+					error_text = "Missing 'id' in external resource tag";
+					_printerr();
+					return error;
+				}
+
+				type = next_tag.fields["type"];
+				id = next_tag.fields["id"];
+				main_res = false;
+			} else {
+				type = res_type;
+				id = 0; //used for last anyway
+				main_res = true;
 			}
 
-			type = next_tag.fields["type"];
-			id = next_tag.fields["id"];
-			main_res = false;
-		} else {
-			type = res_type;
-			id = 0; //used for last anyway
-			main_res = true;
-		}
+			local_offsets.push_back(wf2->get_position());
 
-		local_offsets.push_back(wf2->get_position());
+			bs_save_unicode_string(wf, "local://" + itos(id));
+			local_pointers_pos.push_back(wf->get_position());
+			wf->store_64(0); //temp local offset
 
-		bs_save_unicode_string(wf, "local://" + itos(id));
-		local_pointers_pos.push_back(wf->get_position());
-		wf->store_64(0); //temp local offset
+			bs_save_unicode_string(wf2, type);
+			uint64_t propcount_ofs = wf2->get_position();
+			wf2->store_32(0);
 
-		bs_save_unicode_string(wf2, type);
-		uint64_t propcount_ofs = wf2->get_position();
-		wf2->store_32(0);
+			int prop_count = 0;
 
-		int prop_count = 0;
+			while (true) {
+				String assign;
+				Variant value;
 
-		while (true) {
-			String assign;
-			Variant value;
+				error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
 
-			error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
+				if (error) {
+					if (main_res && error == ERR_FILE_EOF) {
+						next_tag.name = ""; //exit
+						break;
+					}
 
-			if (error) {
-				if (main_res && error == ERR_FILE_EOF) {
-					next_tag.name = ""; //exit
-					break;
+					_printerr();
+					return error;
 				}
 
-				_printerr();
-				return error;
+				if (!assign.is_empty()) {
+					Map<StringName, int> empty_string_map; //unused
+					bs_save_unicode_string(wf2, assign, true);
+					ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
+					prop_count++;
+
+				} else if (!next_tag.name.is_empty()) {
+					error = OK;
+					break;
+				} else {
+					error = ERR_FILE_CORRUPT;
+					error_text = "Premature end of file while parsing [sub_resource]";
+					_printerr();
+					return error;
+				}
 			}
 
-			if (!assign.is_empty()) {
-				Map<StringName, int> empty_string_map; //unused
-				bs_save_unicode_string(wf2, assign, true);
-				ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
-				prop_count++;
+			wf2->seek(propcount_ofs);
+			wf2->store_32(prop_count);
+			wf2->seek_end();
+		}
 
-			} else if (!next_tag.name.is_empty()) {
-				error = OK;
-				break;
-			} else {
-				error = ERR_FILE_CORRUPT;
-				error_text = "Premature end of file while parsing [sub_resource]";
+		if (next_tag.name == "node") {
+			//this is a node, must save one more!
+
+			if (!is_scene) {
+				error_text += "found the 'node' tag on a resource file!";
 				_printerr();
+				error = ERR_FILE_CORRUPT;
 				return error;
 			}
-		}
 
-		wf2->seek(propcount_ofs);
-		wf2->store_32(prop_count);
-		wf2->seek_end();
-	}
-
-	if (next_tag.name == "node") {
-		//this is a node, must save one more!
+			Ref<PackedScene> packed_scene = _parse_node_tag(rp);
 
-		if (!is_scene) {
-			error_text += "found the 'node' tag on a resource file!";
-			_printerr();
-			error = ERR_FILE_CORRUPT;
-			return error;
-		}
+			if (!packed_scene.is_valid()) {
+				return error;
+			}
 
-		Ref<PackedScene> packed_scene = _parse_node_tag(rp);
+			error = OK;
+			//get it here
+			List<PropertyInfo> props;
+			packed_scene->get_property_list(&props);
 
-		if (!packed_scene.is_valid()) {
-			return error;
-		}
+			bs_save_unicode_string(wf, "local://0");
+			local_pointers_pos.push_back(wf->get_position());
+			wf->store_64(0); //temp local offset
 
-		error = OK;
-		//get it here
-		List<PropertyInfo> props;
-		packed_scene->get_property_list(&props);
+			local_offsets.push_back(wf2->get_position());
+			bs_save_unicode_string(wf2, "PackedScene");
+			uint64_t propcount_ofs = wf2->get_position();
+			wf2->store_32(0);
 
-		bs_save_unicode_string(wf, "local://0");
-		local_pointers_pos.push_back(wf->get_position());
-		wf->store_64(0); //temp local offset
+			int prop_count = 0;
 
-		local_offsets.push_back(wf2->get_position());
-		bs_save_unicode_string(wf2, "PackedScene");
-		uint64_t propcount_ofs = wf2->get_position();
-		wf2->store_32(0);
+			for (const PropertyInfo &E : props) {
+				if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
+					continue;
+				}
 
-		int prop_count = 0;
+				String name = E.name;
+				Variant value = packed_scene->get(name);
 
-		for (const PropertyInfo &E : props) {
-			if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
-				continue;
+				Map<StringName, int> empty_string_map; //unused
+				bs_save_unicode_string(wf2, name, true);
+				ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
+				prop_count++;
 			}
 
-			String name = E.name;
-			Variant value = packed_scene->get(name);
-
-			Map<StringName, int> empty_string_map; //unused
-			bs_save_unicode_string(wf2, name, true);
-			ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
-			prop_count++;
+			wf2->seek(propcount_ofs);
+			wf2->store_32(prop_count);
+			wf2->seek_end();
 		}
-
-		wf2->seek(propcount_ofs);
-		wf2->store_32(prop_count);
-		wf2->seek_end();
 	}
 
 	uint64_t offset_from = wf->get_position();