diff options
Diffstat (limited to 'core')
58 files changed, 725 insertions, 902 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 93c1abe7b5..06bfc0c562 100644 --- a/core/config/project_settings.cpp +++ b/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; } diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 706395afa9..892b74c26a 100644 --- a/core/core_bind.cpp +++ b/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; } @@ -1073,25 +1072,22 @@ Error File::open_compressed(const String &p_path, ModeFlags p_mode_flags, Compre } 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.unref(); } bool File::is_open() const { @@ -1099,79 +1095,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 +1188,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 +1201,7 @@ String File::get_as_text() const { } text += l; - f->seek(original_pos); + const_cast<FileAccess *>(*f)->seek(original_pos); return text; } @@ -1219,12 +1215,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 +1231,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 +1241,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 +1335,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 +1352,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 +1436,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 +1451,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 +1536,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 +1553,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 +1579,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 +1587,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 +1601,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 +1613,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 +1655,6 @@ Directory::Directory() { d = DirAccess::create(DirAccess::ACCESS_RESOURCES); } -Directory::~Directory() { - if (d) { - memdelete(d); - } -} - ////// Marshalls ////// Marshalls *Marshalls::singleton = nullptr; diff --git a/core/core_bind.h b/core/core_bind.h index 4d26698f99..591cacdabb 100644 --- a/core/core_bind.h +++ b/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 { diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index 9acc28f51e..f64c30dca5 100644 --- a/core/extension/extension_api_dump.cpp +++ b/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 diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp index b5b340731d..a312ce4ebd 100644 --- a/core/extension/gdnative_interface.cpp +++ b/core/extension/gdnative_interface.cpp @@ -241,6 +241,13 @@ static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self) return self->booleanize(); } +static void gdnative_variant_sub(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst) { + const Variant *a = (const Variant *)p_a; + const Variant *b = (const Variant *)p_b; + memnew_placement(r_dst, Variant); + Variant::sub(*a, *b, *(Variant *)r_dst); +} + static void gdnative_variant_blend(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) { const Variant *a = (const Variant *)p_a; const Variant *b = (const Variant *)p_b; @@ -939,6 +946,7 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) { gdni.variant_iter_get = gdnative_variant_iter_get; gdni.variant_hash_compare = gdnative_variant_hash_compare; gdni.variant_booleanize = gdnative_variant_booleanize; + gdni.variant_sub = gdnative_variant_sub; gdni.variant_blend = gdnative_variant_blend; gdni.variant_interpolate = gdnative_variant_interpolate; gdni.variant_duplicate = gdnative_variant_duplicate; diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index 732a1b5af0..2bac52dc4a 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -416,6 +416,7 @@ typedef struct { void (*variant_iter_get)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other); GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self); + void (*variant_sub)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst); void (*variant_blend)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst); void (*variant_interpolate)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst); void (*variant_duplicate)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep); diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp index 509405494b..5436f7d51e 100644 --- a/core/extension/native_extension_manager.cpp +++ b/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); diff --git a/core/input/input.cpp b/core/input/input.cpp index 343076b4e1..0db20a7c82 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -855,6 +855,8 @@ void Input::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, co return; } + ERR_FAIL_INDEX(p_shape, CursorShape::CURSOR_MAX); + set_custom_mouse_cursor_func(p_cursor, p_shape, p_hotspot); } diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index c942b417e4..bc24cac955 100644 --- a/core/io/config_file.cpp +++ b/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; } diff --git a/core/io/config_file.h b/core/io/config_file.h index 71e9080fb7..7a52b0e16a 100644 --- a/core/io/config_file.h +++ b/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); diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp index 73efdeb38e..433a7efb21 100644 --- a/core/io/dir_access.cpp +++ b/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,54 +262,45 @@ 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; - } - - 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> fsrc = FileAccess::open(p_from, FileAccess::READ, &err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_from); + + Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to); + + fsrc->seek_end(0); + int size = fsrc->get_position(); + fsrc->seek(0); + err = OK; + while (size--) { + if (fsrc->get_error() != OK) { + err = fsrc->get_error(); + break; + } + if (fdst->get_error() != OK) { + err = fdst->get_error(); + break; + } - fsrc->seek_end(0); - int size = fsrc->get_position(); - fsrc->seek(0); - err = OK; - while (size--) { - if (fsrc->get_error() != OK) { - err = fsrc->get_error(); - break; - } - if (fdst->get_error() != OK) { - err = fdst->get_error(); - break; + fdst->store_8(fsrc->get_8()); } - - fdst->store_8(fsrc->get_8()); } if (err == OK && p_chmod_flags != -1) { - 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 +308,6 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { } } - memdelete(fsrc); - memdelete(fdst); - return err; } @@ -343,7 +329,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 +385,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 +399,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; } diff --git a/core/io/dir_access.h b/core/io/dir_access.h index b97d097842..0125f011b5 100644 --- a/core/io/dir_access.h +++ b/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 diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index 86836454c5..7d8da1b11c 100644 --- a/core/io/file_access.cpp +++ b/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.unref(); } 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); } diff --git a/core/io/file_access.h b/core/io/file_access.h index a5150010da..e2c11142d7 100644 --- a/core/io/file_access.h +++ b/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); } @@ -87,7 +88,6 @@ public: WRITE_READ = 7, }; - virtual void close() = 0; ///< close a file virtual bool is_open() const = 0; ///< true when file is open virtual String get_path() const { return ""; } /// returns the path for the current open file @@ -148,9 +148,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 +176,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 diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index 85faf04315..1d0a718166 100644 --- a/core/io/file_access_compressed.cpp +++ b/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.unref(); ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted."); } read_total = f->get_32(); @@ -97,17 +97,13 @@ 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) { - close(); - } + _close(); Error err; f = FileAccess::open(p_path, p_mode_flags, &err); if (err != OK) { //not openable - - f = nullptr; + f.unref(); return err; } @@ -127,8 +123,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.unref(); return err; } } @@ -136,8 +131,8 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) { return OK; } -void FileAccessCompressed::close() { - if (!f) { +void FileAccessCompressed::_close() { + if (f.is_null()) { return; } @@ -182,17 +177,15 @@ void FileAccessCompressed::close() { buffer.clear(); read_blocks.clear(); } - - memdelete(f); - f = nullptr; + f.unref(); } 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 +215,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 +224,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 +233,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 +242,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 +251,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 +284,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 +325,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 +340,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 +356,19 @@ 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) { - close(); - } + _close(); } diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h index 97ef3fbdeb..b8382e61d9 100644 --- a/core/io/file_access_compressed.h +++ b/core/io/file_access_compressed.h @@ -61,15 +61,16 @@ class FileAccessCompressed : public FileAccess { String magic = "GCMP"; mutable Vector<uint8_t> buffer; - FileAccess *f = nullptr; + Ref<FileAccess> f; + + void _close(); 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 virtual bool is_open() const; ///< true when file is open virtual void seek(uint64_t p_position); ///< seek to a given position diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 8ee19d3d06..d1b014a0be 100644 --- a/core/io/file_access_encrypted.cpp +++ b/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; @@ -115,30 +115,11 @@ Error FileAccessEncrypted::_open(const String &p_path, int p_mode_flags) { return OK; } -void FileAccessEncrypted::close() { - if (!file) { +void FileAccessEncrypted::_close() { + if (file.is_null()) { return; } - _release(); - - file->close(); - memdelete(file); - - file = nullptr; -} - -void FileAccessEncrypted::release() { - if (!file) { - return; - } - - _release(); - - file = nullptr; -} - -void FileAccessEncrypted::_release() { if (writing) { Vector<uint8_t> compressed; uint64_t len = data.size(); @@ -176,6 +157,8 @@ void FileAccessEncrypted::_release() { file->store_buffer(compressed.ptr(), compressed.size()); data.clear(); } + + file.unref(); } bool FileAccessEncrypted::is_open() const { @@ -183,7 +166,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 +174,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 +274,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 +295,5 @@ Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t } FileAccessEncrypted::~FileAccessEncrypted() { - if (file) { - close(); - } + _close(); } diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index be5904c894..0d1ee6a4d8 100644 --- a/core/io/file_access_encrypted.h +++ b/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; @@ -54,15 +54,13 @@ private: mutable bool eofed = false; bool use_magic = true; - void _release(); + void _close(); 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 - virtual void release(); ///< finish and keep base file open virtual bool is_open() const; ///< true when file is open virtual String get_path() const; /// returns the path for the current open file diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index 4aca26b007..943dc72307 100644 --- a/core/io/file_access_memory.cpp +++ b/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); } @@ -94,10 +94,6 @@ Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) { return OK; } -void FileAccessMemory::close() { - data = nullptr; -} - bool FileAccessMemory::is_open() const { return data != nullptr; } diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h index 50b23e1f32..868b8ed481 100644 --- a/core/io/file_access_memory.h +++ b/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); @@ -46,7 +46,6 @@ public: virtual Error open_custom(const uint8_t *p_data, uint64_t p_len); ///< open a file virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open virtual void seek(uint64_t p_position); ///< seek to a given position diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index 612181f8d5..1365b4b593 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -254,9 +254,8 @@ void FileAccessNetwork::_respond(uint64_t p_len, Error p_status) { Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) { ERR_FAIL_COND_V(p_mode_flags != READ, ERR_UNAVAILABLE); - if (opened) { - close(); - } + _close(); + FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; DEBUG_PRINT("open: " + p_path); @@ -287,7 +286,7 @@ Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) { return response; } -void FileAccessNetwork::close() { +void FileAccessNetwork::_close() { if (!opened) { return; } @@ -483,7 +482,7 @@ FileAccessNetwork::FileAccessNetwork() { } FileAccessNetwork::~FileAccessNetwork() { - close(); + _close(); FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; nc->lock_mutex(); diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index 6cae49b540..6afbf6adf5 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -113,6 +113,7 @@ class FileAccessNetwork : public FileAccess { void _queue_page(int32_t p_page) const; void _respond(uint64_t p_len, Error p_status); void _set_block(uint64_t p_offset, const Vector<uint8_t> &p_block); + void _close(); public: enum Command { @@ -131,7 +132,6 @@ public: }; virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open virtual void seek(uint64_t p_position); ///< seek to a given position diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 7dbea96c3d..c6e14ffee7 100644 --- a/core/io/file_access_pack.cpp +++ b/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)); } @@ -252,15 +226,17 @@ Error FileAccessPack::_open(const String &p_path, int p_mode_flags) { return ERR_UNAVAILABLE; } -void FileAccessPack::close() { - f->close(); -} - bool FileAccessPack::is_open() const { - return f->is_open(); + if (f.is_valid()) { + return f->is_open(); + } else { + return false; + } } void FileAccessPack::seek(uint64_t p_position) { + ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use."); + if (p_position > pf.size) { eof = true; } else { @@ -288,6 +264,7 @@ bool FileAccessPack::eof_reached() const { } uint8_t FileAccessPack::get_8() const { + ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use."); if (pos >= pf.size) { eof = true; return 0; @@ -298,6 +275,7 @@ uint8_t FileAccessPack::get_8() const { } uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const { + ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use."); ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); if (eof) { @@ -321,6 +299,8 @@ uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const { } void FileAccessPack::set_big_endian(bool p_big_endian) { + ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use."); + FileAccess::set_big_endian(p_big_endian); f->set_big_endian(p_big_endian); } @@ -351,16 +331,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 +348,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 +356,6 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil eof = false; } -FileAccessPack::~FileAccessPack() { - if (f) { - f->close(); - memdelete(f); - } -} - ////////////////////////////////////////////////////////////////////////////////// // DIR ACCESS ////////////////////////////////////////////////////////////////////////////////// @@ -507,7 +476,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; diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index d4b32df2c7..44df2029bd 100644 --- a/core/io/file_access_pack.h +++ b/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,14 +150,13 @@ 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; } virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; } public: - virtual void close(); virtual bool is_open() const; virtual void seek(uint64_t p_position); @@ -183,10 +182,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 +202,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 +230,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 +249,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; } diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index 6347862775..17f2335a8e 100644 --- a/core/io/file_access_zip.cpp +++ b/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)); } @@ -233,7 +235,7 @@ ZipArchive::~ZipArchive() { } Error FileAccessZip::_open(const String &p_path, int p_mode_flags) { - close(); + _close(); ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED); ZipArchive *arch = ZipArchive::get_singleton(); @@ -247,7 +249,7 @@ Error FileAccessZip::_open(const String &p_path, int p_mode_flags) { return OK; } -void FileAccessZip::close() { +void FileAccessZip::_close() { if (!zfile) { return; } @@ -339,7 +341,7 @@ FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile } FileAccessZip::~FileAccessZip() { - close(); + _close(); } #endif // MINIZIP_ENABLED diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index a238c66437..2504aeedc4 100644 --- a/core/io/file_access_zip.h +++ b/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(); @@ -82,9 +82,10 @@ class FileAccessZip : public FileAccess { mutable bool at_eof; + void _close(); + public: virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open virtual void seek(uint64_t p_position); ///< seek to a given position diff --git a/core/io/image.cpp b/core/io/image.cpp index fad9942017..4aed5a913a 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -3276,7 +3276,7 @@ Ref<Image> Image::rgbe_to_srgb() { for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { - new_image->set_pixel(col, row, get_pixel(col, row).to_srgb()); + new_image->set_pixel(col, row, get_pixel(col, row).linear_to_srgb()); } } diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index 5518ec8ceb..2ccc95f0de 100644 --- a/core/io/image_loader.cpp +++ b/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; diff --git a/core/io/image_loader.h b/core/io/image_loader.h index 37d7620f96..9409617268 100644 --- a/core/io/image_loader.h +++ b/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); diff --git a/core/io/logger.cpp b/core/io/logger.cpp index 2b6f230434..c19fc2820b 100644 --- a/core/io/logger.cpp +++ b/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.unref(); 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; diff --git a/core/io/logger.h b/core/io/logger.h index 047ee3d0f1..e3ac00f11c 100644 --- a/core/io/logger.h +++ b/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 { diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index b3bf0cff2d..aa1b323db2 100644 --- a/core/io/pck_packer.cpp +++ b/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,9 @@ Error PCKPacker::flush(bool p_verbose) { fhead->store_32(flags); } - if (fae) { - fae->release(); - memdelete(fae); + if (fae.is_valid()) { + fhead.unref(); + fae.unref(); } int header_padding = _get_pad(alignment, file->get_position()); @@ -222,14 +214,13 @@ 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; + 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,9 @@ Error PCKPacker::flush(bool p_verbose) { to_write -= read; } - if (fae) { - fae->release(); - memdelete(fae); + if (fae.is_valid()) { + ftmp.unref(); + fae.unref(); } int pad = _get_pad(alignment, file->get_position()); @@ -252,8 +243,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 +254,8 @@ Error PCKPacker::flush(bool p_verbose) { printf("\n"); } - file->close(); + file.unref(); memdelete_arr(buf); return OK; } - -PCKPacker::~PCKPacker() { - if (file != nullptr) { - memdelete(file); - } - file = nullptr; -} diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h index 583171a70b..77ec293fb2 100644 --- a/core/io/pck_packer.h +++ b/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 diff --git a/core/io/resource.cpp b/core/io/resource.cpp index f90a6e9304..bf91438810 100644 --- a/core/io/resource.cpp +++ b/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 diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index b65993e3dd..8d4dbc3f73 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -101,6 +101,50 @@ void ResourceLoaderBinary::_advance_padding(uint32_t p_len) { } } +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)); +#ifdef BIG_ENDIAN_ENABLED + { + uint64_t *dst = (uint64_t *)dst; + for (size_t i = 0; i < count; i++) { + dst[i] = BSWAP64(dst[i]); + } + } +#endif + } 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(); + } + } else { + ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "real_t size is neither 4 nor 8!"); + } + } else { + if (sizeof(real_t) == 4) { + // Ideal case with float-precision + f->get_buffer((uint8_t *)dst, count * sizeof(float)); +#ifdef BIG_ENDIAN_ENABLED + { + uint32_t *dst = (uint32_t *)dst; + for (size_t i = 0; i < count; i++) { + dst[i] = BSWAP32(dst[i]); + } + } +#endif + } else if (sizeof(real_t) == 8) { + for (size_t i = 0; i < count; ++i) { + dst[i] = f->get_float(); + } + } else { + ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "real_t size is neither 4 nor 8!"); + } + } + return OK; +} + StringName ResourceLoaderBinary::_get_string() { uint32_t id = f->get_32(); if (id & 0x80000000) { @@ -528,21 +572,9 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { Vector<Vector2> array; array.resize(len); Vector2 *w = array.ptrw(); - if (sizeof(Vector2) == 8) { - f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 2); -#ifdef BIG_ENDIAN_ENABLED - { - uint32_t *ptr = (uint32_t *)w.ptr(); - for (int i = 0; i < len * 2; i++) { - ptr[i] = BSWAP32(ptr[i]); - } - } - -#endif - - } else { - ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector2 size is NOT 8!"); - } + static_assert(sizeof(Vector2) == 2 * sizeof(real_t)); + const Error err = read_reals(reinterpret_cast<real_t *>(w), f, len * 2); + ERR_FAIL_COND_V(err != OK, err); r_v = array; @@ -553,21 +585,9 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { Vector<Vector3> array; array.resize(len); Vector3 *w = array.ptrw(); - if (sizeof(Vector3) == 12) { - f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 3); -#ifdef BIG_ENDIAN_ENABLED - { - uint32_t *ptr = (uint32_t *)w.ptr(); - for (int i = 0; i < len * 3; i++) { - ptr[i] = BSWAP32(ptr[i]); - } - } - -#endif - - } else { - ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector3 size is NOT 12!"); - } + static_assert(sizeof(Vector3) == 3 * sizeof(real_t)); + const Error err = read_reals(reinterpret_cast<real_t *>(w), f, len * 3); + ERR_FAIL_COND_V(err != OK, err); r_v = array; @@ -578,22 +598,19 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { Vector<Color> array; array.resize(len); Color *w = array.ptrw(); - if (sizeof(Color) == 16) { - f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 4); + // Colors always use `float` even with double-precision support enabled + static_assert(sizeof(Color) == 4 * sizeof(float)); + f->get_buffer((uint8_t *)w, len * sizeof(float) * 4); #ifdef BIG_ENDIAN_ENABLED - { - uint32_t *ptr = (uint32_t *)w.ptr(); - for (int i = 0; i < len * 4; i++) { - ptr[i] = BSWAP32(ptr[i]); - } + { + uint32_t *ptr = (uint32_t *)w.ptr(); + for (int i = 0; i < len * 4; i++) { + ptr[i] = BSWAP32(ptr[i]); } + } #endif - } else { - ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Color size is NOT 16!"); - } - r_v = array; } break; default: { @@ -772,7 +789,7 @@ Error ResourceLoaderBinary::load() { resource_cache.push_back(res); if (main) { - f->close(); + f.unref(); resource = res; resource->set_as_translation_remapped(translation_remapped); error = OK; @@ -787,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); @@ -817,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; @@ -839,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; @@ -847,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.unref(); ERR_FAIL_MSG("Failed to open binary resource file: " + local_path + "."); } f = fac; @@ -859,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.unref(); ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + "."); } @@ -884,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.unref(); ERR_FAIL_MSG(vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).", local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH)); } @@ -961,12 +978,12 @@ void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_kee if (f->eof_reached()) { error = ERR_FILE_CORRUPT; - f->close(); + f.unref(); 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; @@ -974,11 +991,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.unref(); return ""; } f = fac; @@ -986,7 +1003,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.unref(); return ""; } @@ -1000,7 +1017,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.unref(); return ""; } @@ -1009,19 +1026,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 + "'."); @@ -1079,8 +1090,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); @@ -1089,10 +1100,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(); @@ -1100,36 +1111,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); @@ -1152,10 +1153,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"); } @@ -1184,8 +1183,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)); @@ -1294,22 +1291,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 } @@ -1326,8 +1320,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 } @@ -1345,7 +1339,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++) { @@ -1354,7 +1348,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); @@ -1813,14 +1807,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) { @@ -1836,15 +1830,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); } @@ -1885,8 +1877,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; } @@ -2044,14 +2034,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; } diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 5403168a53..72a3c6751d 100644 --- a/core/io/resource_format_binary.h +++ b/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 { diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 9b6440e2a2..b4f73b3b25 100644 --- a/core/io/resource_importer.cpp +++ b/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 { diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 2419c76dd3..fe9693aa20 100644 --- a/core/io/resource_loader.cpp +++ b/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); } } diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp index d0335bed3a..515b7c710e 100644 --- a/core/io/resource_uid.cpp +++ b/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(); @@ -220,11 +220,9 @@ Error ResourceUID::update_cache() { } } - if (f != nullptr) { + if (f.is_valid()) { f->seek(0); f->store_32(cache_entries); //update amount of entries - f->close(); - memdelete(f); } changed = false; diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp index 30df46a6b4..ae1ad304d7 100644 --- a/core/io/translation_loader_po.cpp +++ b/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); } diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h index 1c58896a00..7da361cf24 100644 --- a/core/io/translation_loader_po.h +++ b/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; diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index 360da46f96..7b43193f47 100644 --- a/core/io/xml_parser.cpp +++ b/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; } diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp index 2c4f8346ab..2cc844b628 100644 --- a/core/io/zip_io.cpp +++ b/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; diff --git a/core/io/zip_io.h b/core/io/zip_io.h index 6a29703449..3bcd1f830d 100644 --- a/core/io/zip_io.h +++ b/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 diff --git a/core/math/color.h b/core/math/color.h index b90a0f33a2..91e0bf5532 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -169,14 +169,14 @@ struct _NO_DISCARD_ Color { return res; } - _FORCE_INLINE_ Color to_linear() const { + _FORCE_INLINE_ Color srgb_to_linear() const { return Color( r < 0.04045f ? r * (1.0 / 12.92) : Math::pow((r + 0.055f) * (float)(1.0 / (1 + 0.055)), 2.4f), g < 0.04045f ? g * (1.0 / 12.92) : Math::pow((g + 0.055f) * (float)(1.0 / (1 + 0.055)), 2.4f), b < 0.04045f ? b * (1.0 / 12.92) : Math::pow((b + 0.055f) * (float)(1.0 / (1 + 0.055)), 2.4f), a); } - _FORCE_INLINE_ Color to_srgb() const { + _FORCE_INLINE_ Color linear_to_srgb() const { return Color( r < 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * Math::pow(r, 1.0f / 2.4f) - 0.055f, g < 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * Math::pow(g, 1.0f / 2.4f) - 0.055f, diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index debc5cd00d..e146c4a4e3 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -231,14 +231,14 @@ Vector3 TriangleMesh::get_area_normal(const AABB &p_aabb) const { } case VISIT_LEFT_BIT: { stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.left | TEST_AABB_BIT; level++; + stack[level] = b.left | TEST_AABB_BIT; continue; } case VISIT_RIGHT_BIT: { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.right | TEST_AABB_BIT; level++; + stack[level] = b.right | TEST_AABB_BIT; continue; } case VISIT_DONE_BIT: { @@ -331,14 +331,14 @@ bool TriangleMesh::intersect_segment(const Vector3 &p_begin, const Vector3 &p_en } case VISIT_LEFT_BIT: { stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.left | TEST_AABB_BIT; level++; + stack[level] = b.left | TEST_AABB_BIT; continue; } case VISIT_RIGHT_BIT: { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.right | TEST_AABB_BIT; level++; + stack[level] = b.right | TEST_AABB_BIT; continue; } case VISIT_DONE_BIT: { @@ -431,14 +431,14 @@ bool TriangleMesh::intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, V } case VISIT_LEFT_BIT: { stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.left | TEST_AABB_BIT; level++; + stack[level] = b.left | TEST_AABB_BIT; continue; } case VISIT_RIGHT_BIT: { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.right | TEST_AABB_BIT; level++; + stack[level] = b.right | TEST_AABB_BIT; continue; } case VISIT_DONE_BIT: { @@ -551,14 +551,14 @@ bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_cou } case VISIT_LEFT_BIT: { stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.left | TEST_AABB_BIT; level++; + stack[level] = b.left | TEST_AABB_BIT; continue; } case VISIT_RIGHT_BIT: { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.right | TEST_AABB_BIT; level++; + stack[level] = b.right | TEST_AABB_BIT; continue; } case VISIT_DONE_BIT: { @@ -644,14 +644,14 @@ bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count, } case VISIT_LEFT_BIT: { stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.left | TEST_AABB_BIT; level++; + stack[level] = b.left | TEST_AABB_BIT; continue; } case VISIT_RIGHT_BIT: { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.right | TEST_AABB_BIT; level++; + stack[level] = b.right | TEST_AABB_BIT; continue; } case VISIT_DONE_BIT: { diff --git a/core/object/object.cpp b/core/object/object.cpp index c2cd42ff91..897b5d18de 100644 --- a/core/object/object.cpp +++ b/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) { diff --git a/core/object/object.h b/core/object/object.h index eeef03dcb9..c3e3c68b59 100644 --- a/core/object/object.h +++ b/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> diff --git a/core/os/os.cpp b/core/os/os.cpp index 2e5db145a4..846aeb16c5 100644 --- a/core/os/os.cpp +++ b/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.unref(); 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.unref(); } 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; } diff --git a/core/os/time.cpp b/core/os/time.cpp index e339805475..6582daac7c 100644 --- a/core/os/time.cpp +++ b/core/os/time.cpp @@ -95,16 +95,16 @@ VARIANT_ENUM_CAST(Time::Weekday); day = day_number_copy + 1; \ } -#define VALIDATE_YMDHMS \ - ERR_FAIL_COND_V_MSG(month == 0, 0, "Invalid month value of: " + itos(month) + ", months are 1-indexed and cannot be 0. See the Time.Month enum for valid values."); \ - ERR_FAIL_COND_V_MSG(month > 12, 0, "Invalid month value of: " + itos(month) + ". See the Time.Month enum for valid values."); \ - ERR_FAIL_COND_V_MSG(hour > 23, 0, "Invalid hour value of: " + itos(hour) + "."); \ - ERR_FAIL_COND_V_MSG(minute > 59, 0, "Invalid minute value of: " + itos(minute) + "."); \ - ERR_FAIL_COND_V_MSG(second > 59, 0, "Invalid second value of: " + itos(second) + " (leap seconds are not supported)."); \ - /* Do this check after month is tested as valid. */ \ - ERR_FAIL_COND_V_MSG(day == 0, 0, "Invalid day value of: " + itos(month) + ", days are 1-indexed and cannot be 0."); \ - uint8_t days_in_this_month = MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][month - 1]; \ - ERR_FAIL_COND_V_MSG(day > days_in_this_month, 0, "Invalid day value of: " + itos(day) + " which is larger than the maximum for this month, " + itos(days_in_this_month) + "."); +#define VALIDATE_YMDHMS(ret) \ + ERR_FAIL_COND_V_MSG(month == 0, ret, "Invalid month value of: " + itos(month) + ", months are 1-indexed and cannot be 0. See the Time.Month enum for valid values."); \ + ERR_FAIL_COND_V_MSG(month > 12, ret, "Invalid month value of: " + itos(month) + ". See the Time.Month enum for valid values."); \ + ERR_FAIL_COND_V_MSG(hour > 23, ret, "Invalid hour value of: " + itos(hour) + "."); \ + ERR_FAIL_COND_V_MSG(minute > 59, ret, "Invalid minute value of: " + itos(minute) + "."); \ + ERR_FAIL_COND_V_MSG(second > 59, ret, "Invalid second value of: " + itos(second) + " (leap seconds are not supported)."); \ + /* Do this check after month is tested as valid. */ \ + ERR_FAIL_COND_V_MSG(day == 0, ret, "Invalid day value of: " + itos(month) + ", days are 1-indexed and cannot be 0."); \ + uint8_t days_in_this_month = MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][month - 1]; \ + ERR_FAIL_COND_V_MSG(day > days_in_this_month, ret, "Invalid day value of: " + itos(day) + " which is larger than the maximum for this month, " + itos(days_in_this_month) + "."); #define YMD_TO_DAY_NUMBER \ /* The day number since Unix epoch (0-index). Days before 1970 are negative. */ \ @@ -273,6 +273,7 @@ Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday String Time::get_datetime_string_from_dict(const Dictionary p_datetime, bool p_use_space) const { ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), "", "Invalid datetime Dictionary: Dictionary is empty."); EXTRACT_FROM_DICTIONARY + VALIDATE_YMDHMS("") // vformat only supports up to 6 arguments, so we need to split this up into 2 parts. String timestamp = vformat("%04d-%02d-%02d", year, (uint8_t)month, day); if (p_use_space) { @@ -286,14 +287,14 @@ String Time::get_datetime_string_from_dict(const Dictionary p_datetime, bool p_u int64_t Time::get_unix_time_from_datetime_dict(const Dictionary p_datetime) const { ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), 0, "Invalid datetime Dictionary: Dictionary is empty"); EXTRACT_FROM_DICTIONARY - VALIDATE_YMDHMS + VALIDATE_YMDHMS(0) YMD_TO_DAY_NUMBER return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second; } int64_t Time::get_unix_time_from_datetime_string(String p_datetime) const { PARSE_ISO8601_STRING - VALIDATE_YMDHMS + VALIDATE_YMDHMS(0) YMD_TO_DAY_NUMBER return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second; } diff --git a/core/string/print_string.h b/core/string/print_string.h index f19573ad45..f7d0f25030 100644 --- a/core/string/print_string.h +++ b/core/string/print_string.h @@ -61,6 +61,14 @@ extern bool _print_error_enabled; extern void __print_line(String p_string); extern void print_error(String p_string); extern void print_verbose(String p_string); -#define print_line(...) __print_line(stringify_variants(__VA_ARGS__)) + +inline void print_line(Variant v) { + __print_line(stringify_variants(v)); +} + +template <typename... Args> +void print_line(Variant p_var, Args... p_args) { + __print_line(stringify_variants(p_var, p_args...)); +} #endif // PRINT_STRING_H diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index 1c991ee12d..3f94e064ec 100644 --- a/core/string/translation_po.cpp +++ b/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 diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h index 326616b607..f1ac32928f 100644 --- a/core/templates/cowdata.h +++ b/core/templates/cowdata.h @@ -86,13 +86,6 @@ private: return reinterpret_cast<uint32_t *>(_ptr) - 1; } - _FORCE_INLINE_ T *_get_data() const { - if (!_ptr) { - return nullptr; - } - return reinterpret_cast<T *>(_ptr); - } - _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const { return next_power_of_2(p_elements * sizeof(T)); } @@ -128,11 +121,11 @@ public: _FORCE_INLINE_ T *ptrw() { _copy_on_write(); - return (T *)_get_data(); + return _ptr; } _FORCE_INLINE_ const T *ptr() const { - return _get_data(); + return _ptr; } _FORCE_INLINE_ int size() const { @@ -150,19 +143,19 @@ public: _FORCE_INLINE_ void set(int p_index, const T &p_elem) { ERR_FAIL_INDEX(p_index, size()); _copy_on_write(); - _get_data()[p_index] = p_elem; + _ptr[p_index] = p_elem; } _FORCE_INLINE_ T &get_m(int p_index) { CRASH_BAD_INDEX(p_index, size()); _copy_on_write(); - return _get_data()[p_index]; + return _ptr[p_index]; } _FORCE_INLINE_ const T &get(int p_index) const { CRASH_BAD_INDEX(p_index, size()); - return _get_data()[p_index]; + return _ptr[p_index]; } Error resize(int p_size); @@ -249,7 +242,7 @@ uint32_t CowData<T>::_copy_on_write() { } else { for (uint32_t i = 0; i < current_size; i++) { - memnew_placement(&_data[i], T(_get_data()[i])); + memnew_placement(&_data[i], T(_ptr[i])); } } @@ -308,10 +301,8 @@ Error CowData<T>::resize(int p_size) { // construct the newly created elements if (!__has_trivial_constructor(T)) { - T *elems = _get_data(); - for (int i = *_get_size(); i < p_size; i++) { - memnew_placement(&elems[i], T); + memnew_placement(&_ptr[i], T); } } @@ -321,7 +312,7 @@ Error CowData<T>::resize(int p_size) { if (!__has_trivial_destructor(T)) { // deinitialize no longer needed elements for (uint32_t i = p_size; i < *_get_size(); i++) { - T *t = &_get_data()[i]; + T *t = &_ptr[i]; t->~T(); } } diff --git a/core/templates/safe_list.h b/core/templates/safe_list.h index ae31525dd0..e850f3bd5e 100644 --- a/core/templates/safe_list.h +++ b/core/templates/safe_list.h @@ -203,7 +203,7 @@ public: } // Calling this will cause zero to many deallocations. - void maybe_cleanup() { + bool maybe_cleanup() { SafeListNode *cursor = nullptr; SafeListNode *new_graveyard_head = nullptr; do { @@ -212,7 +212,7 @@ public: if (active_iterator_count.load() != 0) { // It's not safe to clean up with an active iterator, because that iterator // could be pointing to an element that we want to delete. - return; + return false; } // Any iterator created after this point will never point to a deleted node. // Swap it out with the current graveyard head. @@ -225,6 +225,17 @@ public: tmp->deletion_fn(tmp->val); memdelete_allocator<SafeListNode, A>(tmp); } + return true; + } + + ~SafeList() { +#ifdef DEBUG_ENABLED + if (!maybe_cleanup()) { + ERR_PRINT("There are still iterators around when destructing a SafeList. Memory will be leaked. This is a bug."); + } +#else + maybe_cleanup(); +#endif } }; @@ -353,11 +364,11 @@ public: } // Calling this will cause zero to many deallocations. - void maybe_cleanup() { + bool maybe_cleanup() { SafeListNode *cursor = graveyard_head; if (active_iterator_count != 0) { // It's not safe to clean up with an active iterator, because that iterator could be pointing to an element that we want to delete. - return; + return false; } graveyard_head = nullptr; // Our graveyard list is now unreachable by any active iterators, detached from the main graveyard head and ready for deletion. @@ -367,6 +378,17 @@ public: tmp->deletion_fn(tmp->val); memdelete_allocator<SafeListNode, A>(tmp); } + return true; + } + + ~SafeList() { +#ifdef DEBUG_ENABLED + if (!maybe_cleanup()) { + ERR_PRINT("There are still iterators around when destructing a SafeList. Memory will be leaked. This is a bug."); + } +#else + maybe_cleanup(); +#endif } }; diff --git a/core/variant/variant.h b/core/variant/variant.h index ca18249f36..475bf7158d 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -511,6 +511,7 @@ public: Variant recursive_duplicate(bool p_deep, int recursion_count) const; static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst); static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst); + static void sub(const Variant &a, const Variant &b, Variant &r_dst); /* Built-In Methods */ diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index c11925fa8c..f1daf1de13 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1656,8 +1656,8 @@ static void _register_variant_builtin_methods() { bind_method(Color, darkened, sarray("amount"), varray()); bind_method(Color, blend, sarray("over"), varray()); bind_method(Color, get_luminance, sarray(), varray()); - bind_method(Color, to_linear, sarray(), varray()); - bind_method(Color, to_srgb, sarray(), varray()); + bind_method(Color, srgb_to_linear, sarray(), varray()); + bind_method(Color, linear_to_srgb, sarray(), varray()); bind_method(Color, is_equal_approx, sarray("to"), varray()); diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h index b297babd6f..07d89d30cb 100644 --- a/core/variant/variant_parser.h +++ b/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; diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index e604ff9567..705aa27be6 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -1868,6 +1868,110 @@ Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const { } } +void Variant::sub(const Variant &a, const Variant &b, Variant &r_dst) { + if (a.type != b.type) { + return; + } + + switch (a.type) { + case NIL: { + r_dst = Variant(); + } + return; + case INT: { + int64_t va = a._data._int; + int64_t vb = b._data._int; + r_dst = int(va - vb); + } + return; + case FLOAT: { + double ra = a._data._float; + double rb = b._data._float; + r_dst = ra - rb; + } + return; + case VECTOR2: { + r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) - *reinterpret_cast<const Vector2 *>(b._data._mem); + } + return; + case VECTOR2I: { + int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x; + int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x; + int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y; + int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y; + r_dst = Vector2i(int32_t(vax - vbx), int32_t(vay - vby)); + } + return; + case RECT2: { + const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem); + const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem); + r_dst = Rect2(ra->position - rb->position, ra->size - rb->size); + } + return; + case RECT2I: { + const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem); + const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem); + + int32_t vax = ra->position.x; + int32_t vay = ra->position.y; + int32_t vbx = ra->size.x; + int32_t vby = ra->size.y; + int32_t vcx = rb->position.x; + int32_t vcy = rb->position.y; + int32_t vdx = rb->size.x; + int32_t vdy = rb->size.y; + + r_dst = Rect2i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vcx - vdx), int32_t(vcy - vdy)); + } + return; + case VECTOR3: { + r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) - *reinterpret_cast<const Vector3 *>(b._data._mem); + } + return; + case VECTOR3I: { + int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x; + int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x; + int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y; + int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y; + int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z; + int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z; + r_dst = Vector3i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vaz - vbz)); + } + return; + case AABB: { + const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem); + const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem); + r_dst = ::AABB(ra->position - rb->position, ra->size - rb->size); + } + return; + case QUATERNION: { + Quaternion empty_rot; + const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem); + const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem); + r_dst = (*qb).inverse() * *qa; + } + return; + case COLOR: { + const Color *ca = reinterpret_cast<const Color *>(a._data._mem); + const Color *cb = reinterpret_cast<const Color *>(b._data._mem); + float new_r = ca->r - cb->r; + float new_g = ca->g - cb->g; + float new_b = ca->b - cb->b; + float new_a = ca->a - cb->a; + new_r = new_r > 1.0 ? 1.0 : new_r; + new_g = new_g > 1.0 ? 1.0 : new_g; + new_b = new_b > 1.0 ? 1.0 : new_b; + new_a = new_a > 1.0 ? 1.0 : new_a; + r_dst = Color(new_r, new_g, new_b, new_a); + } + return; + default: { + r_dst = a; + } + return; + } +} + void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) { if (a.type != b.type) { if (a.is_num() && b.is_num()) { |