浏览代码

Merge pull request #59440 from bruvzg/fd_ref_counted

Rémi Verschelde 3 年之前
父节点
当前提交
5613ac37d6
共有 100 个文件被更改,包括 690 次插入1133 次删除
  1. 13 43
      core/config/project_settings.cpp
  2. 60 79
      core/core_bind.cpp
  3. 2 4
      core/core_bind.h
  4. 1 2
      core/extension/extension_api_dump.cpp
  5. 2 2
      core/extension/native_extension_manager.cpp
  6. 17 28
      core/io/config_file.cpp
  7. 2 2
      core/io/config_file.h
  8. 18 38
      core/io/dir_access.cpp
  9. 10 31
      core/io/dir_access.h
  10. 24 34
      core/io/file_access.cpp
  11. 7 29
      core/io/file_access.h
  12. 23 28
      core/io/file_access_compressed.cpp
  13. 2 2
      core/io/file_access_compressed.h
  14. 11 13
      core/io/file_access_encrypted.cpp
  15. 3 3
      core/io/file_access_encrypted.h
  16. 1 1
      core/io/file_access_memory.cpp
  17. 1 1
      core/io/file_access_memory.h
  18. 16 53
      core/io/file_access_pack.cpp
  19. 12 16
      core/io/file_access_pack.h
  20. 24 22
      core/io/file_access_zip.cpp
  21. 1 1
      core/io/file_access_zip.h
  22. 6 21
      core/io/image_loader.cpp
  23. 2 2
      core/io/image_loader.h
  24. 9 19
      core/io/logger.cpp
  25. 1 4
      core/io/logger.h
  26. 16 35
      core/io/pck_packer.cpp
  27. 1 2
      core/io/pck_packer.h
  28. 4 8
      core/io/resource.cpp
  29. 52 85
      core/io/resource_format_binary.cpp
  30. 7 9
      core/io/resource_format_binary.h
  31. 4 11
      core/io/resource_importer.cpp
  32. 3 6
      core/io/resource_loader.cpp
  33. 8 10
      core/io/resource_uid.cpp
  34. 14 53
      core/io/translation_loader_po.cpp
  35. 1 1
      core/io/translation_loader_po.h
  36. 1 3
      core/io/xml_parser.cpp
  37. 23 27
      core/io/zip_io.cpp
  38. 7 3
      core/io/zip_io.h
  39. 11 2
      core/object/object.cpp
  40. 1 0
      core/object/object.h
  41. 18 15
      core/os/os.cpp
  42. 1 2
      core/string/translation_po.cpp
  43. 1 1
      core/variant/variant_parser.h
  44. 6 8
      drivers/gles3/shader_gles3.cpp
  45. 1 3
      drivers/png/image_loader_png.cpp
  46. 1 1
      drivers/png/image_loader_png.h
  47. 1 5
      drivers/png/resource_saver_png.cpp
  48. 2 2
      drivers/unix/dir_access_unix.cpp
  49. 2 2
      drivers/unix/dir_access_unix.h
  50. 1 1
      drivers/unix/file_access_unix.cpp
  51. 1 1
      drivers/unix/file_access_unix.h
  52. 1 2
      drivers/vulkan/rendering_device_vulkan.cpp
  53. 1 1
      drivers/windows/dir_access_windows.cpp
  54. 1 1
      drivers/windows/dir_access_windows.h
  55. 7 14
      editor/create_dialog.cpp
  56. 2 2
      editor/debugger/script_editor_debugger.cpp
  57. 1 1
      editor/dependency_editor.cpp
  58. 7 7
      editor/doc_tools.cpp
  59. 5 8
      editor/editor_asset_installer.cpp
  60. 2 2
      editor/editor_dir_dialog.cpp
  61. 22 32
      editor/editor_export.cpp
  62. 2 2
      editor/editor_export.h
  63. 6 7
      editor/editor_feature_profile.cpp
  64. 0 2
      editor/editor_file_dialog.cpp
  65. 1 1
      editor/editor_file_dialog.h
  66. 29 50
      editor/editor_file_system.cpp
  67. 2 2
      editor/editor_file_system.h
  68. 1 1
      editor/editor_folding.cpp
  69. 1 1
      editor/editor_fonts.cpp
  70. 4 4
      editor/editor_node.cpp
  71. 5 6
      editor/editor_paths.cpp
  72. 1 1
      editor/editor_plugin_settings.cpp
  73. 5 12
      editor/editor_resource_preview.cpp
  74. 14 18
      editor/editor_settings.cpp
  75. 4 2
      editor/editor_translation.cpp
  76. 3 5
      editor/editor_vcs_interface.cpp
  77. 18 25
      editor/export_template_manager.cpp
  78. 2 4
      editor/fileserver/editor_file_server.cpp
  79. 1 1
      editor/fileserver/editor_file_server.h
  80. 14 14
      editor/filesystem_dock.cpp
  81. 7 11
      editor/find_in_files.cpp
  82. 2 3
      editor/import/resource_importer_csv_translation.cpp
  83. 3 8
      editor/import/resource_importer_image.cpp
  84. 1 3
      editor/import/resource_importer_layered_texture.cpp
  85. 4 4
      editor/import/resource_importer_obj.cpp
  86. 2 3
      editor/import/resource_importer_scene.cpp
  87. 2 2
      editor/import/resource_importer_shader_file.cpp
  88. 3 5
      editor/import/resource_importer_texture.cpp
  89. 1 1
      editor/import/resource_importer_texture.h
  90. 1 18
      editor/import/resource_importer_wav.cpp
  91. 3 3
      editor/plugin_config_dialog.cpp
  92. 7 18
      editor/plugins/asset_library_editor_plugin.cpp
  93. 2 7
      editor/plugins/script_editor_plugin.cpp
  94. 2 4
      editor/pot_generator.cpp
  95. 1 1
      editor/pot_generator.h
  96. 13 17
      editor/project_manager.cpp
  97. 2 5
      editor/scene_tree_dock.cpp
  98. 6 8
      editor/script_create_dialog.cpp
  99. 3 3
      editor/shader_create_dialog.cpp
  100. 7 7
      main/main.cpp

+ 13 - 43
core/config/project_settings.cpp

@@ -145,7 +145,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
 		return p_path.simplify_path();
 	}
 
-	DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 
 	String path = p_path.replace("\\", "/").simplify_path();
 
@@ -537,8 +537,8 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
 	// Nothing was found, try to find a project file in provided path (`p_path`)
 	// or, if requested (`p_upwards`) in parent directories.
 
-	DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-	ERR_FAIL_COND_V_MSG(!d, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'.");
+	Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	ERR_FAIL_COND_V_MSG(d.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'.");
 	d->change_dir(p_path);
 
 	String current_dir = d->get_current_dir();
@@ -613,17 +613,14 @@ bool ProjectSettings::has_setting(String p_var) const {
 
 Error ProjectSettings::_load_settings_binary(const String &p_path) {
 	Error err;
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
 	if (err != OK) {
 		return err;
 	}
 
 	uint8_t hdr[4];
 	f->get_buffer(hdr, 4);
-	if (hdr[0] != 'E' || hdr[1] != 'C' || hdr[2] != 'F' || hdr[3] != 'G') {
-		memdelete(f);
-		ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Corrupted header in binary project.binary (not ECFG).");
-	}
+	ERR_FAIL_COND_V_MSG((hdr[0] != 'E' || hdr[1] != 'C' || hdr[2] != 'F' || hdr[3] != 'G'), ERR_FILE_CORRUPT, "Corrupted header in binary project.binary (not ECFG).");
 
 	uint32_t count = f->get_32();
 
@@ -646,16 +643,14 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) {
 		set(key, value);
 	}
 
-	f->close();
-	memdelete(f);
 	return OK;
 }
 
 Error ProjectSettings::_load_settings_text(const String &p_path) {
 	Error err;
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
 
-	if (!f) {
+	if (f.is_null()) {
 		// FIXME: Above 'err' error code is ERR_FILE_CANT_OPEN if the file is missing
 		// This needs to be streamlined if we want decent error reporting
 		return ERR_FILE_NOT_FOUND;
@@ -680,25 +675,18 @@ Error ProjectSettings::_load_settings_text(const String &p_path) {
 
 		err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true);
 		if (err == ERR_FILE_EOF) {
-			memdelete(f);
 			// If we're loading a project.godot from source code, we can operate some
 			// ProjectSettings conversions if need be.
 			_convert_to_last_version(config_version);
 			last_save_time = FileAccess::get_modified_time(get_resource_path().plus_file("project.godot"));
 			return OK;
-		} else if (err != OK) {
-			ERR_PRINT("Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted.");
-			memdelete(f);
-			return err;
 		}
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted.");
 
 		if (!assign.is_empty()) {
 			if (section.is_empty() && assign == "config_version") {
 				config_version = value;
-				if (config_version > CONFIG_VERSION) {
-					memdelete(f);
-					ERR_FAIL_V_MSG(ERR_FILE_CANT_OPEN, vformat("Can't open project at '%s', its `config_version` (%d) is from a more recent and incompatible version of the engine. Expected config version: %d.", p_path, config_version, CONFIG_VERSION));
-				}
+				ERR_FAIL_COND_V_MSG(config_version > CONFIG_VERSION, ERR_FILE_CANT_OPEN, vformat("Can't open project at '%s', its `config_version` (%d) is from a more recent and incompatible version of the engine. Expected config version: %d.", p_path, config_version, CONFIG_VERSION));
 			} else {
 				if (section.is_empty()) {
 					set(assign, value);
@@ -778,7 +766,7 @@ Error ProjectSettings::save() {
 
 Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) {
 	Error err;
-	FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+	Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
 	ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.binary at " + p_file + ".");
 
 	uint8_t hdr[4] = { 'E', 'C', 'F', 'G' };
@@ -798,19 +786,13 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
 
 		int len;
 		err = encode_variant(p_custom_features, nullptr, len, false);
-		if (err != OK) {
-			memdelete(file);
-			ERR_FAIL_V(err);
-		}
+		ERR_FAIL_COND_V(err != OK, err);
 
 		Vector<uint8_t> buff;
 		buff.resize(len);
 
 		err = encode_variant(p_custom_features, buff.ptrw(), len, false);
-		if (err != OK) {
-			memdelete(file);
-			ERR_FAIL_V(err);
-		}
+		ERR_FAIL_COND_V(err != OK, err);
 		file->store_32(len);
 		file->store_buffer(buff.ptr(), buff.size());
 
@@ -834,33 +816,24 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
 
 			int len;
 			err = encode_variant(value, nullptr, len, true);
-			if (err != OK) {
-				memdelete(file);
-			}
 			ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Error when trying to encode Variant.");
 
 			Vector<uint8_t> buff;
 			buff.resize(len);
 
 			err = encode_variant(value, buff.ptrw(), len, true);
-			if (err != OK) {
-				memdelete(file);
-			}
 			ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Error when trying to encode Variant.");
 			file->store_32(len);
 			file->store_buffer(buff.ptr(), buff.size());
 		}
 	}
 
-	file->close();
-	memdelete(file);
-
 	return OK;
 }
 
 Error ProjectSettings::_save_settings_text(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) {
 	Error err;
-	FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+	Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
 
 	ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.godot - " + p_file + ".");
 
@@ -905,9 +878,6 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
 		}
 	}
 
-	file->close();
-	memdelete(file);
-
 	return OK;
 }
 

+ 60 - 79
core/core_bind.cpp

@@ -1027,10 +1027,10 @@ Error File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const V
 		return err;
 	}
 
-	FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+	Ref<FileAccessEncrypted> fae;
+	fae.instantiate();
 	err = fae->open_and_parse(f, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ);
 	if (err) {
-		memdelete(fae);
 		close();
 		return err;
 	}
@@ -1044,10 +1044,10 @@ Error File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, co
 		return err;
 	}
 
-	FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+	Ref<FileAccessEncrypted> fae;
+	fae.instantiate();
 	err = fae->open_and_parse_password(f, p_pass, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ);
 	if (err) {
-		memdelete(fae);
 		close();
 		return err;
 	}
@@ -1057,14 +1057,13 @@ Error File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, co
 }
 
 Error File::open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode) {
-	FileAccessCompressed *fac = memnew(FileAccessCompressed);
-
+	Ref<FileAccessCompressed> fac;
+	fac.instantiate();
 	fac->configure("GCPF", (Compression::Mode)p_compress_mode);
 
 	Error err = fac->_open(p_path, p_mode_flags);
 
 	if (err) {
-		memdelete(fac);
 		return err;
 	}
 
@@ -1076,22 +1075,20 @@ Error File::open(const String &p_path, ModeFlags p_mode_flags) {
 	close();
 	Error err;
 	f = FileAccess::open(p_path, p_mode_flags, &err);
-	if (f) {
+	if (f.is_valid()) {
 		f->set_big_endian(big_endian);
 	}
 	return err;
 }
 
 void File::flush() {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before flushing.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before flushing.");
 	f->flush();
 }
 
 void File::close() {
-	if (f) {
-		memdelete(f);
-	}
-	f = nullptr;
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened.");
+	f = Ref<FileAccess>();
 }
 
 bool File::is_open() const {
@@ -1099,79 +1096,79 @@ bool File::is_open() const {
 }
 
 String File::get_path() const {
-	ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), "", "File must be opened before use, or is lacking read-write permission.");
 	return f->get_path();
 }
 
 String File::get_path_absolute() const {
-	ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), "", "File must be opened before use, or is lacking read-write permission.");
 	return f->get_path_absolute();
 }
 
 void File::seek(int64_t p_position) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 	ERR_FAIL_COND_MSG(p_position < 0, "Seek position must be a positive integer.");
 	f->seek(p_position);
 }
 
 void File::seek_end(int64_t p_position) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 	f->seek_end(p_position);
 }
 
 uint64_t File::get_position() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
 	return f->get_position();
 }
 
 uint64_t File::get_length() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
 	return f->get_length();
 }
 
 bool File::eof_reached() const {
-	ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), false, "File must be opened before use, or is lacking read-write permission.");
 	return f->eof_reached();
 }
 
 uint8_t File::get_8() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
 	return f->get_8();
 }
 
 uint16_t File::get_16() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
 	return f->get_16();
 }
 
 uint32_t File::get_32() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
 	return f->get_32();
 }
 
 uint64_t File::get_64() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
 	return f->get_64();
 }
 
 float File::get_float() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
 	return f->get_float();
 }
 
 double File::get_double() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
 	return f->get_double();
 }
 
 real_t File::get_real() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
 	return f->get_real();
 }
 
 Vector<uint8_t> File::get_buffer(int64_t p_length) const {
 	Vector<uint8_t> data;
-	ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), data, "File must be opened before use, or is lacking read-write permission.");
 
 	ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0.");
 	if (p_length == 0) {
@@ -1192,11 +1189,11 @@ Vector<uint8_t> File::get_buffer(int64_t p_length) const {
 }
 
 String File::get_as_text() const {
-	ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), String(), "File must be opened before use, or is lacking read-write permission.");
 
 	String text;
 	uint64_t original_pos = f->get_position();
-	f->seek(0);
+	const_cast<FileAccess *>(*f)->seek(0);
 
 	String l = get_line();
 	while (!eof_reached()) {
@@ -1205,7 +1202,7 @@ String File::get_as_text() const {
 	}
 	text += l;
 
-	f->seek(original_pos);
+	const_cast<FileAccess *>(*f)->seek(original_pos);
 
 	return text;
 }
@@ -1219,12 +1216,12 @@ String File::get_sha256(const String &p_path) const {
 }
 
 String File::get_line() const {
-	ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), String(), "File must be opened before use, or is lacking read-write permission.");
 	return f->get_line();
 }
 
 Vector<String> File::get_csv_line(const String &p_delim) const {
-	ERR_FAIL_COND_V_MSG(!f, Vector<String>(), "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), Vector<String>(), "File must be opened before use, or is lacking read-write permission.");
 	return f->get_csv_line(p_delim);
 }
 
@@ -1235,7 +1232,7 @@ Vector<String> File::get_csv_line(const String &p_delim) const {
 
 void File::set_big_endian(bool p_big_endian) {
 	big_endian = p_big_endian;
-	if (f) {
+	if (f.is_valid()) {
 		f->set_big_endian(p_big_endian);
 	}
 }
@@ -1245,84 +1242,84 @@ bool File::is_big_endian() {
 }
 
 Error File::get_error() const {
-	if (!f) {
+	if (f.is_null()) {
 		return ERR_UNCONFIGURED;
 	}
 	return f->get_error();
 }
 
 void File::store_8(uint8_t p_dest) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	f->store_8(p_dest);
 }
 
 void File::store_16(uint16_t p_dest) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	f->store_16(p_dest);
 }
 
 void File::store_32(uint32_t p_dest) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	f->store_32(p_dest);
 }
 
 void File::store_64(uint64_t p_dest) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	f->store_64(p_dest);
 }
 
 void File::store_float(float p_dest) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	f->store_float(p_dest);
 }
 
 void File::store_double(double p_dest) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	f->store_double(p_dest);
 }
 
 void File::store_real(real_t p_real) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	f->store_real(p_real);
 }
 
 void File::store_string(const String &p_string) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	f->store_string(p_string);
 }
 
 void File::store_pascal_string(const String &p_string) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	f->store_pascal_string(p_string);
 }
 
 String File::get_pascal_string() {
-	ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), "", "File must be opened before use, or is lacking read-write permission.");
 
 	return f->get_pascal_string();
 }
 
 void File::store_line(const String &p_string) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 	f->store_line(p_string);
 }
 
 void File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 	f->store_csv_line(p_values, p_delim);
 }
 
 void File::store_buffer(const Vector<uint8_t> &p_buffer) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 
 	uint64_t len = p_buffer.size();
 	if (len == 0) {
@@ -1339,7 +1336,7 @@ bool File::file_exists(const String &p_name) {
 }
 
 void File::store_var(const Variant &p_var, bool p_full_objects) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
 	int len;
 	Error err = encode_variant(p_var, nullptr, len, p_full_objects);
 	ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
@@ -1356,7 +1353,7 @@ void File::store_var(const Variant &p_var, bool p_full_objects) {
 }
 
 Variant File::get_var(bool p_allow_objects) const {
-	ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use, or is lacking read-write permission.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), Variant(), "File must be opened before use, or is lacking read-write permission.");
 	uint32_t len = get_32();
 	Vector<uint8_t> buff = get_buffer(len);
 	ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant());
@@ -1440,24 +1437,14 @@ void File::_bind_methods() {
 	BIND_ENUM_CONSTANT(COMPRESSION_GZIP);
 }
 
-File::~File() {
-	if (f) {
-		memdelete(f);
-	}
-}
-
 ////// Directory //////
 
 Error Directory::open(const String &p_path) {
 	Error err;
-	DirAccess *alt = DirAccess::open(p_path, &err);
-
-	if (!alt) {
+	Ref<DirAccess> alt = DirAccess::open(p_path, &err);
+	if (alt.is_null()) {
 		return err;
 	}
-	if (d) {
-		memdelete(d);
-	}
 	d = alt;
 	dir_open = true;
 
@@ -1465,7 +1452,7 @@ Error Directory::open(const String &p_path) {
 }
 
 bool Directory::is_open() const {
-	return d && dir_open;
+	return d.is_valid() && dir_open;
 }
 
 Error Directory::list_dir_begin() {
@@ -1550,7 +1537,7 @@ int Directory::get_current_drive() {
 }
 
 Error Directory::change_dir(String p_dir) {
-	ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
+	ERR_FAIL_COND_V_MSG(d.is_null(), ERR_UNCONFIGURED, "Directory is not configured properly.");
 	Error err = d->change_dir(p_dir);
 
 	if (err != OK) {
@@ -1567,25 +1554,25 @@ String Directory::get_current_dir() {
 }
 
 Error Directory::make_dir(String p_dir) {
-	ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
+	ERR_FAIL_COND_V_MSG(d.is_null(), ERR_UNCONFIGURED, "Directory is not configured properly.");
 	if (!p_dir.is_relative_path()) {
-		DirAccessRef da = DirAccess::create_for_path(p_dir);
+		Ref<DirAccess> da = DirAccess::create_for_path(p_dir);
 		return da->make_dir(p_dir);
 	}
 	return d->make_dir(p_dir);
 }
 
 Error Directory::make_dir_recursive(String p_dir) {
-	ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
+	ERR_FAIL_COND_V_MSG(d.is_null(), ERR_UNCONFIGURED, "Directory is not configured properly.");
 	if (!p_dir.is_relative_path()) {
-		DirAccessRef da = DirAccess::create_for_path(p_dir);
+		Ref<DirAccess> da = DirAccess::create_for_path(p_dir);
 		return da->make_dir_recursive(p_dir);
 	}
 	return d->make_dir_recursive(p_dir);
 }
 
 bool Directory::file_exists(String p_file) {
-	ERR_FAIL_COND_V_MSG(!d, false, "Directory is not configured properly.");
+	ERR_FAIL_COND_V_MSG(d.is_null(), false, "Directory is not configured properly.");
 	if (!p_file.is_relative_path()) {
 		return FileAccess::exists(p_file);
 	}
@@ -1593,7 +1580,7 @@ bool Directory::file_exists(String p_file) {
 }
 
 bool Directory::dir_exists(String p_dir) {
-	ERR_FAIL_COND_V_MSG(!d, false, "Directory is not configured properly.");
+	ERR_FAIL_COND_V_MSG(d.is_null(), false, "Directory is not configured properly.");
 	if (!p_dir.is_relative_path()) {
 		return DirAccess::exists(p_dir);
 	}
@@ -1601,7 +1588,7 @@ bool Directory::dir_exists(String p_dir) {
 }
 
 uint64_t Directory::get_space_left() {
-	ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use.");
+	ERR_FAIL_COND_V_MSG(d.is_null(), 0, "Directory must be opened before use.");
 	return d->get_space_left() / 1024 * 1024; // Truncate to closest MiB.
 }
 
@@ -1615,7 +1602,7 @@ Error Directory::rename(String p_from, String p_to) {
 	ERR_FAIL_COND_V_MSG(p_from.is_empty() || p_from == "." || p_from == "..", ERR_INVALID_PARAMETER, "Invalid path to rename.");
 
 	if (!p_from.is_relative_path()) {
-		DirAccessRef da = DirAccess::create_for_path(p_from);
+		Ref<DirAccess> da = DirAccess::create_for_path(p_from);
 		ERR_FAIL_COND_V_MSG(!da->file_exists(p_from) && !da->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
 		return da->rename(p_from, p_to);
 	}
@@ -1627,7 +1614,7 @@ Error Directory::rename(String p_from, String p_to) {
 Error Directory::remove(String p_name) {
 	ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
 	if (!p_name.is_relative_path()) {
-		DirAccessRef da = DirAccess::create_for_path(p_name);
+		Ref<DirAccess> da = DirAccess::create_for_path(p_name);
 		return da->remove(p_name);
 	}
 
@@ -1669,12 +1656,6 @@ Directory::Directory() {
 	d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 }
 
-Directory::~Directory() {
-	if (d) {
-		memdelete(d);
-	}
-}
-
 ////// Marshalls //////
 
 Marshalls *Marshalls::singleton = nullptr;

+ 2 - 4
core/core_bind.h

@@ -349,7 +349,7 @@ public:
 class File : public RefCounted {
 	GDCLASS(File, RefCounted);
 
-	FileAccess *f = nullptr;
+	Ref<FileAccess> f;
 	bool big_endian = false;
 
 protected:
@@ -442,12 +442,11 @@ public:
 	uint64_t get_modified_time(const String &p_file) const;
 
 	File() {}
-	virtual ~File();
 };
 
 class Directory : public RefCounted {
 	GDCLASS(Directory, RefCounted);
-	DirAccess *d = nullptr;
+	Ref<DirAccess> d;
 
 	bool dir_open = false;
 	bool include_navigational = false;
@@ -495,7 +494,6 @@ public:
 	Error remove(String p_name);
 
 	Directory();
-	virtual ~Directory();
 };
 
 class Marshalls : public Object {

+ 1 - 2
core/extension/extension_api_dump.cpp

@@ -869,9 +869,8 @@ void NativeExtensionAPIDump::generate_extension_json_file(const String &p_path)
 	json.instantiate();
 
 	String text = json->stringify(api, "\t", false);
-	FileAccessRef fa = FileAccess::open(p_path, FileAccess::WRITE);
+	Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
 	CharString cs = text.ascii();
 	fa->store_buffer((const uint8_t *)cs.ptr(), cs.length());
-	fa->close();
 }
 #endif

+ 2 - 2
core/extension/native_extension_manager.cpp

@@ -112,8 +112,8 @@ void NativeExtensionManager::deinitialize_extensions(NativeExtension::Initializa
 }
 
 void NativeExtensionManager::load_extensions() {
-	FileAccessRef f = FileAccess::open(NativeExtension::get_extension_list_config_file(), FileAccess::READ);
-	while (f && !f->eof_reached()) {
+	Ref<FileAccess> f = FileAccess::open(NativeExtension::get_extension_list_config_file(), FileAccess::READ);
+	while (f.is_valid() && !f->eof_reached()) {
 		String s = f->get_line().strip_edges();
 		if (!s.is_empty()) {
 			LoadStatus err = load_extension(s);

+ 17 - 28
core/io/config_file.cpp

@@ -129,12 +129,9 @@ void ConfigFile::erase_section_key(const String &p_section, const String &p_key)
 
 Error ConfigFile::save(const String &p_path) {
 	Error err;
-	FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+	Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
 
 	if (err) {
-		if (file) {
-			memdelete(file);
-		}
 		return err;
 	}
 
@@ -143,17 +140,16 @@ Error ConfigFile::save(const String &p_path) {
 
 Error ConfigFile::save_encrypted(const String &p_path, const Vector<uint8_t> &p_key) {
 	Error err;
-	FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
 
 	if (err) {
 		return err;
 	}
 
-	FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+	Ref<FileAccessEncrypted> fae;
+	fae.instantiate();
 	err = fae->open_and_parse(f, p_key, FileAccessEncrypted::MODE_WRITE_AES256);
 	if (err) {
-		memdelete(fae);
-		memdelete(f);
 		return err;
 	}
 	return _internal_save(fae);
@@ -161,24 +157,23 @@ Error ConfigFile::save_encrypted(const String &p_path, const Vector<uint8_t> &p_
 
 Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass) {
 	Error err;
-	FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
 
 	if (err) {
 		return err;
 	}
 
-	FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+	Ref<FileAccessEncrypted> fae;
+	fae.instantiate();
 	err = fae->open_and_parse_password(f, p_pass, FileAccessEncrypted::MODE_WRITE_AES256);
 	if (err) {
-		memdelete(fae);
-		memdelete(f);
 		return err;
 	}
 
 	return _internal_save(fae);
 }
 
-Error ConfigFile::_internal_save(FileAccess *file) {
+Error ConfigFile::_internal_save(Ref<FileAccess> file) {
 	for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::Element E = values.front(); E; E = E.next()) {
 		if (E != values.front()) {
 			file->store_string("\n");
@@ -194,16 +189,14 @@ Error ConfigFile::_internal_save(FileAccess *file) {
 		}
 	}
 
-	memdelete(file);
-
 	return OK;
 }
 
 Error ConfigFile::load(const String &p_path) {
 	Error err;
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
 
-	if (!f) {
+	if (f.is_null()) {
 		return err;
 	}
 
@@ -212,17 +205,16 @@ Error ConfigFile::load(const String &p_path) {
 
 Error ConfigFile::load_encrypted(const String &p_path, const Vector<uint8_t> &p_key) {
 	Error err;
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
 
 	if (err) {
 		return err;
 	}
 
-	FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+	Ref<FileAccessEncrypted> fae;
+	fae.instantiate();
 	err = fae->open_and_parse(f, p_key, FileAccessEncrypted::MODE_READ);
 	if (err) {
-		memdelete(fae);
-		memdelete(f);
 		return err;
 	}
 	return _internal_load(p_path, fae);
@@ -230,31 +222,28 @@ Error ConfigFile::load_encrypted(const String &p_path, const Vector<uint8_t> &p_
 
 Error ConfigFile::load_encrypted_pass(const String &p_path, const String &p_pass) {
 	Error err;
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
 
 	if (err) {
 		return err;
 	}
 
-	FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+	Ref<FileAccessEncrypted> fae;
+	fae.instantiate();
 	err = fae->open_and_parse_password(f, p_pass, FileAccessEncrypted::MODE_READ);
 	if (err) {
-		memdelete(fae);
-		memdelete(f);
 		return err;
 	}
 
 	return _internal_load(p_path, fae);
 }
 
-Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) {
+Error ConfigFile::_internal_load(const String &p_path, Ref<FileAccess> f) {
 	VariantParser::StreamFile stream;
 	stream.f = f;
 
 	Error err = _parse(p_path, &stream);
 
-	memdelete(f);
-
 	return err;
 }
 

+ 2 - 2
core/io/config_file.h

@@ -43,8 +43,8 @@ class ConfigFile : public RefCounted {
 
 	PackedStringArray _get_sections() const;
 	PackedStringArray _get_section_keys(const String &p_section) const;
-	Error _internal_load(const String &p_path, FileAccess *f);
-	Error _internal_save(FileAccess *file);
+	Error _internal_load(const String &p_path, Ref<FileAccess> f);
+	Error _internal_save(Ref<FileAccess> file);
 
 	Error _parse(const String &p_path, VariantParser::Stream *p_stream);
 

+ 18 - 38
core/io/dir_access.cpp

@@ -217,8 +217,8 @@ String DirAccess::fix_path(String p_path) const {
 
 DirAccess::CreateFunc DirAccess::create_func[ACCESS_MAX] = { nullptr, nullptr, nullptr };
 
-DirAccess *DirAccess::create_for_path(const String &p_path) {
-	DirAccess *da = nullptr;
+Ref<DirAccess> DirAccess::create_for_path(const String &p_path) {
+	Ref<DirAccess> da;
 	if (p_path.begins_with("res://")) {
 		da = create(ACCESS_RESOURCES);
 	} else if (p_path.begins_with("user://")) {
@@ -230,25 +230,23 @@ DirAccess *DirAccess::create_for_path(const String &p_path) {
 	return da;
 }
 
-DirAccess *DirAccess::open(const String &p_path, Error *r_error) {
-	DirAccess *da = create_for_path(p_path);
-
-	ERR_FAIL_COND_V_MSG(!da, nullptr, "Cannot create DirAccess for path '" + p_path + "'.");
+Ref<DirAccess> DirAccess::open(const String &p_path, Error *r_error) {
+	Ref<DirAccess> da = create_for_path(p_path);
+	ERR_FAIL_COND_V_MSG(da.is_null(), nullptr, "Cannot create DirAccess for path '" + p_path + "'.");
 	Error err = da->change_dir(p_path);
 	if (r_error) {
 		*r_error = err;
 	}
 	if (err != OK) {
-		memdelete(da);
 		return nullptr;
 	}
 
 	return da;
 }
 
-DirAccess *DirAccess::create(AccessType p_access) {
-	DirAccess *da = create_func[p_access] ? create_func[p_access]() : nullptr;
-	if (da) {
+Ref<DirAccess> DirAccess::create(AccessType p_access) {
+	Ref<DirAccess> da = create_func[p_access] ? create_func[p_access]() : nullptr;
+	if (da.is_valid()) {
 		da->_access_type = p_access;
 
 		// for ACCESS_RESOURCES and ACCESS_FILESYSTEM, current_dir already defaults to where game was started
@@ -264,34 +262,24 @@ DirAccess *DirAccess::create(AccessType p_access) {
 }
 
 String DirAccess::get_full_path(const String &p_path, AccessType p_access) {
-	DirAccess *d = DirAccess::create(p_access);
-	if (!d) {
+	Ref<DirAccess> d = DirAccess::create(p_access);
+	if (d.is_null()) {
 		return p_path;
 	}
 
 	d->change_dir(p_path);
 	String full = d->get_current_dir();
-	memdelete(d);
 	return full;
 }
 
 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;
-	FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
-
-	if (err) {
-		ERR_PRINT("Failed to open " + p_from);
-		return err;
-	}
+	Ref<FileAccess> fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
+	ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_from);
 
-	FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
-	if (err) {
-		fsrc->close();
-		memdelete(fsrc);
-		ERR_PRINT("Failed to open " + p_to);
-		return err;
-	}
+	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();
@@ -311,7 +299,6 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
 	}
 
 	if (err == OK && p_chmod_flags != -1) {
-		fdst->close();
 		err = FileAccess::set_unix_permissions(p_to, p_chmod_flags);
 		// If running on a platform with no chmod support (i.e., Windows), don't fail
 		if (err == ERR_UNAVAILABLE) {
@@ -319,9 +306,6 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
 		}
 	}
 
-	memdelete(fsrc);
-	memdelete(fdst);
-
 	return err;
 }
 
@@ -343,7 +327,7 @@ public:
 	}
 };
 
-Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags, bool p_copy_links) {
+Error DirAccess::_copy_dir(Ref<DirAccess> &p_target_da, String p_to, int p_chmod_flags, bool p_copy_links) {
 	List<String> dirs;
 
 	String curdir = get_current_dir();
@@ -399,14 +383,11 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag
 Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags, bool p_copy_links) {
 	ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist.");
 
-	DirAccess *target_da = DirAccess::create_for_path(p_to);
-	ERR_FAIL_COND_V_MSG(!target_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'.");
+	Ref<DirAccess> target_da = DirAccess::create_for_path(p_to);
+	ERR_FAIL_COND_V_MSG(target_da.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'.");
 
 	if (!target_da->dir_exists(p_to)) {
 		Error err = target_da->make_dir_recursive(p_to);
-		if (err) {
-			memdelete(target_da);
-		}
 		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + p_to + "'.");
 	}
 
@@ -416,12 +397,11 @@ Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags, bool p_
 
 	DirChanger dir_changer(this, p_from);
 	Error err = _copy_dir(target_da, p_to, p_chmod_flags, p_copy_links);
-	memdelete(target_da);
 
 	return err;
 }
 
 bool DirAccess::exists(String p_dir) {
-	DirAccessRef da = DirAccess::create_for_path(p_dir);
+	Ref<DirAccess> da = DirAccess::create_for_path(p_dir);
 	return da->change_dir(p_dir) == OK;
 }

+ 10 - 31
core/io/dir_access.h

@@ -31,11 +31,12 @@
 #ifndef DIR_ACCESS_H
 #define DIR_ACCESS_H
 
+#include "core/object/ref_counted.h"
 #include "core/string/ustring.h"
 #include "core/typedefs.h"
 
 //@ TODO, excellent candidate for THREAD_SAFE MACRO, should go through all these and add THREAD_SAFE where it applies
-class DirAccess {
+class DirAccess : public RefCounted {
 public:
 	enum AccessType {
 		ACCESS_RESOURCES,
@@ -44,13 +45,13 @@ public:
 		ACCESS_MAX
 	};
 
-	typedef DirAccess *(*CreateFunc)();
+	typedef Ref<DirAccess> (*CreateFunc)();
 
 private:
 	AccessType _access_type = ACCESS_FILESYSTEM;
 	static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
 
-	Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags, bool p_copy_links);
+	Error _copy_dir(Ref<DirAccess> &p_target_da, String p_to, int p_chmod_flags, bool p_copy_links);
 
 protected:
 	String _get_root_path() const;
@@ -59,7 +60,7 @@ protected:
 	String fix_path(String p_path) const;
 
 	template <class T>
-	static DirAccess *_create_builtin() {
+	static Ref<DirAccess> _create_builtin() {
 		return memnew(T);
 	}
 
@@ -77,7 +78,7 @@ public:
 	virtual bool drives_are_shortcuts();
 
 	virtual Error change_dir(String p_dir) = 0; ///< can be relative or absolute, return false on success
-	virtual String get_current_dir(bool p_include_drive = true) = 0; ///< return current dir location
+	virtual String get_current_dir(bool p_include_drive = true) const = 0; ///< return current dir location
 	virtual Error make_dir(String p_dir) = 0;
 	virtual Error make_dir_recursive(String p_dir);
 	virtual Error erase_contents_recursive(); //super dangerous, use with care!
@@ -101,51 +102,29 @@ public:
 	// Meant for editor code when we want to quickly remove a file without custom
 	// handling (e.g. removing a cache file).
 	static void remove_file_or_error(String p_path) {
-		DirAccess *da = create(ACCESS_FILESYSTEM);
+		Ref<DirAccess> da = create(ACCESS_FILESYSTEM);
 		if (da->file_exists(p_path)) {
 			if (da->remove(p_path) != OK) {
 				ERR_FAIL_MSG("Cannot remove file or directory: " + p_path);
 			}
 		}
-		memdelete(da);
 	}
 
 	virtual String get_filesystem_type() const = 0;
 	static String get_full_path(const String &p_path, AccessType p_access);
-	static DirAccess *create_for_path(const String &p_path);
+	static Ref<DirAccess> create_for_path(const String &p_path);
 
-	static DirAccess *create(AccessType p_access);
+	static Ref<DirAccess> create(AccessType p_access);
 
 	template <class T>
 	static void make_default(AccessType p_access) {
 		create_func[p_access] = _create_builtin<T>;
 	}
 
-	static DirAccess *open(const String &p_path, Error *r_error = nullptr);
+	static Ref<DirAccess> open(const String &p_path, Error *r_error = nullptr);
 
 	DirAccess() {}
 	virtual ~DirAccess() {}
 };
 
-struct DirAccessRef {
-	_FORCE_INLINE_ DirAccess *operator->() {
-		return f;
-	}
-
-	operator bool() const { return f != nullptr; }
-
-	DirAccess *f = nullptr;
-
-	DirAccessRef(DirAccess *fa) { f = fa; }
-	DirAccessRef(DirAccessRef &&other) {
-		f = other.f;
-		other.f = nullptr;
-	}
-	~DirAccessRef() {
-		if (f) {
-			memdelete(f);
-		}
-	}
-};
-
 #endif // DIR_ACCESS_H

+ 24 - 34
core/io/file_access.cpp

@@ -42,10 +42,10 @@ FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr;
 
 bool FileAccess::backup_save = false;
 
-FileAccess *FileAccess::create(AccessType p_access) {
+Ref<FileAccess> FileAccess::create(AccessType p_access) {
 	ERR_FAIL_INDEX_V(p_access, ACCESS_MAX, nullptr);
 
-	FileAccess *ret = create_func[p_access]();
+	Ref<FileAccess> ret = create_func[p_access]();
 	ret->_set_access_type(p_access);
 	return ret;
 }
@@ -55,11 +55,10 @@ bool FileAccess::exists(const String &p_name) {
 		return true;
 	}
 
-	FileAccess *f = open(p_name, READ);
-	if (!f) {
+	Ref<FileAccess> f = open(p_name, READ);
+	if (f.is_null()) {
 		return false;
 	}
-	memdelete(f);
 	return true;
 }
 
@@ -67,8 +66,8 @@ void FileAccess::_set_access_type(AccessType p_access) {
 	_access_type = p_access;
 }
 
-FileAccess *FileAccess::create_for_path(const String &p_path) {
-	FileAccess *ret = nullptr;
+Ref<FileAccess> FileAccess::create_for_path(const String &p_path) {
+	Ref<FileAccess> ret;
 	if (p_path.begins_with("res://")) {
 		ret = create(ACCESS_RESOURCES);
 	} else if (p_path.begins_with("user://")) {
@@ -85,13 +84,13 @@ Error FileAccess::reopen(const String &p_path, int p_mode_flags) {
 	return _open(p_path, p_mode_flags);
 }
 
-FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
+Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
 	//try packed data first
 
-	FileAccess *ret = nullptr;
+	Ref<FileAccess> ret;
 	if (!(p_mode_flags & WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
 		ret = PackedData::get_singleton()->try_open_path(p_path);
-		if (ret) {
+		if (ret.is_valid()) {
 			if (r_error) {
 				*r_error = OK;
 			}
@@ -106,8 +105,7 @@ FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_er
 		*r_error = err;
 	}
 	if (err != OK) {
-		memdelete(ret);
-		ret = nullptr;
+		ret = Ref<FileAccess>();
 	}
 
 	return ret;
@@ -463,11 +461,10 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
 		return 0;
 	}
 
-	FileAccess *fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
+	Ref<FileAccess> fa = create_for_path(p_file);
+	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'.");
 
 	uint64_t mt = fa->_get_modified_time(p_file);
-	memdelete(fa);
 	return mt;
 }
 
@@ -476,11 +473,10 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) {
 		return 0;
 	}
 
-	FileAccess *fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
+	Ref<FileAccess> fa = create_for_path(p_file);
+	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'.");
 
 	uint32_t mt = fa->_get_unix_permissions(p_file);
-	memdelete(fa);
 	return mt;
 }
 
@@ -489,11 +485,10 @@ Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissi
 		return ERR_UNAVAILABLE;
 	}
 
-	FileAccess *fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
+	Ref<FileAccess> fa = create_for_path(p_file);
+	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
 
 	Error err = fa->_set_unix_permissions(p_file, p_permissions);
-	memdelete(fa);
 	return err;
 }
 
@@ -559,8 +554,8 @@ void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
 }
 
 Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) {
-	FileAccess *f = FileAccess::open(p_path, READ, r_error);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(p_path, READ, r_error);
+	if (f.is_null()) {
 		if (r_error) { // if error requested, do not throw error
 			return Vector<uint8_t>();
 		}
@@ -569,7 +564,6 @@ Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_err
 	Vector<uint8_t> data;
 	data.resize(f->get_length());
 	f->get_buffer(data.ptrw(), data.size());
-	memdelete(f);
 	return data;
 }
 
@@ -592,8 +586,8 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
 }
 
 String FileAccess::get_md5(const String &p_file) {
-	FileAccess *f = FileAccess::open(p_file, READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(p_file, READ);
+	if (f.is_null()) {
 		return String();
 	}
 
@@ -615,8 +609,6 @@ String FileAccess::get_md5(const String &p_file) {
 	unsigned char hash[16];
 	ctx.finish(hash);
 
-	memdelete(f);
-
 	return String::md5(hash);
 }
 
@@ -625,8 +617,8 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) {
 	ctx.start();
 
 	for (int i = 0; i < p_file.size(); i++) {
-		FileAccess *f = FileAccess::open(p_file[i], READ);
-		ERR_CONTINUE(!f);
+		Ref<FileAccess> f = FileAccess::open(p_file[i], READ);
+		ERR_CONTINUE(f.is_null());
 
 		unsigned char step[32768];
 
@@ -639,7 +631,6 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) {
 				break;
 			}
 		}
-		memdelete(f);
 	}
 
 	unsigned char hash[16];
@@ -649,8 +640,8 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) {
 }
 
 String FileAccess::get_sha256(const String &p_file) {
-	FileAccess *f = FileAccess::open(p_file, READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(p_file, READ);
+	if (f.is_null()) {
 		return String();
 	}
 
@@ -672,6 +663,5 @@ String FileAccess::get_sha256(const String &p_file) {
 	unsigned char hash[32];
 	ctx.finish(hash);
 
-	memdelete(f);
 	return String::hex_encode_buffer(hash, 32);
 }

+ 7 - 29
core/io/file_access.h

@@ -32,6 +32,7 @@
 #define FILE_ACCESS_H
 
 #include "core/math/math_defs.h"
+#include "core/object/ref_counted.h"
 #include "core/os/memory.h"
 #include "core/string/ustring.h"
 #include "core/typedefs.h"
@@ -40,7 +41,7 @@
  * Multi-Platform abstraction for accessing to files.
  */
 
-class FileAccess {
+class FileAccess : public RefCounted {
 public:
 	enum AccessType {
 		ACCESS_RESOURCES,
@@ -51,7 +52,7 @@ public:
 
 	typedef void (*FileCloseFailNotify)(const String &);
 
-	typedef FileAccess *(*CreateFunc)();
+	typedef Ref<FileAccess> (*CreateFunc)();
 	bool big_endian = false;
 	bool real_is_double = false;
 
@@ -71,7 +72,7 @@ private:
 	AccessType _access_type = ACCESS_FILESYSTEM;
 	static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */
 	template <class T>
-	static FileAccess *_create_builtin() {
+	static Ref<FileAccess> _create_builtin() {
 		return memnew(T);
 	}
 
@@ -148,9 +149,9 @@ public:
 
 	virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
 
-	static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
-	static FileAccess *create_for_path(const String &p_path);
-	static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files.
+	static Ref<FileAccess> create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
+	static Ref<FileAccess> create_for_path(const String &p_path);
+	static Ref<FileAccess> open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files.
 	static CreateFunc get_create_func(AccessType p_access);
 	static bool exists(const String &p_name); ///< return true if a file exists
 	static uint64_t get_modified_time(const String &p_file);
@@ -176,27 +177,4 @@ public:
 	virtual ~FileAccess() {}
 };
 
-struct FileAccessRef {
-	_FORCE_INLINE_ FileAccess *operator->() {
-		return f;
-	}
-
-	operator bool() const { return f != nullptr; }
-
-	FileAccess *f = nullptr;
-
-	operator FileAccess *() { return f; }
-
-	FileAccessRef(FileAccess *fa) { f = fa; }
-	FileAccessRef(FileAccessRef &&other) {
-		f = other.f;
-		other.f = nullptr;
-	}
-	~FileAccessRef() {
-		if (f) {
-			memdelete(f);
-		}
-	}
-};
-
 #endif // FILE_ACCESS_H

+ 23 - 28
core/io/file_access_compressed.cpp

@@ -58,12 +58,12 @@ void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_
 		}                                                   \
 	}
 
-Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
+Error FileAccessCompressed::open_after_magic(Ref<FileAccess> p_base) {
 	f = p_base;
 	cmode = (Compression::Mode)f->get_32();
 	block_size = f->get_32();
 	if (block_size == 0) {
-		f = nullptr; // Let the caller to handle the FileAccess object if failed to open as compressed file.
+		f = Ref<FileAccess>();
 		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();
@@ -98,7 +98,7 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
 Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
 	ERR_FAIL_COND_V(p_mode_flags == READ_WRITE, ERR_UNAVAILABLE);
 
-	if (f) {
+	if (f.is_valid()) {
 		close();
 	}
 
@@ -106,8 +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 = nullptr;
+		f = Ref<FileAccess>();
 		return err;
 	}
 
@@ -127,8 +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) {
-			memdelete(f);
-			f = nullptr;
+			f = Ref<FileAccess>();
 			return err;
 		}
 	}
@@ -137,7 +135,7 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
 }
 
 void FileAccessCompressed::close() {
-	if (!f) {
+	if (f.is_null()) {
 		return;
 	}
 
@@ -182,17 +180,15 @@ void FileAccessCompressed::close() {
 		buffer.clear();
 		read_blocks.clear();
 	}
-
-	memdelete(f);
-	f = nullptr;
+	f = Ref<FileAccess>();
 }
 
 bool FileAccessCompressed::is_open() const {
-	return f != nullptr;
+	return f.is_valid();
 }
 
 void FileAccessCompressed::seek(uint64_t p_position) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
 
 	if (writing) {
 		ERR_FAIL_COND(p_position > write_max);
@@ -222,7 +218,7 @@ void FileAccessCompressed::seek(uint64_t p_position) {
 }
 
 void FileAccessCompressed::seek_end(int64_t p_position) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
 	if (writing) {
 		seek(write_max + p_position);
 	} else {
@@ -231,7 +227,7 @@ void FileAccessCompressed::seek_end(int64_t p_position) {
 }
 
 uint64_t FileAccessCompressed::get_position() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
 	if (writing) {
 		return write_pos;
 	} else {
@@ -240,7 +236,7 @@ uint64_t FileAccessCompressed::get_position() const {
 }
 
 uint64_t FileAccessCompressed::get_length() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
 	if (writing) {
 		return write_max;
 	} else {
@@ -249,7 +245,7 @@ uint64_t FileAccessCompressed::get_length() const {
 }
 
 bool FileAccessCompressed::eof_reached() const {
-	ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), false, "File must be opened before use.");
 	if (writing) {
 		return false;
 	} else {
@@ -258,7 +254,7 @@ bool FileAccessCompressed::eof_reached() const {
 }
 
 uint8_t FileAccessCompressed::get_8() const {
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
 	ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
 
 	if (at_end) {
@@ -291,7 +287,7 @@ uint8_t FileAccessCompressed::get_8() const {
 
 uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
 	ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
-	ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
 	ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
 
 	if (at_end) {
@@ -332,14 +328,14 @@ Error FileAccessCompressed::get_error() const {
 }
 
 void FileAccessCompressed::flush() {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
 	ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
 
 	// compressed files keep data in memory till close()
 }
 
 void FileAccessCompressed::store_8(uint8_t p_dest) {
-	ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+	ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
 	ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
 
 	WRITE_FIT(1);
@@ -347,16 +343,15 @@ void FileAccessCompressed::store_8(uint8_t p_dest) {
 }
 
 bool FileAccessCompressed::file_exists(const String &p_name) {
-	FileAccess *fa = FileAccess::open(p_name, FileAccess::READ);
-	if (!fa) {
+	Ref<FileAccess> fa = FileAccess::open(p_name, FileAccess::READ);
+	if (fa.is_null()) {
 		return false;
 	}
-	memdelete(fa);
 	return true;
 }
 
 uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
-	if (f) {
+	if (f.is_valid()) {
 		return f->get_modified_time(p_file);
 	} else {
 		return 0;
@@ -364,21 +359,21 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
 }
 
 uint32_t FileAccessCompressed::_get_unix_permissions(const String &p_file) {
-	if (f) {
+	if (f.is_valid()) {
 		return f->_get_unix_permissions(p_file);
 	}
 	return 0;
 }
 
 Error FileAccessCompressed::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
-	if (f) {
+	if (f.is_valid()) {
 		return f->_set_unix_permissions(p_file, p_permissions);
 	}
 	return FAILED;
 }
 
 FileAccessCompressed::~FileAccessCompressed() {
-	if (f) {
+	if (f.is_valid()) {
 		close();
 	}
 }

+ 2 - 2
core/io/file_access_compressed.h

@@ -61,12 +61,12 @@ class FileAccessCompressed : public FileAccess {
 
 	String magic = "GCMP";
 	mutable Vector<uint8_t> buffer;
-	FileAccess *f = nullptr;
+	Ref<FileAccess> f;
 
 public:
 	void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, uint32_t p_block_size = 4096);
 
-	Error open_after_magic(FileAccess *p_base);
+	Error open_after_magic(Ref<FileAccess> p_base);
 
 	virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
 	virtual void close(); ///< close a file

+ 11 - 13
core/io/file_access_encrypted.cpp

@@ -36,7 +36,7 @@
 
 #include <stdio.h>
 
-Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {
+Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {
 	ERR_FAIL_COND_V_MSG(file != nullptr, ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open.");
 	ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
 
@@ -99,7 +99,7 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8
 	return OK;
 }
 
-Error FileAccessEncrypted::open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode) {
+Error FileAccessEncrypted::open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode) {
 	String cs = p_key.md5_text();
 	ERR_FAIL_COND_V(cs.length() != 32, ERR_INVALID_PARAMETER);
 	Vector<uint8_t> key;
@@ -116,26 +116,25 @@ Error FileAccessEncrypted::_open(const String &p_path, int p_mode_flags) {
 }
 
 void FileAccessEncrypted::close() {
-	if (!file) {
+	if (file.is_null()) {
 		return;
 	}
 
 	_release();
 
 	file->close();
-	memdelete(file);
 
-	file = nullptr;
+	file = Ref<FileAccess>();
 }
 
 void FileAccessEncrypted::release() {
-	if (!file) {
+	if (file.is_null()) {
 		return;
 	}
 
 	_release();
 
-	file = nullptr;
+	file = Ref<FileAccess>();
 }
 
 void FileAccessEncrypted::_release() {
@@ -183,7 +182,7 @@ bool FileAccessEncrypted::is_open() const {
 }
 
 String FileAccessEncrypted::get_path() const {
-	if (file) {
+	if (file.is_valid()) {
 		return file->get_path();
 	} else {
 		return "";
@@ -191,7 +190,7 @@ String FileAccessEncrypted::get_path() const {
 }
 
 String FileAccessEncrypted::get_path_absolute() const {
-	if (file) {
+	if (file.is_valid()) {
 		return file->get_path_absolute();
 	} else {
 		return "";
@@ -291,11 +290,10 @@ void FileAccessEncrypted::store_8(uint8_t p_dest) {
 }
 
 bool FileAccessEncrypted::file_exists(const String &p_name) {
-	FileAccess *fa = FileAccess::open(p_name, FileAccess::READ);
-	if (!fa) {
+	Ref<FileAccess> fa = FileAccess::open(p_name, FileAccess::READ);
+	if (fa.is_null()) {
 		return false;
 	}
-	memdelete(fa);
 	return true;
 }
 
@@ -313,7 +311,7 @@ Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t
 }
 
 FileAccessEncrypted::~FileAccessEncrypted() {
-	if (file) {
+	if (file.is_valid()) {
 		close();
 	}
 }

+ 3 - 3
core/io/file_access_encrypted.h

@@ -46,7 +46,7 @@ public:
 private:
 	Vector<uint8_t> key;
 	bool writing = false;
-	FileAccess *file = nullptr;
+	Ref<FileAccess> file;
 	uint64_t base = 0;
 	uint64_t length = 0;
 	Vector<uint8_t> data;
@@ -57,8 +57,8 @@ private:
 	void _release();
 
 public:
-	Error open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true);
-	Error open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode);
+	Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true);
+	Error open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode);
 
 	virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
 	virtual void close(); ///< close a file

+ 1 - 1
core/io/file_access_memory.cpp

@@ -60,7 +60,7 @@ void FileAccessMemory::cleanup() {
 	memdelete(files);
 }
 
-FileAccess *FileAccessMemory::create() {
+Ref<FileAccess> FileAccessMemory::create() {
 	return memnew(FileAccessMemory);
 }
 

+ 1 - 1
core/io/file_access_memory.h

@@ -38,7 +38,7 @@ class FileAccessMemory : public FileAccess {
 	uint64_t length = 0;
 	mutable uint64_t pos = 0;
 
-	static FileAccess *create();
+	static Ref<FileAccess> create();
 
 public:
 	static void register_file(String p_name, Vector<uint8_t> p_data);

+ 16 - 53
core/io/file_access_pack.cpp

@@ -126,8 +126,8 @@ PackedData::~PackedData() {
 //////////////////////////////////////////////////////////////////
 
 bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	if (f.is_null()) {
 		return false;
 	}
 
@@ -137,19 +137,13 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
 
 	if (magic != PACK_HEADER_MAGIC) {
 		// loading with offset feature not supported for self contained exe files
-		if (p_offset != 0) {
-			f->close();
-			memdelete(f);
-			ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported.");
-		}
+		ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Loading self-contained executable with offset not supported.");
 
 		//maybe at the end.... self contained exe
 		f->seek_end();
 		f->seek(f->get_position() - 4);
 		magic = f->get_32();
 		if (magic != PACK_HEADER_MAGIC) {
-			f->close();
-			memdelete(f);
 			return false;
 		}
 		f->seek(f->get_position() - 12);
@@ -159,8 +153,6 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
 
 		magic = f->get_32();
 		if (magic != PACK_HEADER_MAGIC) {
-			f->close();
-			memdelete(f);
 			return false;
 		}
 	}
@@ -170,16 +162,8 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
 	uint32_t ver_minor = f->get_32();
 	f->get_32(); // patch number, not used for validation.
 
-	if (version != PACK_FORMAT_VERSION) {
-		f->close();
-		memdelete(f);
-		ERR_FAIL_V_MSG(false, "Pack version unsupported: " + itos(version) + ".");
-	}
-	if (ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR)) {
-		f->close();
-		memdelete(f);
-		ERR_FAIL_V_MSG(false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
-	}
+	ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, "Pack version unsupported: " + itos(version) + ".");
+	ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
 
 	uint32_t pack_flags = f->get_32();
 	uint64_t file_base = f->get_64();
@@ -194,12 +178,9 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
 	int file_count = f->get_32();
 
 	if (enc_directory) {
-		FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
-		if (!fae) {
-			f->close();
-			memdelete(f);
-			ERR_FAIL_V_MSG(false, "Can't open encrypted pack directory.");
-		}
+		Ref<FileAccessEncrypted> fae;
+		fae.instantiate();
+		ERR_FAIL_COND_V_MSG(fae.is_null(), false, "Can't open encrypted pack directory.");
 
 		Vector<uint8_t> key;
 		key.resize(32);
@@ -208,12 +189,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
 		}
 
 		Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
-		if (err) {
-			f->close();
-			memdelete(f);
-			memdelete(fae);
-			ERR_FAIL_V_MSG(false, "Can't open encrypted pack directory.");
-		}
+		ERR_FAIL_COND_V_MSG(err, false, "Can't open encrypted pack directory.");
 		f = fae;
 	}
 
@@ -236,12 +212,10 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
 		PackedData::get_singleton()->add_path(p_path, path, ofs + p_offset, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED));
 	}
 
-	f->close();
-	memdelete(f);
 	return true;
 }
 
-FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
+Ref<FileAccess> PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
 	return memnew(FileAccessPack(p_path, *p_file));
 }
 
@@ -351,16 +325,15 @@ bool FileAccessPack::file_exists(const String &p_name) {
 FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
 		pf(p_file),
 		f(FileAccess::open(pf.pack, FileAccess::READ)) {
-	ERR_FAIL_COND_MSG(!f, "Can't open pack-referenced file '" + String(pf.pack) + "'.");
+	ERR_FAIL_COND_MSG(f.is_null(), "Can't open pack-referenced file '" + String(pf.pack) + "'.");
 
 	f->seek(pf.offset);
 	off = pf.offset;
 
 	if (pf.encrypted) {
-		FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
-		if (!fae) {
-			ERR_FAIL_MSG("Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
-		}
+		Ref<FileAccessEncrypted> fae;
+		fae.instantiate();
+		ERR_FAIL_COND_MSG(fae.is_null(), "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
 
 		Vector<uint8_t> key;
 		key.resize(32);
@@ -369,10 +342,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
 		}
 
 		Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
-		if (err) {
-			memdelete(fae);
-			ERR_FAIL_MSG("Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
-		}
+		ERR_FAIL_COND_MSG(err, "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
 		f = fae;
 		off = 0;
 	}
@@ -380,13 +350,6 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
 	eof = false;
 }
 
-FileAccessPack::~FileAccessPack() {
-	if (f) {
-		f->close();
-		memdelete(f);
-	}
-}
-
 //////////////////////////////////////////////////////////////////////////////////
 // DIR ACCESS
 //////////////////////////////////////////////////////////////////////////////////
@@ -507,7 +470,7 @@ Error DirAccessPack::change_dir(String p_dir) {
 	}
 }
 
-String DirAccessPack::get_current_dir(bool p_include_drive) {
+String DirAccessPack::get_current_dir(bool p_include_drive) const {
 	PackedData::PackedDir *pd = current;
 	String p = current->name;
 

+ 12 - 16
core/io/file_access_pack.h

@@ -120,10 +120,10 @@ public:
 	static PackedData *get_singleton() { return singleton; }
 	Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
 
-	_FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
+	_FORCE_INLINE_ Ref<FileAccess> try_open_path(const String &p_path);
 	_FORCE_INLINE_ bool has_path(const String &p_path);
 
-	_FORCE_INLINE_ DirAccess *try_open_directory(const String &p_path);
+	_FORCE_INLINE_ Ref<DirAccess> try_open_directory(const String &p_path);
 	_FORCE_INLINE_ bool has_directory(const String &p_path);
 
 	PackedData();
@@ -133,14 +133,14 @@ public:
 class PackSource {
 public:
 	virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) = 0;
-	virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
+	virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
 	virtual ~PackSource() {}
 };
 
 class PackedSourcePCK : public PackSource {
 public:
 	virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) override;
-	virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) override;
+	virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file) override;
 };
 
 class FileAccessPack : public FileAccess {
@@ -150,7 +150,7 @@ class FileAccessPack : public FileAccess {
 	mutable bool eof;
 	uint64_t off;
 
-	FileAccess *f = nullptr;
+	Ref<FileAccess> f;
 	virtual Error _open(const String &p_path, int p_mode_flags);
 	virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
 	virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
@@ -183,10 +183,9 @@ public:
 	virtual bool file_exists(const String &p_name);
 
 	FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
-	~FileAccessPack();
 };
 
-FileAccess *PackedData::try_open_path(const String &p_path) {
+Ref<FileAccess> PackedData::try_open_path(const String &p_path) {
 	PathMD5 pmd5(p_path.md5_buffer());
 	Map<PathMD5, PackedFile>::Element *E = files.find(pmd5);
 	if (!E) {
@@ -204,9 +203,8 @@ bool PackedData::has_path(const String &p_path) {
 }
 
 bool PackedData::has_directory(const String &p_path) {
-	DirAccess *da = try_open_directory(p_path);
-	if (da) {
-		memdelete(da);
+	Ref<DirAccess> da = try_open_directory(p_path);
+	if (da.is_valid()) {
 		return true;
 	} else {
 		return false;
@@ -233,7 +231,7 @@ public:
 	virtual String get_drive(int p_drive);
 
 	virtual Error change_dir(String p_dir);
-	virtual String get_current_dir(bool p_include_drive = true);
+	virtual String get_current_dir(bool p_include_drive = true) const;
 
 	virtual bool file_exists(String p_file);
 	virtual bool dir_exists(String p_dir);
@@ -252,14 +250,12 @@ public:
 	virtual String get_filesystem_type() const;
 
 	DirAccessPack();
-	~DirAccessPack() {}
 };
 
-DirAccess *PackedData::try_open_directory(const String &p_path) {
-	DirAccess *da = memnew(DirAccessPack());
+Ref<DirAccess> PackedData::try_open_directory(const String &p_path) {
+	Ref<DirAccess> da = memnew(DirAccessPack());
 	if (da->change_dir(p_path) != OK) {
-		memdelete(da);
-		da = nullptr;
+		da = Ref<DirAccess>();
 	}
 	return da;
 }

+ 24 - 22
core/io/file_access_zip.cpp

@@ -38,20 +38,26 @@ ZipArchive *ZipArchive::instance = nullptr;
 
 extern "C" {
 
-static void *godot_open(void *data, const char *p_fname, int mode) {
+struct ZipData {
+	Ref<FileAccess> f;
+};
+
+static void *godot_open(voidpf opaque, const char *p_fname, int mode) {
 	if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
 		return nullptr;
 	}
 
-	FileAccess *f = FileAccess::open(p_fname, FileAccess::READ);
-	ERR_FAIL_COND_V(!f, nullptr);
+	Ref<FileAccess> f = FileAccess::open(p_fname, FileAccess::READ);
+	ERR_FAIL_COND_V(f.is_null(), nullptr);
 
-	return f;
+	ZipData *zd = memnew(ZipData);
+	zd->f = f;
+	return zd;
 }
 
-static uLong godot_read(void *data, void *fdata, void *buf, uLong size) {
-	FileAccess *f = (FileAccess *)fdata;
-	f->get_buffer((uint8_t *)buf, size);
+static uLong godot_read(voidpf opaque, voidpf stream, void *buf, uLong size) {
+	ZipData *zd = (ZipData *)stream;
+	zd->f->get_buffer((uint8_t *)buf, size);
 	return size;
 }
 
@@ -60,42 +66,38 @@ static uLong godot_write(voidpf opaque, voidpf stream, const void *buf, uLong si
 }
 
 static long godot_tell(voidpf opaque, voidpf stream) {
-	FileAccess *f = (FileAccess *)stream;
-	return f->get_position();
+	ZipData *zd = (ZipData *)stream;
+	return zd->f->get_position();
 }
 
 static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
-	FileAccess *f = (FileAccess *)stream;
+	ZipData *zd = (ZipData *)stream;
 
 	uint64_t pos = offset;
 	switch (origin) {
 		case ZLIB_FILEFUNC_SEEK_CUR:
-			pos = f->get_position() + offset;
+			pos = zd->f->get_position() + offset;
 			break;
 		case ZLIB_FILEFUNC_SEEK_END:
-			pos = f->get_length() + offset;
+			pos = zd->f->get_length() + offset;
 			break;
 		default:
 			break;
 	}
 
-	f->seek(pos);
+	zd->f->seek(pos);
 	return 0;
 }
 
 static int godot_close(voidpf opaque, voidpf stream) {
-	FileAccess *f = (FileAccess *)stream;
-	if (f) {
-		f->close();
-		memdelete(f);
-		f = nullptr;
-	}
+	ZipData *zd = (ZipData *)stream;
+	memdelete(zd);
 	return 0;
 }
 
 static int godot_testerror(voidpf opaque, voidpf stream) {
-	FileAccess *f = (FileAccess *)stream;
-	return f->get_error() != OK ? 1 : 0;
+	ZipData *zd = (ZipData *)stream;
+	return zd->f->get_error() != OK ? 1 : 0;
 }
 
 static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
@@ -208,7 +210,7 @@ bool ZipArchive::file_exists(String p_name) const {
 	return files.has(p_name);
 }
 
-FileAccess *ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) {
+Ref<FileAccess> ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) {
 	return memnew(FileAccessZip(p_path, *p_file));
 }
 

+ 1 - 1
core/io/file_access_zip.h

@@ -68,7 +68,7 @@ public:
 	bool file_exists(String p_name) const;
 
 	virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) override;
-	FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) override;
+	Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file) override;
 
 	static ZipArchive *get_singleton();
 

+ 6 - 21
core/io/image_loader.cpp

@@ -44,17 +44,14 @@ bool ImageFormatLoader::recognize(const String &p_extension) const {
 	return false;
 }
 
-Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom, bool p_force_linear, float p_scale) {
+Error ImageLoader::load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom, bool p_force_linear, float p_scale) {
 	ERR_FAIL_COND_V_MSG(p_image.is_null(), ERR_INVALID_PARAMETER, "It's not a reference to a valid Image object.");
 
-	FileAccess *f = p_custom;
-	if (!f) {
+	Ref<FileAccess> f = p_custom;
+	if (f.is_null()) {
 		Error err;
 		f = FileAccess::open(p_file, FileAccess::READ, &err);
-		if (!f) {
-			ERR_PRINT("Error opening file '" + p_file + "'.");
-			return err;
-		}
+		ERR_FAIL_COND_V_MSG(f.is_null(), err, "Error opening file '" + p_file + "'.");
 	}
 
 	String extension = p_file.get_extension();
@@ -69,18 +66,10 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c
 		}
 
 		if (err != ERR_FILE_UNRECOGNIZED) {
-			if (!p_custom) {
-				memdelete(f);
-			}
-
 			return err;
 		}
 	}
 
-	if (!p_custom) {
-		memdelete(f);
-	}
-
 	return ERR_FILE_UNRECOGNIZED;
 }
 
@@ -123,8 +112,8 @@ void ImageLoader::cleanup() {
 /////////////////
 
 RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	if (f.is_null()) {
 		if (r_error) {
 			*r_error = ERR_CANT_OPEN;
 		}
@@ -136,7 +125,6 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
 
 	bool unrecognized = header[0] != 'G' || header[1] != 'D' || header[2] != 'I' || header[3] != 'M';
 	if (unrecognized) {
-		memdelete(f);
 		if (r_error) {
 			*r_error = ERR_FILE_UNRECOGNIZED;
 		}
@@ -155,7 +143,6 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
 	}
 
 	if (idx == -1) {
-		memdelete(f);
 		if (r_error) {
 			*r_error = ERR_FILE_UNRECOGNIZED;
 		}
@@ -167,8 +154,6 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
 
 	Error err = ImageLoader::loader[idx]->load_image(image, f, false, 1.0);
 
-	memdelete(f);
-
 	if (err != OK) {
 		if (r_error) {
 			*r_error = err;

+ 2 - 2
core/io/image_loader.h

@@ -44,7 +44,7 @@ class ImageFormatLoader {
 	friend class ResourceFormatLoaderImage;
 
 protected:
-	virtual Error load_image(Ref<Image> p_image, FileAccess *p_fileaccess, bool p_force_linear, float p_scale) = 0;
+	virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, bool p_force_linear, float p_scale) = 0;
 	virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
 	bool recognize(const String &p_extension) const;
 
@@ -58,7 +58,7 @@ class ImageLoader {
 
 protected:
 public:
-	static Error load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom = nullptr, bool p_force_linear = false, float p_scale = 1.0);
+	static Error load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom = Ref<FileAccess>(), bool p_force_linear = false, float p_scale = 1.0);
 	static void get_recognized_extensions(List<String> *p_extensions);
 	static ImageFormatLoader *recognize(const String &p_extension);
 

+ 9 - 19
core/io/logger.cpp

@@ -115,21 +115,14 @@ void Logger::logf_error(const char *p_format, ...) {
 	va_end(argp);
 }
 
-void RotatedFileLogger::close_file() {
-	if (file) {
-		memdelete(file);
-		file = nullptr;
-	}
-}
-
 void RotatedFileLogger::clear_old_backups() {
 	int max_backups = max_files - 1; // -1 for the current file
 
 	String basename = base_path.get_file().get_basename();
 	String extension = base_path.get_extension();
 
-	DirAccessRef da = DirAccess::open(base_path.get_base_dir());
-	if (!da) {
+	Ref<DirAccess> da = DirAccess::open(base_path.get_base_dir());
+	if (da.is_null()) {
 		return;
 	}
 
@@ -155,7 +148,7 @@ void RotatedFileLogger::clear_old_backups() {
 }
 
 void RotatedFileLogger::rotate_file() {
-	close_file();
+	file = Ref<FileAccess>();
 
 	if (FileAccess::exists(base_path)) {
 		if (max_files > 1) {
@@ -165,20 +158,21 @@ void RotatedFileLogger::rotate_file() {
 				backup_name += "." + base_path.get_extension();
 			}
 
-			DirAccessRef da = DirAccess::open(base_path.get_base_dir());
-			if (da) {
+			Ref<DirAccess> da = DirAccess::open(base_path.get_base_dir());
+			if (da.is_valid()) {
 				da->copy(base_path, backup_name);
 			}
 			clear_old_backups();
 		}
 	} else {
-		DirAccessRef da = DirAccess::create(DirAccess::ACCESS_USERDATA);
-		if (da) {
+		Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_USERDATA);
+		if (da.is_valid()) {
 			da->make_dir_recursive(base_path.get_base_dir());
 		}
 	}
 
 	file = FileAccess::open(base_path, FileAccess::WRITE);
+	file->detach_from_objectdb(); // Note: This FileAccess instance will exist longer than ObjectDB, therefor can't be registered in ObjectDB.
 }
 
 RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) :
@@ -192,7 +186,7 @@ void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
 		return;
 	}
 
-	if (file) {
+	if (file.is_valid()) {
 		const int static_buf_size = 512;
 		char static_buf[static_buf_size];
 		char *buf = static_buf;
@@ -218,10 +212,6 @@ void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
 	}
 }
 
-RotatedFileLogger::~RotatedFileLogger() {
-	close_file();
-}
-
 void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
 	if (!should_log(p_err)) {
 		return;

+ 1 - 4
core/io/logger.h

@@ -81,9 +81,8 @@ class RotatedFileLogger : public Logger {
 	String base_path;
 	int max_files;
 
-	FileAccess *file = nullptr;
+	Ref<FileAccess> file;
 
-	void close_file();
 	void clear_old_backups();
 	void rotate_file();
 
@@ -91,8 +90,6 @@ public:
 	RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
 
 	virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
-
-	virtual ~RotatedFileLogger();
 };
 
 class CompositeLogger : public Logger {

+ 16 - 35
core/io/pck_packer.cpp

@@ -83,13 +83,8 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
 	}
 	enc_dir = p_encrypt_directory;
 
-	if (file != nullptr) {
-		memdelete(file);
-	}
-
 	file = FileAccess::open(p_file, FileAccess::WRITE);
-
-	ERR_FAIL_COND_V_MSG(!file, ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
+	ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
 
 	alignment = p_alignment;
 
@@ -112,8 +107,8 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
 }
 
 Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encrypt) {
-	FileAccess *f = FileAccess::open(p_src, FileAccess::READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ);
+	if (f.is_null()) {
 		return ERR_FILE_CANT_OPEN;
 	}
 
@@ -149,14 +144,11 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encr
 
 	files.push_back(pf);
 
-	f->close();
-	memdelete(f);
-
 	return OK;
 }
 
 Error PCKPacker::flush(bool p_verbose) {
-	ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use.");
+	ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use.");
 
 	int64_t file_base_ofs = file->get_position();
 	file->store_64(0); // files base
@@ -168,12 +160,12 @@ Error PCKPacker::flush(bool p_verbose) {
 	// write the index
 	file->store_32(files.size());
 
-	FileAccessEncrypted *fae = nullptr;
-	FileAccess *fhead = file;
+	Ref<FileAccessEncrypted> fae;
+	Ref<FileAccess> fhead = file;
 
 	if (enc_dir) {
-		fae = memnew(FileAccessEncrypted);
-		ERR_FAIL_COND_V(!fae, ERR_CANT_CREATE);
+		fae.instantiate();
+		ERR_FAIL_COND_V(fae.is_null(), ERR_CANT_CREATE);
 
 		Error err = fae->open_and_parse(file, key, FileAccessEncrypted::MODE_WRITE_AES256, false);
 		ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
@@ -202,9 +194,8 @@ Error PCKPacker::flush(bool p_verbose) {
 		fhead->store_32(flags);
 	}
 
-	if (fae) {
+	if (fae.is_valid()) {
 		fae->release();
-		memdelete(fae);
 	}
 
 	int header_padding = _get_pad(alignment, file->get_position());
@@ -222,14 +213,14 @@ Error PCKPacker::flush(bool p_verbose) {
 
 	int count = 0;
 	for (int i = 0; i < files.size(); i++) {
-		FileAccess *src = FileAccess::open(files[i].src_path, FileAccess::READ);
+		Ref<FileAccess> src = FileAccess::open(files[i].src_path, FileAccess::READ);
 		uint64_t to_write = files[i].size;
 
-		fae = nullptr;
-		FileAccess *ftmp = file;
+		fae = Ref<FileAccess>();
+		Ref<FileAccess> ftmp = file;
 		if (files[i].encrypted) {
-			fae = memnew(FileAccessEncrypted);
-			ERR_FAIL_COND_V(!fae, ERR_CANT_CREATE);
+			fae.instantiate();
+			ERR_FAIL_COND_V(fae.is_null(), ERR_CANT_CREATE);
 
 			Error err = fae->open_and_parse(file, key, FileAccessEncrypted::MODE_WRITE_AES256, false);
 			ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
@@ -242,9 +233,8 @@ Error PCKPacker::flush(bool p_verbose) {
 			to_write -= read;
 		}
 
-		if (fae) {
+		if (fae.is_valid()) {
 			fae->release();
-			memdelete(fae);
 		}
 
 		int pad = _get_pad(alignment, file->get_position());
@@ -252,8 +242,6 @@ Error PCKPacker::flush(bool p_verbose) {
 			file->store_8(Math::rand() % 256);
 		}
 
-		src->close();
-		memdelete(src);
 		count += 1;
 		const int file_num = files.size();
 		if (p_verbose && (file_num > 0)) {
@@ -265,15 +253,8 @@ Error PCKPacker::flush(bool p_verbose) {
 		printf("\n");
 	}
 
-	file->close();
+	file = Ref<FileAccess>();
 	memdelete_arr(buf);
 
 	return OK;
 }
-
-PCKPacker::~PCKPacker() {
-	if (file != nullptr) {
-		memdelete(file);
-	}
-	file = nullptr;
-}

+ 1 - 2
core/io/pck_packer.h

@@ -38,7 +38,7 @@ class FileAccess;
 class PCKPacker : public RefCounted {
 	GDCLASS(PCKPacker, RefCounted);
 
-	FileAccess *file = nullptr;
+	Ref<FileAccess> file;
 	int alignment = 0;
 	uint64_t ofs = 0;
 
@@ -63,7 +63,6 @@ public:
 	Error flush(bool p_verbose = false);
 
 	PCKPacker() {}
-	~PCKPacker();
 };
 
 #endif // PCK_PACKER_H

+ 4 - 8
core/io/resource.cpp

@@ -538,10 +538,10 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
 
 	Map<String, int> type_count;
 
-	FileAccess *f = nullptr;
+	Ref<FileAccess> f;
 	if (p_file) {
 		f = FileAccess::open(String::utf8(p_file), FileAccess::WRITE);
-		ERR_FAIL_COND_MSG(!f, "Cannot create file at path '" + String::utf8(p_file) + "'.");
+		ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file at path '" + String::utf8(p_file) + "'.");
 	}
 
 	const String *K = nullptr;
@@ -555,21 +555,17 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
 		type_count[r->get_class()]++;
 
 		if (!p_short) {
-			if (f) {
+			if (f.is_valid()) {
 				f->store_line(r->get_class() + ": " + r->get_path());
 			}
 		}
 	}
 
 	for (const KeyValue<String, int> &E : type_count) {
-		if (f) {
+		if (f.is_valid()) {
 			f->store_line(E.key + " count: " + itos(E.value));
 		}
 	}
-	if (f) {
-		f->close();
-		memdelete(f);
-	}
 
 	lock.read_unlock();
 #else

+ 52 - 85
core/io/resource_format_binary.cpp

@@ -101,11 +101,11 @@ void ResourceLoaderBinary::_advance_padding(uint32_t p_len) {
 	}
 }
 
-static Error read_reals(real_t *dst, FileAccess &f, size_t count) {
-	if (f.real_is_double) {
+static Error read_reals(real_t *dst, Ref<FileAccess> &f, size_t count) {
+	if (f->real_is_double) {
 		if (sizeof(real_t) == 8) {
 			// Ideal case with double-precision
-			f.get_buffer((uint8_t *)dst, count * sizeof(double));
+			f->get_buffer((uint8_t *)dst, count * sizeof(double));
 #ifdef BIG_ENDIAN_ENABLED
 			{
 				uint64_t *dst = (uint64_t *)dst;
@@ -117,7 +117,7 @@ static Error read_reals(real_t *dst, FileAccess &f, size_t count) {
 		} else if (sizeof(real_t) == 4) {
 			// May be slower, but this is for compatibility. Eventually the data should be converted.
 			for (size_t i = 0; i < count; ++i) {
-				dst[i] = f.get_double();
+				dst[i] = f->get_double();
 			}
 		} else {
 			ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "real_t size is neither 4 nor 8!");
@@ -125,7 +125,7 @@ static Error read_reals(real_t *dst, FileAccess &f, size_t count) {
 	} else {
 		if (sizeof(real_t) == 4) {
 			// Ideal case with float-precision
-			f.get_buffer((uint8_t *)dst, count * sizeof(float));
+			f->get_buffer((uint8_t *)dst, count * sizeof(float));
 #ifdef BIG_ENDIAN_ENABLED
 			{
 				uint32_t *dst = (uint32_t *)dst;
@@ -136,7 +136,7 @@ static Error read_reals(real_t *dst, FileAccess &f, size_t count) {
 #endif
 		} else if (sizeof(real_t) == 8) {
 			for (size_t i = 0; i < count; ++i) {
-				dst[i] = f.get_float();
+				dst[i] = f->get_float();
 			}
 		} else {
 			ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "real_t size is neither 4 nor 8!");
@@ -573,7 +573,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
 			array.resize(len);
 			Vector2 *w = array.ptrw();
 			static_assert(sizeof(Vector2) == 2 * sizeof(real_t));
-			const Error err = read_reals(reinterpret_cast<real_t *>(w), *f, len * 2);
+			const Error err = read_reals(reinterpret_cast<real_t *>(w), f, len * 2);
 			ERR_FAIL_COND_V(err != OK, err);
 
 			r_v = array;
@@ -586,7 +586,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
 			array.resize(len);
 			Vector3 *w = array.ptrw();
 			static_assert(sizeof(Vector3) == 3 * sizeof(real_t));
-			const Error err = read_reals(reinterpret_cast<real_t *>(w), *f, len * 3);
+			const Error err = read_reals(reinterpret_cast<real_t *>(w), f, len * 3);
 			ERR_FAIL_COND_V(err != OK, err);
 
 			r_v = array;
@@ -789,7 +789,7 @@ Error ResourceLoaderBinary::load() {
 		resource_cache.push_back(res);
 
 		if (main) {
-			f->close();
+			f = Ref<FileAccess>();
 			resource = res;
 			resource->set_as_translation_remapped(translation_remapped);
 			error = OK;
@@ -804,13 +804,13 @@ void ResourceLoaderBinary::set_translation_remapped(bool p_remapped) {
 	translation_remapped = p_remapped;
 }
 
-static void save_ustring(FileAccess *f, const String &p_string) {
+static void save_ustring(Ref<FileAccess> f, const String &p_string) {
 	CharString utf8 = p_string.utf8();
 	f->store_32(utf8.length() + 1);
 	f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
 }
 
-static String get_ustring(FileAccess *f) {
+static String get_ustring(Ref<FileAccess> f) {
 	int len = f->get_32();
 	Vector<char> str_buf;
 	str_buf.resize(len);
@@ -834,7 +834,7 @@ String ResourceLoaderBinary::get_unicode_string() {
 	return s;
 }
 
-void ResourceLoaderBinary::get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types) {
+void ResourceLoaderBinary::get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types) {
 	open(p_f, false, true);
 	if (error) {
 		return;
@@ -856,7 +856,7 @@ void ResourceLoaderBinary::get_dependencies(FileAccess *p_f, List<String> *p_dep
 	}
 }
 
-void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_keep_uuid_paths) {
+void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p_keep_uuid_paths) {
 	error = OK;
 
 	f = p_f;
@@ -864,11 +864,11 @@ void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_kee
 	f->get_buffer(header, 4);
 	if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
 		// Compressed.
-		FileAccessCompressed *fac = memnew(FileAccessCompressed);
+		Ref<FileAccessCompressed> fac;
+		fac.instantiate();
 		error = fac->open_after_magic(f);
 		if (error != OK) {
-			memdelete(fac);
-			f->close();
+			f = Ref<FileAccess>();
 			ERR_FAIL_MSG("Failed to open binary resource file: " + local_path + ".");
 		}
 		f = fac;
@@ -876,7 +876,7 @@ void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_kee
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 		// Not normal.
 		error = ERR_FILE_UNRECOGNIZED;
-		f->close();
+		f = Ref<FileAccess>();
 		ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + ".");
 	}
 
@@ -901,7 +901,7 @@ void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_kee
 	print_bl("format: " + itos(ver_format));
 
 	if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
-		f->close();
+		f = Ref<FileAccess>();
 		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,12 +978,11 @@ void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_kee
 
 	if (f->eof_reached()) {
 		error = ERR_FILE_CORRUPT;
-		f->close();
 		ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + ".");
 	}
 }
 
-String ResourceLoaderBinary::recognize(FileAccess *p_f) {
+String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) {
 	error = OK;
 
 	f = p_f;
@@ -991,11 +990,11 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) {
 	f->get_buffer(header, 4);
 	if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
 		// Compressed.
-		FileAccessCompressed *fac = memnew(FileAccessCompressed);
+		Ref<FileAccessCompressed> fac;
+		fac.instantiate();
 		error = fac->open_after_magic(f);
 		if (error != OK) {
-			memdelete(fac);
-			f->close();
+			f = Ref<FileAccess>();
 			return "";
 		}
 		f = fac;
@@ -1003,7 +1002,7 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) {
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 		// Not normal.
 		error = ERR_FILE_UNRECOGNIZED;
-		f->close();
+		f = Ref<FileAccess>();
 		return "";
 	}
 
@@ -1017,7 +1016,7 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) {
 	uint32_t ver_format = f->get_32();
 
 	if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
-		f->close();
+		f = Ref<FileAccess>();
 		return "";
 	}
 
@@ -1026,19 +1025,13 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) {
 	return type;
 }
 
-ResourceLoaderBinary::~ResourceLoaderBinary() {
-	if (f) {
-		memdelete(f);
-	}
-}
-
 RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
 	if (r_error) {
 		*r_error = ERR_FILE_CANT_OPEN;
 	}
 
 	Error err;
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
 
 	ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot open file '" + p_path + "'.");
 
@@ -1096,8 +1089,8 @@ bool ResourceFormatLoaderBinary::handles_type(const String &p_type) const {
 }
 
 void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_MSG(!f, "Cannot open file '" + p_path + "'.");
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_path + "'.");
 
 	ResourceLoaderBinary loader;
 	loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
@@ -1106,10 +1099,10 @@ void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<Str
 }
 
 Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
 
-	FileAccess *fw = nullptr;
+	Ref<FileAccess> fw;
 
 	String local_path = p_path.get_base_dir();
 
@@ -1117,36 +1110,26 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 	f->get_buffer(header, 4);
 	if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
 		// Compressed.
-		FileAccessCompressed *fac = memnew(FileAccessCompressed);
+		Ref<FileAccessCompressed> fac;
+		fac.instantiate();
 		Error err = fac->open_after_magic(f);
-		if (err != OK) {
-			memdelete(fac);
-			memdelete(f);
-			ERR_FAIL_V_MSG(err, "Cannot open file '" + p_path + "'.");
-		}
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
 		f = fac;
 
-		FileAccessCompressed *facw = memnew(FileAccessCompressed);
+		Ref<FileAccessCompressed> facw;
+		facw.instantiate();
 		facw->configure("RSCC");
 		err = facw->_open(p_path + ".depren", FileAccess::WRITE);
-		if (err) {
-			memdelete(fac);
-			memdelete(facw);
-			ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".depren'.");
-		}
+		ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".depren'.");
 
 		fw = facw;
 
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 		// Not normal.
-		memdelete(f);
 		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file '" + local_path + "'.");
 	} else {
 		fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
-		if (!fw) {
-			memdelete(f);
-		}
-		ERR_FAIL_COND_V_MSG(!fw, ERR_CANT_CREATE, "Cannot create file '" + p_path + ".depren'.");
+		ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + ".depren'.");
 
 		uint8_t magic[4] = { 'R', 'S', 'R', 'C' };
 		fw->store_buffer(magic, 4);
@@ -1169,10 +1152,8 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 	uint32_t ver_format = f->get_32();
 
 	if (ver_format < FORMAT_VERSION_CAN_RENAME_DEPS) {
-		memdelete(f);
-		memdelete(fw);
 		{
-			DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+			Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 			da->remove(p_path + ".depren");
 		}
 
@@ -1201,8 +1182,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 	}
 
 	if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
-		memdelete(f);
-		memdelete(fw);
 		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED,
 				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));
@@ -1311,22 +1290,19 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 	fw->seek(md_ofs);
 	fw->store_64(importmd_ofs + size_diff);
 
-	memdelete(f);
-	memdelete(fw);
-
 	if (!all_ok) {
 		return ERR_CANT_CREATE;
 	}
 
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	da->remove(p_path);
 	da->rename(p_path + ".depren", p_path);
 	return OK;
 }
 
 String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const {
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	if (f.is_null()) {
 		return ""; //could not read
 	}
 
@@ -1343,8 +1319,8 @@ ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_pat
 		return ResourceUID::INVALID_ID;
 	}
 
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	if (f.is_null()) {
 		return ResourceUID::INVALID_ID; //could not read
 	}
 
@@ -1362,7 +1338,7 @@ ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_pat
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes) {
+void ResourceFormatSaverBinaryInstance::_pad_buffer(Ref<FileAccess> f, int p_bytes) {
 	int extra = 4 - (p_bytes % 4);
 	if (extra < 4) {
 		for (int i = 0; i < extra; i++) {
@@ -1371,7 +1347,7 @@ void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes)
 	}
 }
 
-void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
+void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
 	switch (p_property.get_type()) {
 		case Variant::NIL: {
 			f->store_32(VARIANT_NIL);
@@ -1830,14 +1806,14 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
 	}
 }
 
-void ResourceFormatSaverBinaryInstance::save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len) {
+void ResourceFormatSaverBinaryInstance::save_unicode_string(Ref<FileAccess> p_f, const String &p_string, bool p_bit_on_len) {
 	CharString utf8 = p_string.utf8();
 	if (p_bit_on_len) {
-		f->store_32((utf8.length() + 1) | 0x80000000);
+		p_f->store_32((utf8.length() + 1) | 0x80000000);
 	} else {
-		f->store_32(utf8.length() + 1);
+		p_f->store_32(utf8.length() + 1);
 	}
-	f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
+	p_f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
 }
 
 int ResourceFormatSaverBinaryInstance::get_string_index(const String &p_string) {
@@ -1853,15 +1829,13 @@ int ResourceFormatSaverBinaryInstance::get_string_index(const String &p_string)
 
 Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
 	Error err;
+	Ref<FileAccess> f;
 	if (p_flags & ResourceSaver::FLAG_COMPRESS) {
-		FileAccessCompressed *fac = memnew(FileAccessCompressed);
+		Ref<FileAccessCompressed> fac;
+		fac.instantiate();
 		fac->configure("RSCC");
 		f = fac;
 		err = fac->_open(p_path, FileAccess::WRITE);
-		if (err) {
-			memdelete(f);
-		}
-
 	} else {
 		f = FileAccess::open(p_path, FileAccess::WRITE, &err);
 	}
@@ -1902,8 +1876,6 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
 	f->store_32(FORMAT_VERSION);
 
 	if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
-		f->close();
-		memdelete(f);
 		return ERR_CANT_CREATE;
 	}
 
@@ -2061,14 +2033,9 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
 	f->store_buffer((const uint8_t *)"RSRC", 4); //magic at end
 
 	if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
-		f->close();
-		memdelete(f);
 		return ERR_CANT_CREATE;
 	}
 
-	f->close();
-	memdelete(f);
-
 	return OK;
 }
 

+ 7 - 9
core/io/resource_format_binary.h

@@ -43,7 +43,7 @@ class ResourceLoaderBinary {
 	Ref<Resource> resource;
 	uint32_t ver_format = 0;
 
-	FileAccess *f = nullptr;
+	Ref<FileAccess> f;
 
 	uint64_t importmd_ofs = 0;
 
@@ -98,12 +98,11 @@ public:
 	void set_translation_remapped(bool p_remapped);
 
 	void set_remaps(const Map<String, String> &p_remaps) { remaps = p_remaps; }
-	void open(FileAccess *p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false);
-	String recognize(FileAccess *p_f);
-	void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
+	void open(Ref<FileAccess> p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false);
+	String recognize(Ref<FileAccess> p_f);
+	void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types);
 
 	ResourceLoaderBinary() {}
-	~ResourceLoaderBinary();
 };
 
 class ResourceFormatLoaderBinary : public ResourceFormatLoader {
@@ -127,7 +126,6 @@ class ResourceFormatSaverBinaryInstance {
 	bool skip_editor;
 	bool big_endian;
 	bool takeover_paths;
-	FileAccess *f = nullptr;
 	String magic;
 	Set<RES> resource_set;
 
@@ -155,9 +153,9 @@ class ResourceFormatSaverBinaryInstance {
 		List<Property> properties;
 	};
 
-	static void _pad_buffer(FileAccess *f, int p_bytes);
+	static void _pad_buffer(Ref<FileAccess> f, int p_bytes);
 	void _find_resources(const Variant &p_variant, bool p_main = false);
-	static void save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false);
+	static void save_unicode_string(Ref<FileAccess> f, const String &p_string, bool p_bit_on_len = false);
 	int get_string_index(const String &p_string);
 
 public:
@@ -170,7 +168,7 @@ public:
 		RESERVED_FIELDS = 11
 	};
 	Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
-	static void write_variant(FileAccess *f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
+	static void write_variant(Ref<FileAccess> f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
 };
 
 class ResourceFormatSaverBinary : public ResourceFormatSaver {

+ 4 - 11
core/io/resource_importer.cpp

@@ -40,9 +40,9 @@ bool ResourceFormatImporter::SortImporterByName::operator()(const Ref<ResourceIm
 
 Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid) const {
 	Error err;
-	FileAccess *f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
 
-	if (!f) {
+	if (f.is_null()) {
 		if (r_valid) {
 			*r_valid = false;
 		}
@@ -70,11 +70,9 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
 
 		err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true);
 		if (err == ERR_FILE_EOF) {
-			memdelete(f);
 			return OK;
 		} else if (err != OK) {
 			ERR_PRINT("ResourceFormatImporter::load - " + p_path + ".import:" + itos(lines) + " error: " + error_text);
-			memdelete(f);
 			return err;
 		}
 
@@ -110,8 +108,6 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
 		}
 	}
 
-	memdelete(f);
-
 	if (r_path_and_type.path.is_empty() || r_path_and_type.type.is_empty()) {
 		return ERR_FILE_CORRUPT;
 	}
@@ -270,9 +266,9 @@ String ResourceFormatImporter::get_internal_resource_path(const String &p_path)
 
 void ResourceFormatImporter::get_internal_resource_path_list(const String &p_path, List<String> *r_paths) {
 	Error err;
-	FileAccess *f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
 
-	if (!f) {
+	if (f.is_null()) {
 		return;
 	}
 
@@ -292,11 +288,9 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
 
 		err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true);
 		if (err == ERR_FILE_EOF) {
-			memdelete(f);
 			return;
 		} else if (err != OK) {
 			ERR_PRINT("ResourceFormatImporter::get_internal_resource_path_list - " + p_path + ".import:" + itos(lines) + " error: " + error_text);
-			memdelete(f);
 			return;
 		}
 
@@ -310,7 +304,6 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
 			break;
 		}
 	}
-	memdelete(f);
 }
 
 String ResourceFormatImporter::get_import_group_file(const String &p_path) const {

+ 3 - 6
core/io/resource_loader.cpp

@@ -206,7 +206,7 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c
 			vformat("Failed loading resource: %s. Make sure resources have been imported by opening the project in the editor at least once.", p_path));
 
 #ifdef TOOLS_ENABLED
-	FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
+	Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
 	ERR_FAIL_COND_V_MSG(!file_check->file_exists(p_path), RES(), "Resource file not found: " + p_path + ".");
 #endif
 
@@ -817,9 +817,8 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
 	if (new_path == p_path) { // Did not remap.
 		// Try file remap.
 		Error err;
-		FileAccess *f = FileAccess::open(p_path + ".remap", FileAccess::READ, &err);
-
-		if (f) {
+		Ref<FileAccess> f = FileAccess::open(p_path + ".remap", FileAccess::READ, &err);
+		if (f.is_valid()) {
 			VariantParser::StreamFile stream;
 			stream.f = f;
 
@@ -849,8 +848,6 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
 					break;
 				}
 			}
-
-			memdelete(f);
 		}
 	}
 

+ 8 - 10
core/io/resource_uid.cpp

@@ -135,12 +135,12 @@ void ResourceUID::remove_id(ID p_id) {
 Error ResourceUID::save_to_cache() {
 	String cache_file = get_cache_file();
 	if (!FileAccess::exists(cache_file)) {
-		DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 		d->make_dir_recursive(String(cache_file).get_base_dir()); //ensure base dir exists
 	}
 
-	FileAccessRef f = FileAccess::open(cache_file, FileAccess::WRITE);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(cache_file, FileAccess::WRITE);
+	if (f.is_null()) {
 		return ERR_CANT_OPEN;
 	}
 
@@ -163,8 +163,8 @@ Error ResourceUID::save_to_cache() {
 }
 
 Error ResourceUID::load_from_cache() {
-	FileAccessRef f = FileAccess::open(get_cache_file(), FileAccess::READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(get_cache_file(), FileAccess::READ);
+	if (f.is_null()) {
 		return ERR_CANT_OPEN;
 	}
 
@@ -201,12 +201,12 @@ Error ResourceUID::update_cache() {
 	}
 	MutexLock l(mutex);
 
-	FileAccess *f = nullptr;
+	Ref<FileAccess> f;
 	for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
 		if (!E.get().saved_to_cache) {
-			if (f == nullptr) {
+			if (f.is_null()) {
 				f = FileAccess::open(get_cache_file(), FileAccess::READ_WRITE); //append
-				if (!f) {
+				if (f.is_null()) {
 					return ERR_CANT_OPEN;
 				}
 				f->seek_end();
@@ -223,8 +223,6 @@ Error ResourceUID::update_cache() {
 	if (f != nullptr) {
 		f->seek(0);
 		f->store_32(cache_entries); //update amount of entries
-		f->close();
-		memdelete(f);
 	}
 
 	changed = false;

+ 14 - 53
core/io/translation_loader_po.cpp

@@ -34,7 +34,7 @@
 #include "core/string/translation.h"
 #include "core/string/translation_po.h"
 
-RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
+RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
 	if (r_error) {
 		*r_error = ERR_FILE_CORRUPT;
 	}
@@ -49,9 +49,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 
 		uint16_t version_maj = f->get_16();
 		uint16_t version_min = f->get_16();
-		if (version_maj > 1) {
-			ERR_FAIL_V_MSG(RES(), vformat("Unsupported MO file %s, version %d.%d.", path, version_maj, version_min));
-		}
+		ERR_FAIL_COND_V_MSG(version_maj > 1, RES(), vformat("Unsupported MO file %s, version %d.%d.", path, version_maj, version_min));
 
 		uint32_t num_strings = f->get_32();
 		uint32_t id_table_offset = f->get_32();
@@ -134,7 +132,6 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 			}
 		}
 
-		memdelete(f);
 	} else {
 		// Try to load as text PO file.
 		f->seek(0);
@@ -173,7 +170,6 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 			// If we reached last line and it's not a content line, break, otherwise let processing that last loop
 			if (is_eof && l.is_empty()) {
 				if (status == STATUS_READING_ID || status == STATUS_READING_CONTEXT || (status == STATUS_READING_PLURAL && plural_index != plural_forms - 1)) {
-					memdelete(f);
 					ERR_FAIL_V_MSG(RES(), "Unexpected EOF while reading PO file at: " + path + ":" + itos(line));
 				} else {
 					break;
@@ -181,10 +177,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 			}
 
 			if (l.begins_with("msgctxt")) {
-				if (status != STATUS_READING_STRING && status != STATUS_READING_PLURAL) {
-					memdelete(f);
-					ERR_FAIL_V_MSG(RES(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line));
-				}
+				ERR_FAIL_COND_V_MSG(status != STATUS_READING_STRING && status != STATUS_READING_PLURAL, RES(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line));
 
 				// In PO file, "msgctxt" appears before "msgid". If we encounter a "msgctxt", we add what we have read
 				// and set "entered_context" to true to prevent adding twice.
@@ -192,10 +185,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 					if (status == STATUS_READING_STRING) {
 						translation->add_message(msg_id, msg_str, msg_context);
 					} else if (status == STATUS_READING_PLURAL) {
-						if (plural_index != plural_forms - 1) {
-							memdelete(f);
-							ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
-						}
+						ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
 						translation->add_plural_message(msg_id, msgs_plural, msg_context);
 					}
 				}
@@ -207,10 +197,8 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 
 			if (l.begins_with("msgid_plural")) {
 				if (plural_forms == 0) {
-					memdelete(f);
 					ERR_FAIL_V_MSG(RES(), "PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: " + path + ":" + itos(line));
 				} else if (status != STATUS_READING_ID) {
-					memdelete(f);
 					ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: " + path + ":" + itos(line));
 				}
 				// We don't record the message in "msgid_plural" itself as tr_n(), TTRN(), RTRN() interfaces provide the plural string already.
@@ -221,20 +209,14 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 				msgs_plural.resize(plural_forms);
 				status = STATUS_READING_PLURAL;
 			} else if (l.begins_with("msgid")) {
-				if (status == STATUS_READING_ID) {
-					memdelete(f);
-					ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
-				}
+				ERR_FAIL_COND_V_MSG(status == STATUS_READING_ID, RES(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
 
 				if (!msg_id.is_empty()) {
 					if (!skip_this && !entered_context) {
 						if (status == STATUS_READING_STRING) {
 							translation->add_message(msg_id, msg_str, msg_context);
 						} else if (status == STATUS_READING_PLURAL) {
-							if (plural_index != plural_forms - 1) {
-								memdelete(f);
-								ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
-							}
+							ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
 							translation->add_plural_message(msg_id, msgs_plural, msg_context);
 						}
 					}
@@ -263,18 +245,11 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 			}
 
 			if (l.begins_with("msgstr[")) {
-				if (status != STATUS_READING_PLURAL) {
-					memdelete(f);
-					ERR_FAIL_V_MSG(RES(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line));
-				}
+				ERR_FAIL_COND_V_MSG(status != STATUS_READING_PLURAL, RES(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line));
 				plural_index++; // Increment to add to the next slot in vector msgs_plural.
 				l = l.substr(9, l.length()).strip_edges();
 			} else if (l.begins_with("msgstr")) {
-				if (status != STATUS_READING_ID) {
-					memdelete(f);
-					ERR_FAIL_V_MSG(RES(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line));
-				}
-
+				ERR_FAIL_COND_V_MSG(status != STATUS_READING_ID, RES(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line));
 				l = l.substr(6, l.length()).strip_edges();
 				status = STATUS_READING_STRING;
 			}
@@ -287,10 +262,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 				continue; // Nothing to read or comment.
 			}
 
-			if (!l.begins_with("\"") || status == STATUS_NONE) {
-				memdelete(f);
-				ERR_FAIL_V_MSG(RES(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line));
-			}
+			ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, RES(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line));
 
 			l = l.substr(1, l.length());
 			// Find final quote, ignoring escaped ones (\").
@@ -312,10 +284,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 				escape_next = false;
 			}
 
-			if (end_pos == -1) {
-				memdelete(f);
-				ERR_FAIL_V_MSG(RES(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line));
-			}
+			ERR_FAIL_COND_V_MSG(end_pos == -1, RES(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line));
 
 			l = l.substr(0, end_pos);
 			l = l.c_unescape();
@@ -327,18 +296,13 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 			} else if (status == STATUS_READING_CONTEXT) {
 				msg_context += l;
 			} else if (status == STATUS_READING_PLURAL && plural_index >= 0) {
-				if (plural_index >= plural_forms) {
-					memdelete(f);
-					ERR_FAIL_V_MSG(RES(), "Unexpected plural form while parsing: " + path + ":" + itos(line));
-				}
+				ERR_FAIL_COND_V_MSG(plural_index >= plural_forms, RES(), "Unexpected plural form while parsing: " + path + ":" + itos(line));
 				msgs_plural.write[plural_index] = msgs_plural[plural_index] + l;
 			}
 
 			line++;
 		}
 
-		memdelete(f);
-
 		// Add the last set of data from last iteration.
 		if (status == STATUS_READING_STRING) {
 			if (!msg_id.is_empty()) {
@@ -350,10 +314,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 			}
 		} else if (status == STATUS_READING_PLURAL) {
 			if (!skip_this && !msg_id.is_empty()) {
-				if (plural_index != plural_forms - 1) {
-					memdelete(f);
-					ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
-				}
+				ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
 				translation->add_plural_message(msg_id, msgs_plural, msg_context);
 			}
 		}
@@ -388,8 +349,8 @@ RES TranslationLoaderPO::load(const String &p_path, const String &p_original_pat
 		*r_error = ERR_CANT_OPEN;
 	}
 
-	FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_V_MSG(!f, RES(), "Cannot open file '" + p_path + "'.");
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	ERR_FAIL_COND_V_MSG(f.is_null(), RES(), "Cannot open file '" + p_path + "'.");
 
 	return load_translation(f, r_error);
 }

+ 1 - 1
core/io/translation_loader_po.h

@@ -37,7 +37,7 @@
 
 class TranslationLoaderPO : public ResourceFormatLoader {
 public:
-	static RES load_translation(FileAccess *f, Error *r_error = nullptr);
+	static RES load_translation(Ref<FileAccess> f, Error *r_error = nullptr);
 	virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
 	virtual bool handles_type(const String &p_type) const;

+ 1 - 3
core/io/xml_parser.cpp

@@ -472,7 +472,7 @@ Error XMLParser::open_buffer(const Vector<uint8_t> &p_buffer) {
 
 Error XMLParser::open(const String &p_path) {
 	Error err;
-	FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &err);
+	Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err);
 
 	ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
 
@@ -488,8 +488,6 @@ Error XMLParser::open(const String &p_path) {
 	data[length] = 0;
 	P = data;
 
-	memdelete(file);
-
 	return OK;
 }
 

+ 23 - 27
core/io/zip_io.cpp

@@ -30,73 +30,69 @@
 
 #include "zip_io.h"
 
-void *zipio_open(void *data, const char *p_fname, int mode) {
-	FileAccess *&f = *(FileAccess **)data;
+void *zipio_open(voidpf opaque, const char *p_fname, int mode) {
+	ZipIOData *zd = (ZipIOData *)opaque;
 
 	String fname;
 	fname.parse_utf8(p_fname);
 
 	if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
-		f = FileAccess::open(fname, FileAccess::WRITE);
+		zd->f = FileAccess::open(fname, FileAccess::WRITE);
 	} else {
-		f = FileAccess::open(fname, FileAccess::READ);
+		zd->f = FileAccess::open(fname, FileAccess::READ);
 	}
 
-	if (!f) {
+	if (zd->f.is_null()) {
 		return nullptr;
 	}
 
-	return data;
+	return opaque;
 }
 
-uLong zipio_read(void *data, void *fdata, void *buf, uLong size) {
-	FileAccess *f = *(FileAccess **)data;
-	return f->get_buffer((uint8_t *)buf, size);
+uLong zipio_read(voidpf opaque, voidpf stream, void *buf, uLong size) {
+	ZipIOData *zd = (ZipIOData *)opaque;
+	return zd->f->get_buffer((uint8_t *)buf, size);
 }
 
 uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
-	FileAccess *f = *(FileAccess **)opaque;
-	f->store_buffer((uint8_t *)buf, size);
+	ZipIOData *zd = (ZipIOData *)opaque;
+	zd->f->store_buffer((uint8_t *)buf, size);
 	return size;
 }
 
 long zipio_tell(voidpf opaque, voidpf stream) {
-	FileAccess *f = *(FileAccess **)opaque;
-	return f->get_position();
+	ZipIOData *zd = (ZipIOData *)opaque;
+	return zd->f->get_position();
 }
 
 long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
-	FileAccess *f = *(FileAccess **)opaque;
+	ZipIOData *zd = (ZipIOData *)opaque;
 
 	uint64_t pos = offset;
 	switch (origin) {
 		case ZLIB_FILEFUNC_SEEK_CUR:
-			pos = f->get_position() + offset;
+			pos = zd->f->get_position() + offset;
 			break;
 		case ZLIB_FILEFUNC_SEEK_END:
-			pos = f->get_length() + offset;
+			pos = zd->f->get_length() + offset;
 			break;
 		default:
 			break;
 	}
 
-	f->seek(pos);
+	zd->f->seek(pos);
 	return 0;
 }
 
 int zipio_close(voidpf opaque, voidpf stream) {
-	FileAccess *&f = *(FileAccess **)opaque;
-	if (f) {
-		f->close();
-		memdelete(f);
-		f = nullptr;
-	}
+	ZipIOData *zd = (ZipIOData *)opaque;
+	memdelete(zd);
 	return 0;
 }
 
 int zipio_testerror(voidpf opaque, voidpf stream) {
-	FileAccess *f = *(FileAccess **)opaque;
-	return (f && f->get_error() != OK) ? 1 : 0;
+	ZipIOData *zd = (ZipIOData *)opaque;
+	return (zd->f.is_valid() && zd->f->get_error() != OK) ? 1 : 0;
 }
 
 voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) {
@@ -109,9 +105,9 @@ void zipio_free(voidpf opaque, voidpf address) {
 	memfree(address);
 }
 
-zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file) {
+zlib_filefunc_def zipio_create_io() {
 	zlib_filefunc_def io;
-	io.opaque = p_file;
+	io.opaque = (void *)memnew(ZipIOData);
 	io.zopen_file = zipio_open;
 	io.zread_file = zipio_read;
 	io.zwrite_file = zipio_write;

+ 7 - 3
core/io/zip_io.h

@@ -39,8 +39,12 @@
 #include "thirdparty/minizip/unzip.h"
 #include "thirdparty/minizip/zip.h"
 
-void *zipio_open(void *data, const char *p_fname, int mode);
-uLong zipio_read(void *data, void *fdata, void *buf, uLong size);
+struct ZipIOData {
+	Ref<FileAccess> f;
+};
+
+void *zipio_open(voidpf opaque, const char *p_fname, int mode);
+uLong zipio_read(voidpf opaque, voidpf stream, void *buf, uLong size);
 uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size);
 
 long zipio_tell(voidpf opaque, voidpf stream);
@@ -53,6 +57,6 @@ int zipio_testerror(voidpf opaque, voidpf stream);
 voidpf zipio_alloc(voidpf opaque, uInt items, uInt size);
 void zipio_free(voidpf opaque, voidpf address);
 
-zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file);
+zlib_filefunc_def zipio_create_io();
 
 #endif // ZIP_IO_H

+ 11 - 2
core/object/object.cpp

@@ -1848,6 +1848,13 @@ Object::Object() {
 	_construct_object(false);
 }
 
+void Object::detach_from_objectdb() {
+	if (_instance_id != ObjectID()) {
+		ObjectDB::remove_instance(this);
+		_instance_id = ObjectID();
+	}
+}
+
 Object::~Object() {
 	if (script_instance) {
 		memdelete(script_instance);
@@ -1887,8 +1894,10 @@ Object::~Object() {
 		c.signal.get_object()->_disconnect(c.signal.get_name(), c.callable, true);
 	}
 
-	ObjectDB::remove_instance(this);
-	_instance_id = ObjectID();
+	if (_instance_id != ObjectID()) {
+		ObjectDB::remove_instance(this);
+		_instance_id = ObjectID();
+	}
 	_predelete_ok = 2;
 
 	if (_instance_bindings != nullptr) {

+ 1 - 0
core/object/object.h

@@ -633,6 +633,7 @@ public:
 
 	bool _is_gpl_reversed() const { return false; }
 
+	void detach_from_objectdb();
 	_FORCE_INLINE_ ObjectID get_instance_id() const { return _instance_id; }
 
 	template <class T>

+ 18 - 15
core/os/os.cpp

@@ -80,7 +80,9 @@ void OS::print_error(const char *p_function, const char *p_file, int p_line, con
 		return;
 	}
 
-	_logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type);
+	if (_logger) {
+		_logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type);
+	}
 }
 
 void OS::print(const char *p_format, ...) {
@@ -91,7 +93,9 @@ void OS::print(const char *p_format, ...) {
 	va_list argp;
 	va_start(argp, p_format);
 
-	_logger->logv(p_format, argp, false);
+	if (_logger) {
+		_logger->logv(p_format, argp, false);
+	}
 
 	va_end(argp);
 }
@@ -104,7 +108,9 @@ void OS::printerr(const char *p_format, ...) {
 	va_list argp;
 	va_start(argp, p_format);
 
-	_logger->logv(p_format, argp, true);
+	if (_logger) {
+		_logger->logv(p_format, argp, true);
+	}
 
 	va_end(argp);
 }
@@ -173,7 +179,7 @@ void OS::dump_memory_to_file(const char *p_file) {
 	//Memory::dump_static_mem_to_file(p_file);
 }
 
-static FileAccess *_OSPRF = nullptr;
+static Ref<FileAccess> _OSPRF;
 
 static void _OS_printres(Object *p_obj) {
 	Resource *res = Object::cast_to<Resource>(p_obj);
@@ -182,7 +188,7 @@ static void _OS_printres(Object *p_obj) {
 	}
 
 	String str = vformat("%s - %s - %s", res->to_string(), res->get_name(), res->get_path());
-	if (_OSPRF) {
+	if (_OSPRF.is_valid()) {
 		_OSPRF->store_line(str);
 	} else {
 		print_line(str);
@@ -190,24 +196,19 @@ static void _OS_printres(Object *p_obj) {
 }
 
 void OS::print_all_resources(String p_to_file) {
-	ERR_FAIL_COND(!p_to_file.is_empty() && _OSPRF);
+	ERR_FAIL_COND(!p_to_file.is_empty() && _OSPRF.is_valid());
 	if (!p_to_file.is_empty()) {
 		Error err;
 		_OSPRF = FileAccess::open(p_to_file, FileAccess::WRITE, &err);
 		if (err != OK) {
-			_OSPRF = nullptr;
+			_OSPRF = Ref<FileAccess>();
 			ERR_FAIL_MSG("Can't print all resources to file: " + String(p_to_file) + ".");
 		}
 	}
 
 	ObjectDB::debug_objects(_OS_printres);
 
-	if (!p_to_file.is_empty()) {
-		if (_OSPRF) {
-			memdelete(_OSPRF);
-		}
-		_OSPRF = nullptr;
-	}
+	_OSPRF = Ref<FileAccess>();
 }
 
 void OS::print_resources_in_use(bool p_short) {
@@ -332,7 +333,7 @@ void OS::ensure_user_data_dir() {
 		return;
 	}
 
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	Error err = da->make_dir_recursive(dd);
 	ERR_FAIL_COND_MSG(err != OK, "Error attempting to create data dir: " + dd + ".");
 }
@@ -550,6 +551,8 @@ OS::OS() {
 }
 
 OS::~OS() {
-	memdelete(_logger);
+	if (_logger) {
+		memdelete(_logger);
+	}
 	singleton = nullptr;
 }

+ 1 - 2
core/string/translation_po.cpp

@@ -35,7 +35,7 @@
 #ifdef DEBUG_TRANSLATION_PO
 void TranslationPO::print_translation_map() {
 	Error err;
-	FileAccess *file = FileAccess::open("translation_map_print_test.txt", FileAccess::WRITE, &err);
+	Ref<FileAccess> file = FileAccess::open("translation_map_print_test.txt", FileAccess::WRITE, &err);
 	if (err != OK) {
 		ERR_PRINT("Failed to open translation_map_print_test.txt");
 		return;
@@ -62,7 +62,6 @@ void TranslationPO::print_translation_map() {
 			file->store_line("");
 		}
 	}
-	file->close();
 }
 #endif
 

+ 1 - 1
core/variant/variant_parser.h

@@ -49,7 +49,7 @@ public:
 	};
 
 	struct StreamFile : public Stream {
-		FileAccess *f = nullptr;
+		Ref<FileAccess> f;
 
 		virtual char32_t get_char() override;
 		virtual bool is_utf8() const override;

+ 6 - 8
drivers/gles3/shader_gles3.cpp

@@ -464,8 +464,8 @@ bool ShaderGLES3::_load_from_cache(Version *p_version) {
 	String sha1 = _version_get_sha1(p_version);
 	String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
 
-	FileAccessRef f = FileAccess::open(path, FileAccess::READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
+	if (f.is_null()) {
 		return false;
 	}
 
@@ -530,8 +530,8 @@ void ShaderGLES3::_save_to_cache(Version *p_version) {
 	String sha1 = _version_get_sha1(p_version);
 	String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
 
-	FileAccessRef f = FileAccess::open(path, FileAccess::WRITE);
-	ERR_FAIL_COND(!f);
+	Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE);
+	ERR_FAIL_COND(f.is_null());
 	f->store_buffer((const uint8_t *)shader_file_header, 4);
 	f->store_32(cache_file_version); //file version
 	uint32_t variant_count = variant_count;
@@ -541,8 +541,6 @@ void ShaderGLES3::_save_to_cache(Version *p_version) {
 		f->store_32(p_version->variant_data[i].size()); //stage count
 		f->store_buffer(p_version->variant_data[i].ptr(), p_version->variant_data[i].size());
 	}
-
-	f->close();
 #endif
 }
 
@@ -642,8 +640,8 @@ void ShaderGLES3::initialize(const String &p_general_defines, int p_base_texture
 
 		base_sha256 = hash_build.as_string().sha256_text();
 
-		DirAccessRef d = DirAccess::open(shader_cache_dir);
-		ERR_FAIL_COND(!d);
+		Ref<DirAccess> d = DirAccess::open(shader_cache_dir);
+		ERR_FAIL_COND(d.is_null());
 		if (d->change_dir(name) != OK) {
 			Error err = d->make_dir(name);
 			ERR_FAIL_COND(err != OK);

+ 1 - 3
drivers/png/image_loader_png.cpp

@@ -36,18 +36,16 @@
 
 #include <string.h>
 
-Error ImageLoaderPNG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
+Error ImageLoaderPNG::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) {
 	const uint64_t buffer_size = f->get_length();
 	Vector<uint8_t> file_buffer;
 	Error err = file_buffer.resize(buffer_size);
 	if (err) {
-		f->close();
 		return err;
 	}
 	{
 		uint8_t *writer = file_buffer.ptrw();
 		f->get_buffer(writer, buffer_size);
-		f->close();
 	}
 	const uint8_t *reader = file_buffer.ptr();
 	return PNGDriverCommon::png_to_image(reader, buffer_size, p_force_linear, p_image);

+ 1 - 1
drivers/png/image_loader_png.h

@@ -40,7 +40,7 @@ private:
 	static Ref<Image> load_mem_png(const uint8_t *p_png, int p_size);
 
 public:
-	virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
+	virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale);
 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
 	ImageLoaderPNG();
 };

+ 1 - 5
drivers/png/resource_saver_png.cpp

@@ -52,20 +52,16 @@ Error ResourceSaverPNG::save_image(const String &p_path, const Ref<Image> &p_img
 	Vector<uint8_t> buffer;
 	Error err = PNGDriverCommon::image_to_png(p_img, buffer);
 	ERR_FAIL_COND_V_MSG(err, err, "Can't convert image to PNG.");
-	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, vformat("Can't save PNG at path: '%s'.", p_path));
 
 	const uint8_t *reader = buffer.ptr();
 
 	file->store_buffer(reader, buffer.size());
 	if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
-		memdelete(file);
 		return ERR_CANT_CREATE;
 	}
 
-	file->close();
-	memdelete(file);
-
 	return OK;
 }
 

+ 2 - 2
drivers/unix/dir_access_unix.cpp

@@ -49,7 +49,7 @@
 #include <mntent.h>
 #endif
 
-DirAccess *DirAccessUnix::create_fs() {
+Ref<DirAccess> DirAccessUnix::create_fs() {
 	return memnew(DirAccessUnix);
 }
 
@@ -374,7 +374,7 @@ Error DirAccessUnix::change_dir(String p_dir) {
 	return OK;
 }
 
-String DirAccessUnix::get_current_dir(bool p_include_drive) {
+String DirAccessUnix::get_current_dir(bool p_include_drive) const {
 	String base = _get_root_path();
 	if (!base.is_empty()) {
 		String bd = current_dir.replace_first(base, "");

+ 2 - 2
drivers/unix/dir_access_unix.h

@@ -43,7 +43,7 @@
 class DirAccessUnix : public DirAccess {
 	DIR *dir_stream = nullptr;
 
-	static DirAccess *create_fs();
+	static Ref<DirAccess> create_fs();
 
 	String current_dir;
 	bool _cisdir;
@@ -67,7 +67,7 @@ public:
 	virtual bool drives_are_shortcuts();
 
 	virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
-	virtual String get_current_dir(bool p_include_drive = true); ///< return current dir location
+	virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location
 	virtual Error make_dir(String p_dir);
 
 	virtual bool file_exists(String p_file);

+ 1 - 1
drivers/unix/file_access_unix.cpp

@@ -336,7 +336,7 @@ Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_per
 	return FAILED;
 }
 
-FileAccess *FileAccessUnix::create_libc() {
+Ref<FileAccess> FileAccessUnix::create_libc() {
 	return memnew(FileAccessUnix);
 }
 

+ 1 - 1
drivers/unix/file_access_unix.h

@@ -49,7 +49,7 @@ class FileAccessUnix : public FileAccess {
 	String path;
 	String path_src;
 
-	static FileAccess *create_libc();
+	static Ref<FileAccess> create_libc();
 
 public:
 	static CloseNotificationFunc close_notification_func;

+ 1 - 2
drivers/vulkan/rendering_device_vulkan.cpp

@@ -4875,9 +4875,8 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
 						"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining push constants.");
 #if 0
 				if (pconstants[0] == nullptr) {
-					FileAccess *f = FileAccess::open("res://popo.spv", FileAccess::WRITE);
+					Ref<FileAccess> f = FileAccess::open("res://popo.spv", FileAccess::WRITE);
 					f->store_buffer((const uint8_t *)&SpirV[0], SpirV.size() * sizeof(uint32_t));
-					memdelete(f);
 				}
 #endif
 

+ 1 - 1
drivers/windows/dir_access_windows.cpp

@@ -185,7 +185,7 @@ Error DirAccessWindows::make_dir(String p_dir) {
 	return ERR_CANT_CREATE;
 }
 
-String DirAccessWindows::get_current_dir(bool p_include_drive) {
+String DirAccessWindows::get_current_dir(bool p_include_drive) const {
 	String base = _get_root_path();
 	if (!base.is_empty()) {
 		String bd = current_dir.replace("\\", "/").replace_first(base, "");

+ 1 - 1
drivers/windows/dir_access_windows.h

@@ -64,7 +64,7 @@ public:
 	virtual String get_drive(int p_drive);
 
 	virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
-	virtual String get_current_dir(bool p_include_drive = true); ///< return current dir location
+	virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location
 
 	virtual bool file_exists(String p_file);
 	virtual bool dir_exists(String p_dir);

+ 7 - 14
editor/create_dialog.cpp

@@ -377,8 +377,8 @@ void CreateDialog::_confirmed() {
 		return;
 	}
 
-	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
-	if (f) {
+	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++) {
@@ -386,8 +386,6 @@ void CreateDialog::_confirmed() {
 				f->store_line(recent->get_item_text(i));
 			}
 		}
-
-		memdelete(f);
 	}
 
 	// To prevent, emitting an error from the transient window (shader dialog for example) hide this dialog before emitting the "create" signal.
@@ -647,8 +645,8 @@ void CreateDialog::_save_and_update_favorite_list() {
 	favorites->clear();
 	TreeItem *root = favorites->create_item();
 
-	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
-	if (f) {
+	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);
@@ -665,7 +663,6 @@ void CreateDialog::_save_and_update_favorite_list() {
 			ti->set_text(0, l);
 			ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
 		}
-		memdelete(f);
 	}
 
 	emit_signal(SNAME("favorites_updated"));
@@ -673,8 +670,8 @@ void CreateDialog::_save_and_update_favorite_list() {
 
 void CreateDialog::_load_favorites_and_history() {
 	String dir = EditorSettings::get_singleton()->get_project_settings_dir();
-	FileAccess *f = FileAccess::open(dir.plus_file("create_recent." + base_type), FileAccess::READ);
-	if (f) {
+	Ref<FileAccess> f = FileAccess::open(dir.plus_file("create_recent." + base_type), FileAccess::READ);
+	if (f.is_valid()) {
 		while (!f->eof_reached()) {
 			String l = f->get_line().strip_edges();
 			String name = l.get_slicec(' ', 0);
@@ -683,12 +680,10 @@ void CreateDialog::_load_favorites_and_history() {
 				recent->add_item(l, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
 			}
 		}
-
-		memdelete(f);
 	}
 
 	f = FileAccess::open(dir.plus_file("favorites." + base_type), FileAccess::READ);
-	if (f) {
+	if (f.is_valid()) {
 		while (!f->eof_reached()) {
 			String l = f->get_line().strip_edges();
 
@@ -696,8 +691,6 @@ void CreateDialog::_load_favorites_and_history() {
 				favorite_list.push_back(l);
 			}
 		}
-
-		memdelete(f);
 	}
 }
 

+ 2 - 2
editor/debugger/script_editor_debugger.cpp

@@ -164,7 +164,7 @@ void ScriptEditorDebugger::_file_selected(const String &p_file) {
 	switch (file_dialog_purpose) {
 		case SAVE_MONITORS_CSV: {
 			Error err;
-			FileAccessRef file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+			Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
 
 			if (err != OK) {
 				ERR_PRINT("Failed to open " + p_file);
@@ -209,7 +209,7 @@ void ScriptEditorDebugger::_file_selected(const String &p_file) {
 		} break;
 		case SAVE_VRAM_CSV: {
 			Error err;
-			FileAccessRef file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+			Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
 
 			if (err != OK) {
 				ERR_PRINT("Failed to open " + p_file);

+ 1 - 1
editor/dependency_editor.cpp

@@ -749,7 +749,7 @@ void OrphanResourcesDialog::_find_to_delete(TreeItem *p_item, List<String> &path
 }
 
 void OrphanResourcesDialog::_delete_confirm() {
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	for (const String &E : paths) {
 		da->remove(E);
 		EditorFileSystem::get_singleton()->update_file(E);

+ 7 - 7
editor/doc_tools.cpp

@@ -1035,8 +1035,8 @@ static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> &
 
 Error DocTools::load_classes(const String &p_dir) {
 	Error err;
-	DirAccessRef da = DirAccess::open(p_dir, &err);
-	if (!da) {
+	Ref<DirAccess> da = DirAccess::open(p_dir, &err);
+	if (da.is_null()) {
 		return err;
 	}
 
@@ -1063,8 +1063,8 @@ Error DocTools::load_classes(const String &p_dir) {
 
 Error DocTools::erase_classes(const String &p_dir) {
 	Error err;
-	DirAccessRef da = DirAccess::open(p_dir, &err);
-	if (!da) {
+	Ref<DirAccess> da = DirAccess::open(p_dir, &err);
+	if (da.is_null()) {
 		return err;
 	}
 
@@ -1273,7 +1273,7 @@ Error DocTools::_load(Ref<XMLParser> parser) {
 	return OK;
 }
 
-static void _write_string(FileAccess *f, int p_tablevel, const String &p_string) {
+static void _write_string(Ref<FileAccess> f, int p_tablevel, const String &p_string) {
 	if (p_string.is_empty()) {
 		return;
 	}
@@ -1284,7 +1284,7 @@ static void _write_string(FileAccess *f, int p_tablevel, const String &p_string)
 	f->store_string(tab + p_string + "\n");
 }
 
-static void _write_method_doc(FileAccess *f, const String &p_name, Vector<DocData::MethodDoc> &p_method_docs) {
+static void _write_method_doc(Ref<FileAccess> f, const String &p_name, Vector<DocData::MethodDoc> &p_method_docs) {
 	if (!p_method_docs.is_empty()) {
 		p_method_docs.sort();
 		_write_string(f, 1, "<" + p_name + "s>");
@@ -1350,7 +1350,7 @@ Error DocTools::save_classes(const String &p_default_path, const Map<String, Str
 
 		Error err;
 		String save_file = save_path.plus_file(c.name + ".xml");
-		FileAccessRef f = FileAccess::open(save_file, FileAccess::WRITE, &err);
+		Ref<FileAccess> f = FileAccess::open(save_file, FileAccess::WRITE, &err);
 
 		ERR_CONTINUE_MSG(err != OK, "Can't write doc file: " + save_file + ".");
 

+ 5 - 8
editor/editor_asset_installer.cpp

@@ -64,8 +64,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
 	package_path = p_path;
 	Set<String> files_sorted;
 
-	FileAccess *src_f = nullptr;
-	zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+	zlib_filefunc_def io = zipio_create_io();
 
 	unzFile pkg = unzOpen2(p_path.utf8().get_data(), &io);
 	if (!pkg) {
@@ -238,8 +237,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
 }
 
 void EditorAssetInstaller::ok_pressed() {
-	FileAccess *src_f = nullptr;
-	zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+	zlib_filefunc_def io = zipio_create_io();
 
 	unzFile pkg = unzOpen2(package_path.utf8().get_data(), &io);
 	if (!pkg) {
@@ -280,7 +278,7 @@ void EditorAssetInstaller::ok_pressed() {
 					dirpath = dirpath.substr(0, dirpath.length() - 1);
 				}
 
-				DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+				Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 				da->make_dir(dirpath);
 			} else {
 				Vector<uint8_t> data;
@@ -291,10 +289,9 @@ void EditorAssetInstaller::ok_pressed() {
 				unzReadCurrentFile(pkg, data.ptrw(), data.size());
 				unzCloseCurrentFile(pkg);
 
-				FileAccess *f = FileAccess::open(path, FileAccess::WRITE);
-				if (f) {
+				Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE);
+				if (f.is_valid()) {
 					f->store_buffer(data.ptr(), data.size());
-					memdelete(f);
 				} else {
 					failed_files.push_back(path);
 				}

+ 2 - 2
editor/editor_dir_dialog.cpp

@@ -156,8 +156,8 @@ void EditorDirDialog::_make_dir_confirm() {
 
 	String dir = ti->get_metadata(0);
 
-	DirAccessRef d = DirAccess::open(dir);
-	ERR_FAIL_COND_MSG(!d, "Cannot open directory '" + dir + "'.");
+	Ref<DirAccess> d = DirAccess::open(dir);
+	ERR_FAIL_COND_MSG(d.is_null(), "Cannot open directory '" + dir + "'.");
 
 	const String stripped_dirname = makedirname->get_text().strip_edges();
 

+ 22 - 32
editor/editor_export.cpp

@@ -327,12 +327,12 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa
 		}
 	}
 
-	FileAccessEncrypted *fae = nullptr;
-	FileAccess *ftmp = pd->f;
+	Ref<FileAccessEncrypted> fae;
+	Ref<FileAccess> ftmp = pd->f;
 
 	if (sd.encrypted) {
-		fae = memnew(FileAccessEncrypted);
-		ERR_FAIL_COND_V(!fae, ERR_SKIP);
+		fae.instantiate();
+		ERR_FAIL_COND_V(fae.is_null(), ERR_SKIP);
 
 		Error err = fae->open_and_parse(ftmp, p_key, FileAccessEncrypted::MODE_WRITE_AES256, false);
 		ERR_FAIL_COND_V(err != OK, ERR_SKIP);
@@ -342,9 +342,8 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa
 	// Store file content.
 	ftmp->store_buffer(p_data.ptr(), p_data.size());
 
-	if (fae) {
+	if (fae.is_valid()) {
 		fae->release();
-		memdelete(fae);
 	}
 
 	int pad = _get_pad(PCK_PADDING, pd->f->get_position());
@@ -480,7 +479,7 @@ void EditorExportPlatform::_export_find_dependencies(const String &p_path, Set<S
 	}
 }
 
-void EditorExportPlatform::_edit_files_with_filter(DirAccess *da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude) {
+void EditorExportPlatform::_edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude) {
 	da->list_dir_begin();
 	String cur_dir = da->get_current_dir().replace("\\", "/");
 	if (!cur_dir.ends_with("/")) {
@@ -542,10 +541,9 @@ void EditorExportPlatform::_edit_filter_list(Set<String> &r_list, const String &
 		filters.push_back(f);
 	}
 
-	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
-	ERR_FAIL_NULL(da);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	ERR_FAIL_COND(da.is_null());
 	_edit_files_with_filter(da, filters, r_list, exclude);
-	memdelete(da);
 }
 
 void EditorExportPlugin::set_export_preset(const Ref<EditorExportPreset> &p_preset) {
@@ -1130,12 +1128,12 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 	EditorProgress ep("savepack", TTR("Packing"), 102, true);
 
 	// Create the temporary export directory if it doesn't exist.
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	da->make_dir_recursive(EditorPaths::get_singleton()->get_cache_dir());
 
 	String tmppath = EditorPaths::get_singleton()->get_cache_dir().plus_file("packtmp");
-	FileAccess *ftmp = FileAccess::open(tmppath, FileAccess::WRITE);
-	ERR_FAIL_COND_V_MSG(!ftmp, ERR_CANT_CREATE, "Cannot create file '" + tmppath + "'.");
+	Ref<FileAccess> ftmp = FileAccess::open(tmppath, FileAccess::WRITE);
+	ERR_FAIL_COND_V_MSG(ftmp.is_null(), ERR_CANT_CREATE, "Cannot create file '" + tmppath + "'.");
 
 	PackData pd;
 	pd.ep = &ep;
@@ -1144,8 +1142,6 @@ 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);
 
-	memdelete(ftmp); //close tmp file
-
 	if (err != OK) {
 		DirAccess::remove_file_or_error(tmppath);
 		ERR_PRINT("Failed to export project files");
@@ -1154,19 +1150,19 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 
 	pd.file_ofs.sort(); //do sort, so we can do binary search later
 
-	FileAccess *f;
+	Ref<FileAccess> f;
 	int64_t embed_pos = 0;
 	if (!p_embed) {
 		// Regular output to separate PCK file
 		f = FileAccess::open(p_path, FileAccess::WRITE);
-		if (!f) {
+		if (f.is_null()) {
 			DirAccess::remove_file_or_error(tmppath);
 			ERR_FAIL_V(ERR_CANT_CREATE);
 		}
 	} else {
 		// Append to executable
 		f = FileAccess::open(p_path, FileAccess::READ_WRITE);
-		if (!f) {
+		if (f.is_null()) {
 			DirAccess::remove_file_or_error(tmppath);
 			ERR_FAIL_V(ERR_FILE_CANT_OPEN);
 		}
@@ -1211,8 +1207,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 
 	f->store_32(pd.file_ofs.size()); //amount of files
 
-	FileAccessEncrypted *fae = nullptr;
-	FileAccess *fhead = f;
+	Ref<FileAccessEncrypted> fae;
+	Ref<FileAccess> fhead = f;
 
 	if (enc_pck && enc_directory) {
 		String script_key = p_preset->get_script_encryption_key().to_lower();
@@ -1243,8 +1239,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 				key.write[i] = v;
 			}
 		}
-		fae = memnew(FileAccessEncrypted);
-		ERR_FAIL_COND_V(!fae, ERR_SKIP);
+		fae.instantiate();
+		ERR_FAIL_COND_V(fae.is_null(), ERR_SKIP);
 
 		err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_WRITE_AES256, false);
 		ERR_FAIL_COND_V(err != OK, ERR_SKIP);
@@ -1272,9 +1268,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 		fhead->store_32(flags);
 	}
 
-	if (fae) {
+	if (fae.is_valid()) {
 		fae->release();
-		memdelete(fae);
 	}
 
 	int header_padding = _get_pad(PCK_PADDING, f->get_position());
@@ -1290,8 +1285,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 	// Save the rest of the data.
 
 	ftmp = FileAccess::open(tmppath, FileAccess::READ);
-	if (!ftmp) {
-		memdelete(f);
+	if (ftmp.is_null()) {
 		DirAccess::remove_file_or_error(tmppath);
 		ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't open file to read from path '" + String(tmppath) + "'.");
 	}
@@ -1307,8 +1301,6 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 		f->store_buffer(buf, got);
 	}
 
-	memdelete(ftmp);
-
 	if (p_embed) {
 		// Ensure embedded data ends at a 64-bit multiple
 		uint64_t embed_end = f->get_position() - embed_pos + 12;
@@ -1326,7 +1318,6 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 		}
 	}
 
-	memdelete(f);
 	DirAccess::remove_file_or_error(tmppath);
 
 	return OK;
@@ -1335,8 +1326,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
 Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
 	EditorProgress ep("savezip", TTR("Packing"), 102, true);
 
-	FileAccess *src_f;
-	zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+	zlib_filefunc_def io = zipio_create_io();
 	zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io);
 
 	ZipData zd;
@@ -1839,7 +1829,7 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr
 		return ERR_FILE_NOT_FOUND;
 	}
 
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	da->make_dir_recursive(p_path.get_base_dir());
 	Error err = da->copy(template_path, p_path, get_chmod_flags());
 

+ 2 - 2
editor/editor_export.h

@@ -184,7 +184,7 @@ private:
 	};
 
 	struct PackData {
-		FileAccess *f = nullptr;
+		Ref<FileAccess> f;
 		Vector<SavedData> file_ofs;
 		EditorProgress *ep = nullptr;
 		Vector<SharedObject> *so_files = nullptr;
@@ -207,7 +207,7 @@ private:
 	static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
 	static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
 
-	void _edit_files_with_filter(DirAccess *da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude);
+	void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude);
 	void _edit_filter_list(Set<String> &r_list, const String &p_filter, bool exclude);
 
 	static Error _add_shared_object(void *p_userdata, const SharedObject &p_so);

+ 6 - 7
editor/editor_feature_profile.cpp

@@ -198,13 +198,12 @@ Error EditorFeatureProfile::save_to_file(const String &p_path) {
 
 	data["disabled_features"] = dis_features;
 
-	FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE);
-	ERR_FAIL_COND_V_MSG(!f, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
 
 	JSON json;
 	String text = json.stringify(data, "\t");
 	f->store_string(text);
-	f->close();
 	return OK;
 }
 
@@ -350,8 +349,8 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr
 	}
 
 	Vector<String> profiles;
-	DirAccessRef d = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
-	ERR_FAIL_COND_MSG(!d, "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
+	Ref<DirAccess> d = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
+	ERR_FAIL_COND_MSG(d.is_null(), "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
 
 	d->list_dir_begin();
 	while (true) {
@@ -453,8 +452,8 @@ void EditorFeatureProfileManager::_profile_action(int p_action) {
 void EditorFeatureProfileManager::_erase_selected_profile() {
 	String selected = _get_selected_profile();
 	ERR_FAIL_COND(selected.is_empty());
-	DirAccessRef da = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
-	ERR_FAIL_COND_MSG(!da, "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
+	Ref<DirAccess> da = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
+	ERR_FAIL_COND_MSG(da.is_null(), "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
 
 	da->remove(selected + ".profile");
 	if (selected == current_profile) {

+ 0 - 2
editor/editor_file_dialog.cpp

@@ -1065,7 +1065,6 @@ void EditorFileDialog::set_access(Access p_access) {
 	if (access == p_access) {
 		return;
 	}
-	memdelete(dir_access);
 	switch (p_access) {
 		case ACCESS_FILESYSTEM: {
 			dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
@@ -1853,5 +1852,4 @@ EditorFileDialog::~EditorFileDialog() {
 	if (unregister_func) {
 		unregister_func(this);
 	}
-	memdelete(dir_access);
 }

+ 1 - 1
editor/editor_file_dialog.h

@@ -111,7 +111,7 @@ private:
 	LineEdit *file = nullptr;
 	OptionButton *filter = nullptr;
 	AcceptDialog *error_dialog = nullptr;
-	DirAccess *dir_access = nullptr;
+	Ref<DirAccess> dir_access;
 	ConfirmationDialog *confirm_save = nullptr;
 	DependencyRemoveDialog *dep_remove_dialog = nullptr;
 	ConfirmationDialog *global_remove_dialog = nullptr;

+ 29 - 50
editor/editor_file_system.cpp

@@ -218,10 +218,10 @@ 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);
-	FileAccess *f = FileAccess::open(fscache, FileAccess::READ);
+	Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ);
 
 	bool first = true;
-	if (f) {
+	if (f.is_valid()) {
 		//read the disk cache
 		while (!f->eof_reached()) {
 			String l = f->get_line().strip_edges();
@@ -283,16 +283,13 @@ void EditorFileSystem::_scan_filesystem() {
 				file_cache[name] = fc;
 			}
 		}
-
-		f->close();
-		memdelete(f);
 	}
 
 	String update_cache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4");
 
 	if (FileAccess::exists(update_cache)) {
 		{
-			FileAccessRef f2 = FileAccess::open(update_cache, FileAccess::READ);
+			Ref<FileAccess> f2 = FileAccess::open(update_cache, FileAccess::READ);
 			String l = f2->get_line().strip_edges();
 			while (!l.is_empty()) {
 				file_cache.erase(l); //erase cache for this, so it gets updated
@@ -300,7 +297,7 @@ void EditorFileSystem::_scan_filesystem() {
 			}
 		}
 
-		DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 		d->remove(update_cache); //bye bye update cache
 	}
 
@@ -314,14 +311,12 @@ void EditorFileSystem::_scan_filesystem() {
 	new_filesystem = memnew(EditorFileSystemDirectory);
 	new_filesystem->parent = nullptr;
 
-	DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	d->change_dir("res://");
 	_scan_new_dir(new_filesystem, d, sp);
 
 	file_cache.clear(); //clear caches, no longer needed
 
-	memdelete(d);
-
 	if (!first_scan) {
 		//on the first scan this is done from the main thread after re-importing
 		_save_filesystem_cache();
@@ -335,13 +330,11 @@ void EditorFileSystem::_save_filesystem_cache() {
 
 	String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
 
-	FileAccess *f = FileAccess::open(fscache, FileAccess::WRITE);
-	ERR_FAIL_COND_MSG(!f, "Cannot create file '" + fscache + "'. Check user write permissions.");
+	Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::WRITE);
+	ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + fscache + "'. Check user write permissions.");
 
 	f->store_line(filesystem_settings_version_for_import);
 	_save_filesystem_cache(filesystem, f);
-	f->close();
-	memdelete(f);
 }
 
 void EditorFileSystem::_thread_func(void *_userdata) {
@@ -364,9 +357,9 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
 	}
 
 	Error err;
-	FileAccess *f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
+	Ref<FileAccess> f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
 
-	if (!f) { //no import file, do reimport
+	if (f.is_null()) { //no import file, do reimport
 		return true;
 	}
 
@@ -400,7 +393,6 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
 			break;
 		} else if (err != OK) {
 			ERR_PRINT("ResourceFormatImporter::load - '" + p_path + ".import:" + itos(lines) + "' error '" + error_text + "'.");
-			memdelete(f);
 			return false; //parse error, try reimport manually (Avoid reimport loop on broken file)
 		}
 
@@ -431,8 +423,6 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
 		}
 	}
 
-	memdelete(f);
-
 	if (importer_name == "keep") {
 		return false; //keep mode, do not reimport
 	}
@@ -453,8 +443,8 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
 
 	// Read the md5's from a separate file (so the import parameters aren't dependent on the file version
 	String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_path);
-	FileAccess *md5s = FileAccess::open(base_path + ".md5", FileAccess::READ, &err);
-	if (!md5s) { // No md5's stored for this resource
+	Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::READ, &err);
+	if (md5s.is_null()) { // No md5's stored for this resource
 		return true;
 	}
 
@@ -472,7 +462,6 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
 			break;
 		} else if (err != OK) {
 			ERR_PRINT("ResourceFormatImporter::load - '" + p_path + ".import.md5:" + itos(lines) + "' error '" + error_text + "'.");
-			memdelete(md5s);
 			return false; // parse error
 		}
 		if (!assign.is_empty()) {
@@ -485,7 +474,6 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
 			}
 		}
 	}
-	memdelete(md5s);
 
 	//imported files are gone, reimport
 	for (const String &E : to_check) {
@@ -742,7 +730,7 @@ EditorFileSystem::ScanProgress EditorFileSystem::ScanProgress::get_sub(int p_cur
 	return sp;
 }
 
-void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess *da, const ScanProgress &p_progress) {
+void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAccess> &da, const ScanProgress &p_progress) {
 	List<String> dirs;
 	List<String> files;
 
@@ -967,7 +955,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
 
 		//then scan files and directories and check what's different
 
-		DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 
 		Error ret = da->change_dir(cd);
 		ERR_FAIL_COND_MSG(ret != OK, "Cannot change to '" + cd + "' folder.");
@@ -998,10 +986,9 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
 
 					efd->parent = p_dir;
 					efd->name = f;
-					DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+					Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 					d->change_dir(cd.plus_file(f));
 					_scan_new_dir(efd, d, p_progress.get_sub(1, 1));
-					memdelete(d);
 
 					ItemAction ia;
 					ia.action = ItemAction::ACTION_DIR_ADD;
@@ -1137,7 +1124,7 @@ void EditorFileSystem::_delete_internal_files(String p_file) {
 	if (FileAccess::exists(p_file + ".import")) {
 		List<String> paths;
 		ResourceFormatImporter::get_singleton()->get_internal_resource_path_list(p_file, &paths);
-		DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 		for (const String &E : paths) {
 			da->remove(E);
 		}
@@ -1282,7 +1269,7 @@ EditorFileSystemDirectory *EditorFileSystem::get_filesystem() {
 	return filesystem;
 }
 
-void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir, FileAccess *p_file) {
+void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir, Ref<FileAccess> p_file) {
 	if (!p_dir) {
 		return; //none
 	}
@@ -1467,8 +1454,8 @@ EditorFileSystemDirectory *EditorFileSystem::get_filesystem_path(const String &p
 void EditorFileSystem::_save_late_updated_files() {
 	//files that already existed, and were modified, need re-scanning for dependencies upon project restart. This is done via saving this special file
 	String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4");
-	FileAccessRef f = FileAccess::open(fscache, FileAccess::WRITE);
-	ERR_FAIL_COND_MSG(!f, "Cannot create file '" + fscache + "'. Check user write permissions.");
+	Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::WRITE);
+	ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + fscache + "'. Check user write permissions.");
 	for (Set<String>::Element *E = late_update_files.front(); E; E = E->next()) {
 		f->store_line(E->get());
 	}
@@ -1713,8 +1700,8 @@ 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);
-		FileAccessRef f = FileAccess::open(file + ".import", FileAccess::WRITE);
-		ERR_FAIL_COND_V_MSG(!f, ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'.");
+		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]");
@@ -1774,17 +1761,14 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
 			f->store_line(base + "=" + value);
 		}
 
-		f->close();
-
 		// Store the md5's of the various files. These are stored separately so that the .import files can be version controlled.
-		FileAccessRef md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
-		ERR_FAIL_COND_V_MSG(!md5s, 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->close();
 
 		EditorFileSystemDirectory *fs = nullptr;
 		int cpos = -1;
@@ -1930,8 +1914,8 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
 
 	//as import is complete, save the .import file
 
-	FileAccess *f = FileAccess::open(p_file + ".import", FileAccess::WRITE);
-	ERR_FAIL_COND_MSG(!f, "Cannot open file from path '" + p_file + ".import'.");
+	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]");
@@ -2017,19 +2001,14 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
 		f->store_line(base + "=" + value);
 	}
 
-	f->close();
-	memdelete(f);
-
 	// Store the md5's of the various files. These are stored separately so that the .import files can be version controlled.
-	FileAccess *md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
-	ERR_FAIL_COND_MSG(!md5s, "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->close();
-	memdelete(md5s);
 
 	//update modified times, to avoid reimport
 	fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
@@ -2342,14 +2321,14 @@ bool EditorFileSystem::_scan_extensions() {
 	String extension_list_config_file = NativeExtension::get_extension_list_config_file();
 	if (extensions.size()) {
 		if (extensions_added.size() || extensions_removed.size()) { //extensions were added or removed
-			FileAccessRef f = FileAccess::open(extension_list_config_file, FileAccess::WRITE);
+			Ref<FileAccess> f = FileAccess::open(extension_list_config_file, FileAccess::WRITE);
 			for (const String &E : extensions) {
 				f->store_line(E);
 			}
 		}
 	} else {
 		if (loaded_extensions.size() || FileAccess::exists(extension_list_config_file)) { //extensions were removed
-			DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+			Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 			da->remove(extension_list_config_file);
 		}
 	}
@@ -2438,7 +2417,7 @@ EditorFileSystem::EditorFileSystem() {
 	new_filesystem = nullptr;
 
 	// This should probably also work on Unix and use the string it returns for FAT32 or exFAT
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "exFAT");
 
 	scan_total = 0;

+ 2 - 2
editor/editor_file_system.h

@@ -213,7 +213,7 @@ class EditorFileSystem : public Node {
 	};
 
 	void _save_filesystem_cache();
-	void _save_filesystem_cache(EditorFileSystemDirectory *p_dir, FileAccess *p_file);
+	void _save_filesystem_cache(EditorFileSystemDirectory *p_dir, Ref<FileAccess> p_file);
 
 	bool _find_file(const String &p_file, EditorFileSystemDirectory **r_d, int &r_file_pos) const;
 
@@ -225,7 +225,7 @@ class EditorFileSystem : public Node {
 	Set<String> valid_extensions;
 	Set<String> import_extensions;
 
-	void _scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess *da, const ScanProgress &p_progress);
+	void _scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAccess> &da, const ScanProgress &p_progress);
 
 	Thread thread_sources;
 	bool scanning_changes = false;

+ 1 - 1
editor/editor_folding.cpp

@@ -131,7 +131,7 @@ void EditorFolding::_fill_folds(const Node *p_root, const Node *p_node, Array &p
 void EditorFolding::save_scene_folding(const Node *p_scene, const String &p_path) {
 	ERR_FAIL_NULL(p_scene);
 
-	FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
+	Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
 	if (!file_check->file_exists(p_path)) { //This can happen when creating scene from FilesystemDock. It has path, but no file.
 		return;
 	}

+ 1 - 1
editor/editor_fonts.cpp

@@ -218,7 +218,7 @@ Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, Te
 }
 
 void editor_register_fonts(Ref<Theme> p_theme) {
-	DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 
 	/* Custom font */
 

+ 4 - 4
editor/editor_node.cpp

@@ -935,7 +935,7 @@ void EditorNode::_fs_changed() {
 		}
 
 		if (export_preset.is_null()) {
-			DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+			Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 			if (da->file_exists("res://export_presets.cfg")) {
 				export_error = vformat(
 						"Invalid export preset name: %s.\nThe following presets were detected in this project's `export_presets.cfg`:\n\n",
@@ -1058,7 +1058,7 @@ void EditorNode::_scan_external_changes() {
 	// Check if any edited scene has changed.
 
 	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
-		DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 		if (editor_data.get_scene_path(i) == "" || !da->file_exists(editor_data.get_scene_path(i))) {
 			continue;
 		}
@@ -5487,7 +5487,7 @@ void EditorNode::_dropped_files(const Vector<String> &p_files) {
 }
 
 void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, String to_path) {
-	DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 
 	for (int i = 0; i < p_files.size(); i++) {
 		String from = p_files[i];
@@ -5496,7 +5496,7 @@ void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, Str
 		if (dir->dir_exists(from)) {
 			Vector<String> sub_files;
 
-			DirAccessRef sub_dir = DirAccess::open(from);
+			Ref<DirAccess> sub_dir = DirAccess::open(from);
 			sub_dir->list_dir_begin();
 
 			String next_file = sub_dir->get_next();

+ 5 - 6
editor/editor_paths.cpp

@@ -97,7 +97,7 @@ EditorPaths::EditorPaths() {
 		exe_path = exe_path.plus_file("../../..").simplify_path();
 	}
 	{
-		DirAccessRef d = DirAccess::create_for_path(exe_path);
+		Ref<DirAccess> d = DirAccess::create_for_path(exe_path);
 
 		if (d->file_exists(exe_path + "/._sc_")) {
 			self_contained = true;
@@ -141,7 +141,7 @@ EditorPaths::EditorPaths() {
 
 	// Validate or create each dir and its relevant subdirectories.
 
-	DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 
 	// Data dir.
 	{
@@ -197,7 +197,7 @@ EditorPaths::EditorPaths() {
 		// Nothing to create, use shared editor data dir for shader cache.
 		Engine::get_singleton()->set_shader_cache_path(data_dir);
 	} else {
-		DirAccessRef dir_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Ref<DirAccess> dir_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 		if (dir_res->change_dir(project_data_dir) != OK) {
 			dir_res->make_dir_recursive(project_data_dir);
 			if (dir_res->change_dir(project_data_dir) != OK) {
@@ -210,10 +210,9 @@ EditorPaths::EditorPaths() {
 		String project_data_gdignore_file_path = project_data_dir.plus_file(".gdignore");
 		if (!FileAccess::exists(project_data_gdignore_file_path)) {
 			// Add an empty .gdignore file to avoid scan.
-			FileAccessRef f = FileAccess::open(project_data_gdignore_file_path, FileAccess::WRITE);
-			if (f) {
+			Ref<FileAccess> f = FileAccess::open(project_data_gdignore_file_path, FileAccess::WRITE);
+			if (f.is_valid()) {
 				f->store_line("");
-				f->close();
 			} else {
 				ERR_PRINT("Failed to create file " + project_data_gdignore_file_path);
 			}

+ 1 - 1
editor/editor_plugin_settings.cpp

@@ -161,7 +161,7 @@ void EditorPluginSettings::_cell_button_pressed(Object *p_item, int p_column, in
 }
 
 Vector<String> EditorPluginSettings::_get_plugins(const String &p_dir) {
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	Error err = da->change_dir(p_dir);
 	if (err != OK) {
 		return Vector<String>();

+ 5 - 12
editor/editor_resource_preview.cpp

@@ -199,14 +199,12 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
 			if (has_small_texture) {
 				ResourceSaver::save(cache_base + "_small.png", r_small_texture);
 			}
-			FileAccess *f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE);
-			ERR_FAIL_COND_MSG(!f, "Cannot create file '" + cache_base + ".txt'. Check user write permissions.");
+			Ref<FileAccess> f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE);
+			ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + cache_base + ".txt'. Check user write permissions.");
 			f->store_line(itos(thumbnail_size));
 			f->store_line(itos(has_small_texture));
 			f->store_line(itos(FileAccess::get_modified_time(p_item.path)));
 			f->store_line(FileAccess::get_md5(p_item.path));
-			f->close();
-			memdelete(f);
 		}
 	}
 }
@@ -251,8 +249,8 @@ void EditorResourcePreview::_iterate() {
 				//does not have it, try to load a cached thumbnail
 
 				String file = cache_base + ".txt";
-				FileAccess *f = FileAccess::open(file, FileAccess::READ);
-				if (!f) {
+				Ref<FileAccess> f = FileAccess::open(file, FileAccess::READ);
+				if (f.is_null()) {
 					// No cache found, generate
 					_generate_preview(texture, small_texture, item, cache_base);
 				} else {
@@ -265,11 +263,9 @@ void EditorResourcePreview::_iterate() {
 
 					if (tsize != thumbnail_size) {
 						cache_valid = false;
-						memdelete(f);
 					} else if (last_modtime != modtime) {
 						String last_md5 = f->get_line();
 						String md5 = FileAccess::get_md5(item.path);
-						memdelete(f);
 
 						if (last_md5 != md5) {
 							cache_valid = false;
@@ -278,7 +274,7 @@ void EditorResourcePreview::_iterate() {
 							//update modified time
 
 							f = FileAccess::open(file, FileAccess::WRITE);
-							if (!f) {
+							if (f.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.");
@@ -287,11 +283,8 @@ void EditorResourcePreview::_iterate() {
 								f->store_line(itos(has_small_texture));
 								f->store_line(itos(modtime));
 								f->store_line(md5);
-								memdelete(f);
 							}
 						}
-					} else {
-						memdelete(f);
 					}
 
 					if (cache_valid) {

+ 14 - 18
editor/editor_settings.cpp

@@ -842,7 +842,7 @@ void EditorSettings::create() {
 
 	if (EditorPaths::get_singleton()->are_paths_valid()) {
 		// Validate editor config file.
-		DirAccessRef dir = DirAccess::open(EditorPaths::get_singleton()->get_config_dir());
+		Ref<DirAccess> dir = DirAccess::open(EditorPaths::get_singleton()->get_config_dir());
 		String config_file_name = "editor_settings-" + itos(VERSION_MAJOR) + ".tres";
 		config_file_path = EditorPaths::get_singleton()->get_config_dir().plus_file(config_file_name);
 		if (!dir->file_exists(config_file_name)) {
@@ -1151,12 +1151,11 @@ void EditorSettings::set_favorites(const Vector<String> &p_favorites) {
 	} else {
 		favorites_file = get_project_settings_dir().plus_file("favorites");
 	}
-	FileAccess *f = FileAccess::open(favorites_file, FileAccess::WRITE);
-	if (f) {
+	Ref<FileAccess> f = FileAccess::open(favorites_file, FileAccess::WRITE);
+	if (f.is_valid()) {
 		for (int i = 0; i < favorites.size(); i++) {
 			f->store_line(favorites[i]);
 		}
-		memdelete(f);
 	}
 }
 
@@ -1172,12 +1171,11 @@ void EditorSettings::set_recent_dirs(const Vector<String> &p_recent_dirs) {
 	} else {
 		recent_dirs_file = get_project_settings_dir().plus_file("recent_dirs");
 	}
-	FileAccess *f = FileAccess::open(recent_dirs_file, FileAccess::WRITE);
-	if (f) {
+	Ref<FileAccess> f = FileAccess::open(recent_dirs_file, FileAccess::WRITE);
+	if (f.is_valid()) {
 		for (int i = 0; i < recent_dirs.size(); i++) {
 			f->store_line(recent_dirs[i]);
 		}
-		memdelete(f);
 	}
 }
 
@@ -1195,24 +1193,22 @@ void EditorSettings::load_favorites_and_recent_dirs() {
 		favorites_file = get_project_settings_dir().plus_file("favorites");
 		recent_dirs_file = get_project_settings_dir().plus_file("recent_dirs");
 	}
-	FileAccess *f = FileAccess::open(favorites_file, FileAccess::READ);
-	if (f) {
+	Ref<FileAccess> f = FileAccess::open(favorites_file, FileAccess::READ);
+	if (f.is_valid()) {
 		String line = f->get_line().strip_edges();
 		while (!line.is_empty()) {
 			favorites.push_back(line);
 			line = f->get_line().strip_edges();
 		}
-		memdelete(f);
 	}
 
 	f = FileAccess::open(recent_dirs_file, FileAccess::READ);
-	if (f) {
+	if (f.is_valid()) {
 		String line = f->get_line().strip_edges();
 		while (!line.is_empty()) {
 			recent_dirs.push_back(line);
 			line = f->get_line().strip_edges();
 		}
-		memdelete(f);
 	}
 }
 
@@ -1227,8 +1223,8 @@ bool EditorSettings::is_dark_theme() {
 void EditorSettings::list_text_editor_themes() {
 	String themes = "Default,Godot 2,Custom";
 
-	DirAccessRef d = DirAccess::open(get_text_editor_themes_dir());
-	if (d) {
+	Ref<DirAccess> d = DirAccess::open(get_text_editor_themes_dir());
+	if (d.is_valid()) {
 		List<String> custom_themes;
 		d->list_dir_begin();
 		String file = d->get_next();
@@ -1293,8 +1289,8 @@ bool EditorSettings::import_text_editor_theme(String p_file) {
 			return false;
 		}
 
-		DirAccessRef d = DirAccess::open(get_text_editor_themes_dir());
-		if (d) {
+		Ref<DirAccess> d = DirAccess::open(get_text_editor_themes_dir());
+		if (d.is_valid()) {
 			d->copy(p_file, get_text_editor_themes_dir().plus_file(p_file.get_file()));
 			return true;
 		}
@@ -1345,8 +1341,8 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension, c
 	if (!p_custom_path.is_empty()) {
 		template_dir = p_custom_path;
 	}
-	DirAccessRef d = DirAccess::open(template_dir);
-	if (d) {
+	Ref<DirAccess> d = DirAccess::open(template_dir);
+	if (d.is_valid()) {
 		d->list_dir_begin();
 		String file = d->get_next();
 		while (!file.is_empty()) {

+ 4 - 2
editor/editor_translation.cpp

@@ -59,7 +59,8 @@ void load_editor_translations(const String &p_locale) {
 			int ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
 			ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
 
-			FileAccessMemory *fa = memnew(FileAccessMemory);
+			Ref<FileAccessMemory> fa;
+			fa.instantiate();
 			fa->open_custom(data.ptr(), data.size());
 
 			Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
@@ -84,7 +85,8 @@ void load_doc_translations(const String &p_locale) {
 			int ret = Compression::decompress(data.ptrw(), dtl->uncomp_size, dtl->data, dtl->comp_size, Compression::MODE_DEFLATE);
 			ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
 
-			FileAccessMemory *fa = memnew(FileAccessMemory);
+			Ref<FileAccessMemory> fa;
+			fa.instantiate();
 			fa->open_custom(data.ptr(), data.size());
 
 			Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);

+ 3 - 5
editor/editor_vcs_interface.cpp

@@ -168,21 +168,19 @@ void EditorVCSInterface::set_singleton(EditorVCSInterface *p_singleton) {
 
 void EditorVCSInterface::create_vcs_metadata_files(VCSMetadata p_vcs_metadata_type, String &p_dir) {
 	if (p_vcs_metadata_type == VCSMetadata::GIT) {
-		FileAccess *f = FileAccess::open(p_dir.plus_file(".gitignore"), FileAccess::WRITE);
-		if (!f) {
+		Ref<FileAccess> f = FileAccess::open(p_dir.plus_file(".gitignore"), FileAccess::WRITE);
+		if (f.is_null()) {
 			ERR_FAIL_MSG(TTR("Couldn't create .gitignore in project path."));
 		} else {
 			f->store_line("# Godot 4+ specific ignores");
 			f->store_line(".godot/");
-			memdelete(f);
 		}
 		f = FileAccess::open(p_dir.plus_file(".gitattributes"), FileAccess::WRITE);
-		if (!f) {
+		if (f.is_null()) {
 			ERR_FAIL_MSG(TTR("Couldn't create .gitattributes in project path."));
 		} else {
 			f->store_line("# Normalize EOL for all files that Git considers text files.");
 			f->store_line("* text=auto eol=lf");
-			memdelete(f);
 		}
 	}
 }

+ 18 - 25
editor/export_template_manager.cpp

@@ -44,7 +44,7 @@
 
 void ExportTemplateManager::_update_template_status() {
 	// Fetch installed templates from the file system.
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
 
 	Error err = da->change_dir(templates_dir);
@@ -194,7 +194,7 @@ void ExportTemplateManager::_download_template_completed(int p_status, int p_cod
 				bool ret = _install_file_selected(path, true);
 				if (ret) {
 					// Clean up downloaded file.
-					DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+					Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 					Error err = da->remove(path);
 					if (err != OK) {
 						EditorNode::get_singleton()->add_io_error(TTR("Cannot remove temporary file:") + "\n" + path + "\n");
@@ -374,10 +374,7 @@ void ExportTemplateManager::_install_file() {
 }
 
 bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_skip_progress) {
-	// unzClose() will take care of closing the file stored in the unzFile,
-	// so we don't need to `memdelete(fa)` in this method.
-	FileAccess *fa = nullptr;
-	zlib_filefunc_def io = zipio_create_io_from_file(&fa);
+	zlib_filefunc_def io = zipio_create_io();
 
 	unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io);
 	if (!pkg) {
@@ -441,7 +438,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
 		return false;
 	}
 
-	DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version);
 	Error err = d->make_dir_recursive(template_path);
 	if (err != OK) {
@@ -492,8 +489,8 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
 			base_dir = base_dir.substr(contents_dir.length(), file_path.length()).trim_prefix("/");
 			file = base_dir.plus_file(file);
 
-			DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-			ERR_CONTINUE(!da);
+			Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+			ERR_CONTINUE(da.is_null());
 
 			String output_dir = template_path.plus_file(base_dir);
 
@@ -508,9 +505,9 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
 		}
 
 		String to_write = template_path.plus_file(file);
-		FileAccessRef f = FileAccess::open(to_write, FileAccess::WRITE);
+		Ref<FileAccess> f = FileAccess::open(to_write, FileAccess::WRITE);
 
-		if (!f) {
+		if (f.is_null()) {
 			ret = unzGoToNextFile(pkg);
 			fc++;
 			ERR_CONTINUE_MSG(true, "Can't open file from path '" + String(to_write) + "'.");
@@ -542,7 +539,7 @@ void ExportTemplateManager::_uninstall_template(const String &p_version) {
 }
 
 void ExportTemplateManager::_uninstall_template_confirmed() {
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
 
 	Error err = da->change_dir(templates_dir);
@@ -656,17 +653,16 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
 	// To support custom Android builds, we install the Java source code and buildsystem
 	// from android_source.zip to the project's res://android folder.
 
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
-	ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	ERR_FAIL_COND_V(da.is_null(), ERR_CANT_CREATE);
 
 	// Make res://android dir (if it does not exist).
 	da->make_dir("android");
 	{
 		// Add version, to ensure building won't work if template and Godot version don't match.
-		FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::WRITE);
-		ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
+		Ref<FileAccess> f = FileAccess::open("res://android/.build_version", FileAccess::WRITE);
+		ERR_FAIL_COND_V(f.is_null(), ERR_CANT_CREATE);
 		f->store_line(VERSION_FULL_CONFIG);
-		f->close();
 	}
 
 	// Create the android plugins directory.
@@ -677,16 +673,14 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
 	ERR_FAIL_COND_V(err != OK, err);
 	{
 		// Add an empty .gdignore file to avoid scan.
-		FileAccessRef f = FileAccess::open("res://android/build/.gdignore", FileAccess::WRITE);
-		ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
+		Ref<FileAccess> f = FileAccess::open("res://android/build/.gdignore", FileAccess::WRITE);
+		ERR_FAIL_COND_V(f.is_null(), ERR_CANT_CREATE);
 		f->store_line("");
-		f->close();
 	}
 
 	// Uncompress source template.
 
-	FileAccess *src_f = nullptr;
-	zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+	zlib_filefunc_def io = zipio_create_io();
 
 	unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io);
 	ERR_FAIL_COND_V_MSG(!pkg, ERR_CANT_OPEN, "Android sources not in ZIP format.");
@@ -731,10 +725,9 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
 			}
 
 			String to_write = String("res://android/build").plus_file(path);
-			FileAccess *f = FileAccess::open(to_write, FileAccess::WRITE);
-			if (f) {
+			Ref<FileAccess> f = FileAccess::open(to_write, FileAccess::WRITE);
+			if (f.is_valid()) {
 				f->store_buffer(data.ptr(), data.size());
-				memdelete(f);
 #ifndef WINDOWS_ENABLED
 				FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF);
 #endif

+ 2 - 4
editor/fileserver/editor_file_server.cpp

@@ -46,7 +46,6 @@ void EditorFileServer::_close_client(ClientData *cd) {
 		cd->efs->to_wait.insert(cd->thread);
 	}
 	while (cd->files.size()) {
-		memdelete(cd->files.front()->get());
 		cd->files.erase(cd->files.front());
 	}
 	memdelete(cd);
@@ -181,8 +180,8 @@ void EditorFileServer::_subthread_start(void *s) {
 					break;
 				}
 
-				FileAccess *fa = FileAccess::open(s2, FileAccess::READ);
-				if (!fa) {
+				Ref<FileAccess> fa = FileAccess::open(s2, FileAccess::READ);
+				if (fa.is_null()) {
 					//not found, continue
 					encode_uint32(id, buf4);
 					cd->connection->put_data(buf4, 4);
@@ -249,7 +248,6 @@ void EditorFileServer::_subthread_start(void *s) {
 			case FileAccessNetwork::COMMAND_CLOSE: {
 				print_verbose("CLOSED");
 				ERR_CONTINUE(!cd->files.has(id));
-				memdelete(cd->files[id]);
 				cd->files.erase(id);
 			} break;
 		}

+ 1 - 1
editor/fileserver/editor_file_server.h

@@ -49,7 +49,7 @@ class EditorFileServer : public Object {
 	struct ClientData {
 		Thread *thread = nullptr;
 		Ref<StreamPeerTCP> connection;
-		Map<int, FileAccess *> files;
+		Map<int, Ref<FileAccess>> files;
 		EditorFileServer *efs = nullptr;
 		bool quit = false;
 	};

+ 14 - 14
editor/filesystem_dock.cpp

@@ -225,7 +225,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
 
 	Vector<String> favorite_paths = EditorSettings::get_singleton()->get_favorites();
 
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	bool fav_changed = false;
 	for (int i = favorite_paths.size() - 1; i >= 0; i--) {
 		if (da->dir_exists(favorite_paths[i]) || da->file_exists(favorite_paths[i])) {
@@ -539,7 +539,7 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa
 		if (target_path.ends_with("/")) {
 			target_path = target_path.substr(0, target_path.length() - 1);
 		}
-		DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 		if (da->file_exists(p_path)) {
 			path = target_path;
 		} else if (da->dir_exists(p_path)) {
@@ -1183,7 +1183,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
 		_get_all_items_in_dir(EditorFileSystem::get_singleton()->get_filesystem_path(old_path), file_changed_paths, folder_changed_paths);
 	}
 
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	print_verbose("Moving " + old_path + " -> " + new_path);
 	Error err = da->rename(old_path, new_path);
 	if (err == OK) {
@@ -1241,7 +1241,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
 		return;
 	}
 
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	print_verbose("Duplicating " + old_path + " -> " + new_path);
 	Error err = p_item.is_file ? da->copy(old_path, new_path) : da->copy_dir(old_path, new_path);
 	if (err == OK) {
@@ -1260,7 +1260,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
 			cfg->save(new_path + ".import");
 		} else if (p_item.is_file && (old_path.get_extension() == "tscn" || old_path.get_extension() == "tres")) {
 			// FIXME: Quick hack to fix text resources. This should be fixed properly.
-			FileAccessRef file = FileAccess::open(old_path, FileAccess::READ, &err);
+			Ref<FileAccess> file = FileAccess::open(old_path, FileAccess::READ, &err);
 			if (err == OK) {
 				PackedStringArray lines = file->get_as_utf8_string().split("\n");
 				String line = lines[0];
@@ -1269,7 +1269,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
 					line = line.substr(0, line.find(" uid")) + "]";
 					lines.write[0] = line;
 
-					FileAccessRef file2 = FileAccess::open(new_path, FileAccess::WRITE, &err);
+					Ref<FileAccess> file2 = FileAccess::open(new_path, FileAccess::WRITE, &err);
 					if (err == OK) {
 						file2->store_string(String("\n").join(lines));
 					}
@@ -1429,7 +1429,7 @@ void FileSystemDock::_make_dir_confirm() {
 	}
 
 	print_verbose("Making folder " + dir_name + " in " + directory);
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	Error err = da->change_dir(directory);
 	ERR_FAIL_COND_MSG(err != OK, "Cannot open directory '" + directory + "'.");
 
@@ -1479,7 +1479,7 @@ void FileSystemDock::_make_scene_confirm() {
 
 	scene_name = directory.plus_file(scene_name);
 
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	if (da->file_exists(scene_name)) {
 		EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
 		return;
@@ -1494,7 +1494,7 @@ void FileSystemDock::_file_removed(String p_file) {
 
 	// Find the closest parent directory available, in case multiple items were deleted along the same path.
 	path = p_file.get_base_dir();
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	while (!da->dir_exists(path)) {
 		path = path.get_base_dir();
 	}
@@ -1507,7 +1507,7 @@ void FileSystemDock::_folder_removed(String p_folder) {
 
 	// Find the closest parent directory available, in case multiple items were deleted along the same path.
 	path = p_folder.get_base_dir();
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	while (!da->dir_exists(path)) {
 		path = path.get_base_dir();
 	}
@@ -1546,7 +1546,7 @@ void FileSystemDock::_rename_operation_confirm() {
 	}
 
 	// Present a more user friendly warning for name conflict.
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 #if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
 	// Workaround case insensitivity on Windows.
 	if ((da->file_exists(new_path) || da->dir_exists(new_path)) && new_path.to_lower() != old_path.to_lower()) {
@@ -1599,7 +1599,7 @@ void FileSystemDock::_duplicate_operation_confirm() {
 	String new_path = base_dir.plus_file(new_name);
 
 	// Present a more user friendly warning for name conflict
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	if (da->file_exists(new_path) || da->dir_exists(new_path)) {
 		EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
 		return;
@@ -2354,7 +2354,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
 						}
 
 						int exist_counter = 1;
-						DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+						Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 						while (da->file_exists(new_path) || da->dir_exists(new_path)) {
 							exist_counter++;
 							new_path = vformat(new_path_base, exist_counter);
@@ -2831,7 +2831,7 @@ void FileSystemDock::_get_imported_files(const String &p_path, Vector<String> &f
 		return;
 	}
 
-	DirAccessRef da = DirAccess::open(p_path);
+	Ref<DirAccess> da = DirAccess::open(p_path);
 	da->list_dir_begin();
 	String n = da->get_next();
 	while (!n.is_empty()) {

+ 7 - 11
editor/find_in_files.cpp

@@ -211,8 +211,8 @@ float FindInFiles::get_progress() const {
 }
 
 void FindInFiles::_scan_dir(String path, PackedStringArray &out_folders) {
-	DirAccessRef dir = DirAccess::open(path);
-	if (!dir) {
+	Ref<DirAccess> dir = DirAccess::open(path);
+	if (dir.is_null()) {
 		print_verbose("Cannot open directory! " + path);
 		return;
 	}
@@ -253,8 +253,8 @@ void FindInFiles::_scan_dir(String path, PackedStringArray &out_folders) {
 }
 
 void FindInFiles::_scan_file(String fpath) {
-	FileAccessRef f = FileAccess::open(fpath, FileAccess::READ);
-	if (!f) {
+	Ref<FileAccess> f = FileAccess::open(fpath, FileAccess::READ);
+	if (f.is_null()) {
 		print_verbose(String("Cannot open file ") + fpath);
 		return;
 	}
@@ -274,8 +274,6 @@ void FindInFiles::_scan_file(String fpath) {
 			emit_signal(SNAME(SIGNAL_RESULT_FOUND), fpath, line_number, begin, end, line);
 		}
 	}
-
-	f->close();
 }
 
 void FindInFiles::_bind_methods() {
@@ -873,7 +871,7 @@ void FindInFilesPanel::_on_replace_all_clicked() {
 // Same as get_line, but preserves line ending characters.
 class ConservativeGetLine {
 public:
-	String get_line(FileAccess *f) {
+	String get_line(Ref<FileAccess> f) {
 		_line_buffer.clear();
 
 		char32_t c = f->get_8();
@@ -908,8 +906,8 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector<Result>
 	// If there are unsaved changes, the user will be asked on focus,
 	// however that means either losing changes or losing replaces.
 
-	FileAccessRef f = FileAccess::open(fpath, FileAccess::READ);
-	ERR_FAIL_COND_MSG(!f, "Cannot open file from path '" + fpath + "'.");
+	Ref<FileAccess> f = FileAccess::open(fpath, FileAccess::READ);
+	ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file from path '" + fpath + "'.");
 
 	String buffer;
 	int current_line = 1;
@@ -958,8 +956,6 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector<Result>
 	ERR_FAIL_COND_MSG(err != OK, "Cannot create file in path '" + fpath + "'.");
 
 	f->store_string(buffer);
-
-	f->close();
 }
 
 String FindInFilesPanel::get_replace_text() {

+ 2 - 3
editor/import/resource_importer_csv_translation.cpp

@@ -88,9 +88,8 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const
 			break;
 	}
 
-	FileAccessRef f = FileAccess::open(p_source_file, FileAccess::READ);
-
-	ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot open file from path '" + p_source_file + "'.");
+	Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ);
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_INVALID_PARAMETER, "Cannot open file from path '" + p_source_file + "'.");
 
 	Vector<String> line = f->get_csv_line(delimiter);
 	ERR_FAIL_COND_V(line.size() <= 1, ERR_PARSE_ERROR);

+ 3 - 8
editor/import/resource_importer_image.cpp

@@ -71,10 +71,9 @@ void ResourceImporterImage::get_import_options(const String &p_path, List<Import
 }
 
 Error ResourceImporterImage::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
-	FileAccess *f = FileAccess::open(p_source_file, FileAccess::READ);
-
-	ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file from path '" + p_source_file + "'.");
+	Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ);
 
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file from path '" + p_source_file + "'.");
 	uint64_t len = f->get_length();
 
 	Vector<uint8_t> data;
@@ -82,10 +81,8 @@ Error ResourceImporterImage::import(const String &p_source_file, const String &p
 
 	f->get_buffer(data.ptrw(), len);
 
-	memdelete(f);
-
 	f = FileAccess::open(p_save_path + ".image", FileAccess::WRITE);
-	ERR_FAIL_COND_V_MSG(!f, ERR_CANT_CREATE, "Cannot create file in path '" + p_save_path + ".image'.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_CREATE, "Cannot create file in path '" + p_save_path + ".image'.");
 
 	//save the header GDIM
 	const uint8_t header[4] = { 'G', 'D', 'I', 'M' };
@@ -95,8 +92,6 @@ Error ResourceImporterImage::import(const String &p_source_file, const String &p
 	//SAVE the actual image
 	f->store_buffer(data.ptr(), len);
 
-	memdelete(f);
-
 	return OK;
 }
 

+ 1 - 3
editor/import/resource_importer_layered_texture.cpp

@@ -257,7 +257,7 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons
 		}
 	}
 
-	FileAccessRef f = FileAccess::open(p_to_path, FileAccess::WRITE);
+	Ref<FileAccess> f = FileAccess::open(p_to_path, FileAccess::WRITE);
 	f->store_8('G');
 	f->store_8('S');
 	f->store_8('T');
@@ -280,8 +280,6 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons
 	for (int i = 0; i < mipmap_images.size(); i++) {
 		ResourceImporterTexture::save_to_ctex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
 	}
-
-	f->close();
 }
 
 Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {

+ 4 - 4
editor/import/resource_importer_obj.cpp

@@ -44,8 +44,8 @@ uint32_t EditorOBJImporter::get_import_flags() const {
 }
 
 static Error _parse_material_library(const String &p_path, Map<String, Ref<StandardMaterial3D>> &material_map, List<String> *r_missing_deps) {
-	FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Couldn't open MTL file '%s', it may not exist or not be readable.", p_path));
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Couldn't open MTL file '%s', it may not exist or not be readable.", p_path));
 
 	Ref<StandardMaterial3D> current;
 	String current_name;
@@ -203,8 +203,8 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Stand
 }
 
 static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_single_mesh, bool p_generate_tangents, bool p_optimize, Vector3 p_scale_mesh, Vector3 p_offset_mesh, List<String> *r_missing_deps) {
-	FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path));
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path));
 
 	Ref<ArrayMesh> mesh;
 	mesh.instantiate();

+ 2 - 3
editor/import/resource_importer_scene.cpp

@@ -2086,14 +2086,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
 	_generate_meshes(scene, mesh_data, gen_lods, create_shadow_meshes, LightBakeMode(light_bake_mode), lightmap_texel_size, src_lightmap_cache, mesh_lightmap_caches);
 
 	if (mesh_lightmap_caches.size()) {
-		FileAccessRef f = FileAccess::open(p_source_file + ".unwrap_cache", FileAccess::WRITE);
-		if (f) {
+		Ref<FileAccess> f = FileAccess::open(p_source_file + ".unwrap_cache", FileAccess::WRITE);
+		if (f.is_valid()) {
 			f->store_32(mesh_lightmap_caches.size());
 			for (int i = 0; i < mesh_lightmap_caches.size(); i++) {
 				String md5 = String::md5(mesh_lightmap_caches[i].ptr());
 				f->store_buffer(mesh_lightmap_caches[i].ptr(), mesh_lightmap_caches[i].size());
 			}
-			f->close();
 		}
 	}
 	err = OK;

+ 2 - 2
editor/import/resource_importer_shader_file.cpp

@@ -82,7 +82,7 @@ static String _include_function(const String &p_path, void *userpointer) {
 		include = base_path->plus_file(include);
 	}
 
-	FileAccessRef file_inc = FileAccess::open(include, FileAccess::READ, &err);
+	Ref<FileAccess> file_inc = FileAccess::open(include, FileAccess::READ, &err);
 	if (err != OK) {
 		return String();
 	}
@@ -93,7 +93,7 @@ Error ResourceImporterShaderFile::import(const String &p_source_file, const Stri
 	/* STEP 1, Read shader code */
 
 	Error err;
-	FileAccessRef file = FileAccess::open(p_source_file, FileAccess::READ, &err);
+	Ref<FileAccess> file = FileAccess::open(p_source_file, FileAccess::READ, &err);
 	ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
 	ERR_FAIL_COND_V(!file.operator->(), ERR_CANT_OPEN);
 

+ 3 - 5
editor/import/resource_importer_texture.cpp

@@ -229,7 +229,7 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo
 	}
 }
 
-void ResourceImporterTexture::save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) {
+void ResourceImporterTexture::save_to_ctex_format(Ref<FileAccess> f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) {
 	switch (p_compress_mode) {
 		case COMPRESS_LOSSLESS: {
 			bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png") ||
@@ -322,8 +322,8 @@ void ResourceImporterTexture::save_to_ctex_format(FileAccess *f, const Ref<Image
 }
 
 void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) {
-	FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE);
-	ERR_FAIL_NULL(f);
+	Ref<FileAccess> f = FileAccess::open(p_to_path, FileAccess::WRITE);
+	ERR_FAIL_COND(f.is_null());
 	f->store_8('G');
 	f->store_8('S');
 	f->store_8('T');
@@ -399,8 +399,6 @@ void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String
 	Image::UsedChannels used_channels = image->detect_used_channels(csource);
 
 	save_to_ctex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality);
-
-	memdelete(f);
 }
 
 Error ResourceImporterTexture::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {

+ 1 - 1
editor/import/resource_importer_texture.h

@@ -77,7 +77,7 @@ protected:
 	void _save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel);
 
 public:
-	static void save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality);
+	static void save_to_ctex_format(Ref<FileAccess> f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality);
 
 	static ResourceImporterTexture *get_singleton() { return singleton; }
 	virtual String get_importer_name() const override;

+ 1 - 18
editor/import/resource_importer_wav.cpp

@@ -97,7 +97,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
 	/* STEP 1, READ WAVE FILE */
 
 	Error err;
-	FileAccess *file = FileAccess::open(p_source_file, FileAccess::READ, &err);
+	Ref<FileAccess> file = FileAccess::open(p_source_file, FileAccess::READ, &err);
 
 	ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_OPEN, "Cannot open file '" + p_source_file + "'.");
 
@@ -107,8 +107,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
 	file->get_buffer((uint8_t *)&riff, 4); //RIFF
 
 	if (riff[0] != 'R' || riff[1] != 'I' || riff[2] != 'F' || riff[3] != 'F') {
-		file->close();
-		memdelete(file);
 		ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
 	}
 
@@ -122,8 +120,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
 	file->get_buffer((uint8_t *)&wave, 4); //RIFF
 
 	if (wave[0] != 'W' || wave[1] != 'A' || wave[2] != 'V' || wave[3] != 'E') {
-		file->close();
-		memdelete(file);
 		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Not a WAV file (no WAVE RIFF header).");
 	}
 
@@ -166,15 +162,11 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
 			//Consider revision for engine version 3.0
 			compression_code = file->get_16();
 			if (compression_code != 1 && compression_code != 3) {
-				file->close();
-				memdelete(file);
 				ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Format not supported for WAVE file (not PCM). Save WAVE files as uncompressed PCM instead.");
 			}
 
 			format_channels = file->get_16();
 			if (format_channels != 1 && format_channels != 2) {
-				file->close();
-				memdelete(file);
 				ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Format not supported for WAVE file (not stereo or mono).");
 			}
 
@@ -185,8 +177,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
 			format_bits = file->get_16(); // bits per sample
 
 			if (format_bits % 8 || format_bits == 0) {
-				file->close();
-				memdelete(file);
 				ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Invalid amount of bits in the sample (should be one of 8, 16, 24 or 32).");
 			}
 
@@ -206,8 +196,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
 			frames = chunksize;
 
 			if (format_channels == 0) {
-				file->close();
-				memdelete(file);
 				ERR_FAIL_COND_V(format_channels == 0, ERR_INVALID_DATA);
 			}
 			frames /= format_channels;
@@ -254,8 +242,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
 			}
 
 			if (file->eof_reached()) {
-				file->close();
-				memdelete(file);
 				ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Premature end of file.");
 			}
 		}
@@ -295,9 +281,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
 		file->seek(file_pos + chunksize);
 	}
 
-	file->close();
-	memdelete(file);
-
 	// STEP 2, APPLY CONVERSIONS
 
 	bool is16 = format_bits != 8;

+ 3 - 3
editor/plugin_config_dialog.cpp

@@ -50,8 +50,8 @@ void PluginConfigDialog::_on_confirmed() {
 	String path = "res://addons/" + subfolder_edit->get_text();
 
 	if (!_edit_mode) {
-		DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
-		if (!d || d->make_dir_recursive(path) != OK) {
+		Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		if (d.is_null() || d->make_dir_recursive(path) != OK) {
 			return;
 		}
 	}
@@ -137,7 +137,7 @@ void PluginConfigDialog::_on_required_text_changed(const String &) {
 		subfolder_validation->set_texture(invalid_icon);
 		subfolder_validation->set_tooltip(TTR("Subfolder name is not a valid folder name."));
 	} else {
-		DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 		String path = "res://addons/" + subfolder_edit->get_text();
 		if (dir->dir_exists(path) && !_edit_mode) { // Only show this error if in "create" mode.
 			is_valid = false;

+ 7 - 18
editor/plugins/asset_library_editor_plugin.cpp

@@ -729,9 +729,8 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
 		if (use_cache) {
 			String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
 
-			FileAccess *file = FileAccess::open(cache_filename_base + ".data", FileAccess::READ);
-
-			if (file) {
+			Ref<FileAccess> file = FileAccess::open(cache_filename_base + ".data", FileAccess::READ);
+			if (file.is_valid()) {
 				PackedByteArray cached_data;
 				int len = file->get_32();
 				cached_data.resize(len);
@@ -740,8 +739,6 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
 				file->get_buffer(w, len);
 
 				image_data = cached_data;
-				file->close();
-				memdelete(file);
 			}
 		}
 
@@ -808,23 +805,17 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
 				if (headers[i].findn("ETag:") == 0) { // Save etag
 					String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
 					String new_etag = headers[i].substr(headers[i].find(":") + 1, headers[i].length()).strip_edges();
-					FileAccess *file;
-
-					file = FileAccess::open(cache_filename_base + ".etag", FileAccess::WRITE);
-					if (file) {
+					Ref<FileAccess> file = FileAccess::open(cache_filename_base + ".etag", FileAccess::WRITE);
+					if (file.is_valid()) {
 						file->store_line(new_etag);
-						file->close();
-						memdelete(file);
 					}
 
 					int len = p_data.size();
 					const uint8_t *r = p_data.ptr();
 					file = FileAccess::open(cache_filename_base + ".data", FileAccess::WRITE);
-					if (file) {
+					if (file.is_valid()) {
 						file->store_32(len);
 						file->store_buffer(r, len);
-						file->close();
-						memdelete(file);
 					}
 
 					break;
@@ -858,11 +849,9 @@ void EditorAssetLibrary::_update_image_queue() {
 			Vector<String> headers;
 
 			if (FileAccess::exists(cache_filename_base + ".etag") && FileAccess::exists(cache_filename_base + ".data")) {
-				FileAccess *file = FileAccess::open(cache_filename_base + ".etag", FileAccess::READ);
-				if (file) {
+				Ref<FileAccess> file = FileAccess::open(cache_filename_base + ".etag", FileAccess::READ);
+				if (file.is_valid()) {
 					headers.push_back("If-None-Match: " + file->get_line());
-					file->close();
-					memdelete(file);
 				}
 			}
 

+ 2 - 7
editor/plugins/script_editor_plugin.cpp

@@ -1091,13 +1091,11 @@ void ScriptEditor::_file_dialog_action(String p_file) {
 	switch (file_dialog_option) {
 		case FILE_NEW_TEXTFILE: {
 			Error err;
-			FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &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;
 			}
-			file->close();
-			memdelete(file);
 
 			if (EditorFileSystem::get_singleton()) {
 				if (textfile_extensions.has(p_file.get_extension())) {
@@ -2211,17 +2209,14 @@ Error ScriptEditor::_save_text_file(Ref<TextFile> p_text_file, const String &p_p
 	String source = sqscr->get_text();
 
 	Error err;
-	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 + "'.");
 
 	file->store_string(source);
 	if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
-		memdelete(file);
 		return ERR_CANT_CREATE;
 	}
-	file->close();
-	memdelete(file);
 
 	if (ResourceSaver::get_timestamp_on_save()) {
 		p_text_file->set_last_modified_time(FileAccess::get_modified_time(p_path));

+ 2 - 4
editor/pot_generator.cpp

@@ -93,7 +93,7 @@ void POTGenerator::generate_pot(const String &p_file) {
 
 void POTGenerator::_write_to_pot(const String &p_file) {
 	Error err;
-	FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+	Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
 	if (err != OK) {
 		ERR_PRINT("Failed to open " + p_file);
 		return;
@@ -155,11 +155,9 @@ void POTGenerator::_write_to_pot(const String &p_file) {
 			}
 		}
 	}
-
-	file->close();
 }
 
-void POTGenerator::_write_msgid(FileAccess *r_file, const String &p_id, bool p_plural) {
+void POTGenerator::_write_msgid(Ref<FileAccess> r_file, const String &p_id, bool p_plural) {
 	// Split \\n and \n.
 	Vector<String> temp = p_id.split("\\n");
 	Vector<String> msg_lines;

+ 1 - 1
editor/pot_generator.h

@@ -49,7 +49,7 @@ class POTGenerator {
 	OrderedHashMap<String, Vector<MsgidData>> all_translation_strings;
 
 	void _write_to_pot(const String &p_file);
-	void _write_msgid(FileAccess *r_file, const String &p_id, bool p_plural);
+	void _write_msgid(Ref<FileAccess> r_file, const String &p_id, bool p_plural);
 	void _add_new_msgid(const String &p_msgid, const String &p_context, const String &p_plural, const String &p_location);
 
 #ifdef DEBUG_POT

+ 13 - 17
editor/project_manager.cpp

@@ -147,7 +147,7 @@ private:
 	}
 
 	String _test_path() {
-		DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 		String valid_path, valid_install_path;
 		if (d->change_dir(project_path->get_text()) == OK) {
 			valid_path = project_path->get_text();
@@ -186,8 +186,7 @@ private:
 		if (mode == MODE_IMPORT || mode == MODE_RENAME) {
 			if (!valid_path.is_empty() && !d->file_exists("project.godot")) {
 				if (valid_path.ends_with(".zip")) {
-					FileAccess *src_f = nullptr;
-					zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+					zlib_filefunc_def io = zipio_create_io();
 
 					unzFile pkg = unzOpen2(valid_path.utf8().get_data(), &io);
 					if (!pkg) {
@@ -383,7 +382,7 @@ private:
 			return;
 		}
 
-		DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 		if (d->change_dir(project_path->get_text()) == OK) {
 			if (!d->dir_exists(project_name_no_edges)) {
 				if (d->make_dir(project_name_no_edges) == OK) {
@@ -500,8 +499,7 @@ private:
 						zip_path = project_path->get_text();
 					}
 
-					FileAccess *src_f = nullptr;
-					zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+					zlib_filefunc_def io = zipio_create_io();
 
 					unzFile pkg = unzOpen2(zip_path.utf8().get_data(), &io);
 					if (!pkg) {
@@ -549,7 +547,7 @@ private:
 							path = path.substr(0, path.length() - 1);
 							String rel_path = path.substr(zip_root.length());
 
-							DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+							Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 							da->make_dir(dir.plus_file(rel_path));
 						} else {
 							Vector<uint8_t> data;
@@ -564,11 +562,9 @@ private:
 							}
 							unzCloseCurrentFile(pkg);
 
-							FileAccess *f = FileAccess::open(dir.plus_file(rel_path), FileAccess::WRITE);
-
-							if (f) {
+							Ref<FileAccess> f = FileAccess::open(dir.plus_file(rel_path), FileAccess::WRITE);
+							if (f.is_valid()) {
 								f->store_buffer(data.ptr(), data.size());
-								memdelete(f);
 							} else {
 								failed_files.push_back(rel_path);
 							}
@@ -615,7 +611,7 @@ private:
 
 	void _remove_created_folder() {
 		if (!created_folder_path.is_empty()) {
-			DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+			Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 			d->remove(created_folder_path);
 
 			create_dir->set_disabled(false);
@@ -719,7 +715,7 @@ public:
 				project_path->set_text(fav_dir);
 				fdialog->set_current_dir(fav_dir);
 			} else {
-				DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+				Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 				project_path->set_text(d->get_current_dir());
 				fdialog->set_current_dir(d->get_current_dir());
 			}
@@ -2280,7 +2276,7 @@ void ProjectManager::_run_project() {
 }
 
 void ProjectManager::_scan_dir(const String &path, List<String> *r_projects) {
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	Error error = da->change_dir(path);
 	ERR_FAIL_COND_MSG(error != OK, "Could not scan directory at: " + path);
 	da->list_dir_begin();
@@ -2409,7 +2405,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files) {
 		return;
 	}
 	Set<String> folders_set;
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	for (int i = 0; i < p_files.size(); i++) {
 		String file = p_files[i];
 		folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir());
@@ -2422,7 +2418,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files) {
 
 		bool confirm = true;
 		if (folders.size() == 1) {
-			DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+			Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 			if (dir->change_dir(folders[0]) == OK) {
 				dir->list_dir_begin();
 				String file = dir->get_next();
@@ -2849,7 +2845,7 @@ ProjectManager::ProjectManager() {
 
 	_load_recent_projects();
 
-	DirAccessRef dir_access = DirAccess::create(DirAccess::AccessType::ACCESS_FILESYSTEM);
+	Ref<DirAccess> dir_access = DirAccess::create(DirAccess::AccessType::ACCESS_FILESYSTEM);
 
 	String default_project_path = EditorSettings::get_singleton()->get("filesystem/directories/default_project_path");
 	if (!dir_access->dir_exists(default_project_path)) {

+ 2 - 5
editor/scene_tree_dock.cpp

@@ -3149,9 +3149,8 @@ void SceneTreeDock::_update_create_root_dialog() {
 			favorite_nodes->get_child(i)->queue_delete();
 		}
 
-		FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ);
-
-		if (f) {
+		Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ);
+		if (f.is_valid()) {
 			while (!f->eof_reached()) {
 				String l = f->get_line().strip_edges();
 
@@ -3168,8 +3167,6 @@ void SceneTreeDock::_update_create_root_dialog() {
 					button->connect("pressed", callable_mp(this, &SceneTreeDock::_favorite_root_selected), make_binds(l));
 				}
 			}
-
-			memdelete(f);
 		}
 
 		if (!favorite_nodes->is_visible_in_tree()) {

+ 6 - 8
editor/script_create_dialog.cpp

@@ -246,7 +246,7 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
 	}
 
 	{
-		DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 		if (da->change_dir(p.get_base_dir()) != OK) {
 			return TTR("Base path is invalid.");
 		}
@@ -254,7 +254,7 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
 
 	{
 		// Check if file exists.
-		DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 		if (da->dir_exists(p)) {
 			return TTR("A directory with the same name exists.");
 		} else if (p_file_must_exist && !da->file_exists(p)) {
@@ -547,7 +547,7 @@ void ScriptCreateDialog::_path_changed(const String &p_path) {
 	}
 
 	// Check if file exists.
-	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges());
 	if (da->file_exists(p)) {
 		is_new_script_created = false;
@@ -824,8 +824,8 @@ Vector<ScriptLanguage::ScriptTemplate> ScriptCreateDialog::_get_user_templates(c
 
 	String dir_path = p_dir.plus_file(p_object);
 
-	DirAccessRef d = DirAccess::open(dir_path);
-	if (d) {
+	Ref<DirAccess> d = DirAccess::open(dir_path);
+	if (d.is_valid()) {
 		d->list_dir_begin();
 		String file = d->get_next();
 		while (file != String()) {
@@ -858,7 +858,7 @@ ScriptLanguage::ScriptTemplate ScriptCreateDialog::_parse_template(const ScriptL
 
 	// Parse file for meta-information and script content
 	Error err;
-	FileAccess *file = FileAccess::open(p_path.plus_file(p_filename), FileAccess::READ, &err);
+	Ref<FileAccess> file = FileAccess::open(p_path.plus_file(p_filename), FileAccess::READ, &err);
 	if (!err) {
 		while (!file->eof_reached()) {
 			String line = file->get_line();
@@ -890,8 +890,6 @@ ScriptLanguage::ScriptTemplate ScriptCreateDialog::_parse_template(const ScriptL
 				script_template.content += line.replace("\t", "_TS_") + "\n";
 			}
 		}
-		file->close();
-		memdelete(file);
 	}
 
 	script_template.content = script_template.content.lstrip("\n");

+ 3 - 3
editor/shader_create_dialog.cpp

@@ -313,7 +313,7 @@ void ShaderCreateDialog::_path_changed(const String &p_path) {
 		return;
 	}
 
-	DirAccessRef f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges());
 	if (f->file_exists(p)) {
 		is_new_shader_created = false;
@@ -371,12 +371,12 @@ String ShaderCreateDialog::_validate_path(const String &p_path) {
 		return TTR("Path is not local.");
 	}
 
-	DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	if (d->change_dir(p.get_base_dir()) != OK) {
 		return TTR("Invalid base path.");
 	}
 
-	DirAccessRef f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	Ref<DirAccess> f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
 	if (f->dir_exists(p)) {
 		return TTR("A directory with the same name exists.");
 	}

+ 7 - 7
main/main.cpp

@@ -2112,8 +2112,8 @@ bool Main::start() {
 		}
 
 		{
-			DirAccessRef da = DirAccess::open(doc_tool_path);
-			ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a valid directory path.");
+			Ref<DirAccess> da = DirAccess::open(doc_tool_path);
+			ERR_FAIL_COND_V_MSG(da.is_null(), false, "Argument supplied to --doctool must be a valid directory path.");
 		}
 
 #ifndef MODULE_MONO_ENABLED
@@ -2149,7 +2149,7 @@ bool Main::start() {
 				checked_paths.insert(path);
 
 				// Create the module documentation directory if it doesn't exist
-				DirAccessRef da = DirAccess::create_for_path(path);
+				Ref<DirAccess> da = DirAccess::create_for_path(path);
 				err = da->make_dir_recursive(path);
 				ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create directory: " + path + ": " + itos(err));
 
@@ -2161,7 +2161,7 @@ bool Main::start() {
 
 		String index_path = doc_tool_path.plus_file("doc/classes");
 		// Create the main documentation directory if it doesn't exist
-		DirAccessRef da = DirAccess::create_for_path(index_path);
+		Ref<DirAccess> da = DirAccess::create_for_path(index_path);
 		err = da->make_dir_recursive(index_path);
 		ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create index directory: " + index_path + ": " + itos(err));
 
@@ -2501,11 +2501,11 @@ bool Main::start() {
 						int sep = local_game_path.rfind("/");
 
 						if (sep == -1) {
-							DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+							Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 							local_game_path = da->get_current_dir().plus_file(local_game_path);
 						} else {
-							DirAccessRef da = DirAccess::open(local_game_path.substr(0, sep));
-							if (da) {
+							Ref<DirAccess> da = DirAccess::open(local_game_path.substr(0, sep));
+							if (da.is_valid()) {
 								local_game_path = da->get_current_dir().plus_file(
 										local_game_path.substr(sep + 1, local_game_path.length()));
 							}

部分文件因为文件数量过多而无法显示