From cf029c6075b7ab2719b6eb6e0890b2eac954957c Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Thu, 25 Jan 2024 10:02:04 -0500 Subject: [PATCH 01/20] Add custom file-based resource paths --- core/config/project_settings.cpp | 9 ++++ core/io/dir_access.cpp | 7 +++ core/io/file_access.cpp | 78 +++++++++++++++++++++++++++++++- core/io/file_access.h | 8 ++++ doc/classes/FileAccess.xml | 30 ++++++++++++ 5 files changed, 131 insertions(+), 1 deletion(-) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index d9a5a5094aef..18809e262dfb 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -268,6 +268,15 @@ String ProjectSettings::globalize_path(const String &p_path) const { return p_path.replace("user://", ""); } + // Custom resource paths + Dictionary resource_paths = FileAccess::get_resource_paths(); + for (int i = 0; i < resource_paths.size(); i++) { + String key = resource_paths.get_key_at_index(i); + if (p_path.begins_with(key + "://")) { + return p_path.replace(key + ":/", resource_paths[key]); + } + } + return p_path; } diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp index 680a653dfc22..d26d1893919e 100644 --- a/core/io/dir_access.cpp +++ b/core/io/dir_access.cpp @@ -213,6 +213,13 @@ String DirAccess::fix_path(const String &p_path) const { } break; case ACCESS_FILESYSTEM: { + Dictionary resource_paths = FileAccess::get_resource_paths(); + for (int i = 0; i < resource_paths.size(); i++) { + String key = resource_paths.get_key_at_index(i); + if (p_path.begins_with(key + "://")) { + return p_path.replace(key + ":/", resource_paths[key]); + } + } return p_path; } break; case ACCESS_MAX: diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index 55286277fa41..cf1cf8889bd4 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -42,6 +42,8 @@ FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = {}; FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr; +HashMap FileAccess::resource_paths = HashMap(); + bool FileAccess::backup_save = false; thread_local Error FileAccess::last_file_open_error = OK; @@ -75,7 +77,6 @@ Ref FileAccess::create_for_path(const String &p_path) { ret = create(ACCESS_RESOURCES); } else if (p_path.begins_with("user://")) { ret = create(ACCESS_USERDATA); - } else { ret = create(ACCESS_FILESYSTEM); } @@ -210,6 +211,11 @@ String FileAccess::fix_path(const String &p_path) const { } break; case ACCESS_FILESYSTEM: { + for (KeyValue kv : resource_paths) { + if (r_path.begins_with(kv.key + "://")) { + return r_path.replace(kv.key + ":/", kv.value); + } + } return r_path; } break; case ACCESS_MAX: @@ -852,6 +858,70 @@ String FileAccess::get_sha256(const String &p_file) { return String::hex_encode_buffer(hash, 32); } +void FileAccess::add_resource_path(const String &p_protocol, const String &p_path) { + ERR_FAIL_COND_MSG(p_protocol.length() == 0, "Protocol parameter is empty."); + + String protocol = p_protocol; + if (protocol.ends_with("://")) { + protocol = protocol.left(protocol.length() - 3); + } + + ERR_FAIL_COND_MSG(protocol == "res" || protocol == "user", vformat("Protocol \"%s://\" is built-in.", protocol)); + ERR_FAIL_COND_MSG(resource_paths.has(p_protocol), vformat("Protocol \"%s://\" is already registered.", protocol)); + + resource_paths[protocol] = p_path; +} + +void FileAccess::remove_resource_path(const String &p_protocol) { + ERR_FAIL_COND_MSG(p_protocol.length() == 0, "Protocol parameter is empty."); + + String protocol = p_protocol; + if (protocol.ends_with("://")) { + protocol = protocol.left(protocol.length() - 3); + } + + ERR_FAIL_COND_MSG(protocol == "res" || protocol == "user", vformat("Protocol \"%s://\" is built-in.", protocol)); + ERR_FAIL_COND_MSG(!resource_paths.has(p_protocol), vformat("Protocol \"%s://\" is not registered.", protocol)); + + resource_paths.erase(protocol); +} + +bool FileAccess::is_resource_path(const String &p_protocol) { + ERR_FAIL_COND_V_MSG(p_protocol.length() == 0, false, "Protocol parameter is empty."); + + String protocol = p_protocol; + if (protocol.ends_with("://")) { + protocol = protocol.left(protocol.length() - 3); + } + + ERR_FAIL_COND_V_MSG(protocol == "res" || protocol == "user", false, vformat("Protocol \"%s://\" is built-in.", protocol)); + + return resource_paths.has(protocol); +} + +String FileAccess::get_resource_path(const String &p_protocol) { + if (!is_resource_path(p_protocol)) { + return ""; + } + + String protocol = p_protocol; + if (protocol.ends_with("://")) { + protocol = protocol.left(protocol.length() - 3); + } + + return resource_paths[protocol]; +} + +Dictionary FileAccess::get_resource_paths() { + Dictionary output; + + for (KeyValue kv : resource_paths) { + output[kv.key] = kv.value; + } + + return output; +} + void FileAccess::_bind_methods() { ClassDB::bind_static_method("FileAccess", D_METHOD("open", "path", "flags"), &FileAccess::_open); ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::open_encrypted); @@ -918,6 +988,12 @@ void FileAccess::_bind_methods() { ClassDB::bind_static_method("FileAccess", D_METHOD("set_read_only_attribute", "file", "ro"), &FileAccess::set_read_only_attribute); ClassDB::bind_static_method("FileAccess", D_METHOD("get_read_only_attribute", "file"), &FileAccess::get_read_only_attribute); + ClassDB::bind_static_method("FileAccess", D_METHOD("add_resource_path", "protocol", "path"), &FileAccess::add_resource_path); + ClassDB::bind_static_method("FileAccess", D_METHOD("remove_resource_path", "protocol"), &FileAccess::remove_resource_path); + ClassDB::bind_static_method("FileAccess", D_METHOD("is_resource_path", "protocol"), &FileAccess::is_resource_path); + ClassDB::bind_static_method("FileAccess", D_METHOD("get_resource_path", "protocol"), &FileAccess::get_resource_path); + ClassDB::bind_static_method("FileAccess", D_METHOD("get_resource_paths"), &FileAccess::get_resource_paths); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian"); BIND_ENUM_CONSTANT(READ); diff --git a/core/io/file_access.h b/core/io/file_access.h index 7d346ca2f4f8..bc479b1cb97c 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -121,6 +121,8 @@ class FileAccess : public RefCounted { static Ref _open(const String &p_path, ModeFlags p_mode_flags); + static HashMap resource_paths; + public: static void set_file_close_fail_notify_callback(FileCloseFailNotify p_cbk) { close_fail_notify = p_cbk; } @@ -226,6 +228,12 @@ class FileAccess : public RefCounted { static PackedByteArray _get_file_as_bytes(const String &p_path) { return get_file_as_bytes(p_path, &last_file_open_error); } static String _get_file_as_string(const String &p_path) { return get_file_as_string(p_path, &last_file_open_error); } + static void add_resource_path(const String &p_protocol, const String &p_path); + static void remove_resource_path(const String &p_protocol); + static bool is_resource_path(const String &p_protocol); + static String get_resource_path(const String &p_protocol); + static Dictionary get_resource_paths(); + template static void make_default(AccessType p_access) { create_func[p_access] = _create_builtin; diff --git a/doc/classes/FileAccess.xml b/doc/classes/FileAccess.xml index df8ebc12fa8c..e9b048481a14 100644 --- a/doc/classes/FileAccess.xml +++ b/doc/classes/FileAccess.xml @@ -43,6 +43,13 @@ https://godotengine.org/asset-library/asset/676 + + + + + + + @@ -253,6 +260,17 @@ Returns the next bits from the file as a floating-point number. + + + + + + + + + + + @@ -283,6 +301,12 @@ Returns [code]true[/code] if the file is currently opened. + + + + + + @@ -324,6 +348,12 @@ Returns [code]null[/code] if opening the file failed. You can use [method get_open_error] to check the error that occurred. + + + + + + From 0edb3d8a5e726ca3c5e0d9a803aa5f08c7bc2aa1 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Thu, 25 Jan 2024 17:46:58 -0500 Subject: [PATCH 02/20] Add beginning of `FileAccessExtension` --- core/io/file_access_extension.cpp | 199 ++++++++++++++++++++++++++++++ core/io/file_access_extension.h | 101 +++++++++++++++ core/register_core_types.cpp | 3 + 3 files changed, 303 insertions(+) create mode 100644 core/io/file_access_extension.cpp create mode 100644 core/io/file_access_extension.h diff --git a/core/io/file_access_extension.cpp b/core/io/file_access_extension.cpp new file mode 100644 index 000000000000..167ae40fc63b --- /dev/null +++ b/core/io/file_access_extension.cpp @@ -0,0 +1,199 @@ +/**************************************************************************/ +/* file_access_extension.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "file_access_extension.h" + +#include "core/object/object.h" + +bool FileAccessExtension::is_open() const { + bool is_open = false; + GDVIRTUAL_CALL(_is_open, is_open); + return is_open; +} + +String FileAccessExtension::get_path() const { + String path = ""; + GDVIRTUAL_CALL(_get_path, path); + return path; +} + +String FileAccessExtension::get_path_absolute() const { + String path_absolute = ""; + GDVIRTUAL_CALL(_get_path_absolute, path_absolute); + return path_absolute; +} + +void FileAccessExtension::seek(uint64_t p_position) { + GDVIRTUAL_CALL(_seek, p_position); +} + +void FileAccessExtension::seek_end(int64_t p_position) { + GDVIRTUAL_CALL(_seek_end, p_position); +} + +uint64_t FileAccessExtension::get_position() const { + uint64_t position = 0; + GDVIRTUAL_CALL(_get_position, position); + return position; +} + +uint64_t FileAccessExtension::get_length() const { + uint64_t length = 0; + GDVIRTUAL_CALL(_get_length, length); + return length; +} + +bool FileAccessExtension::eof_reached() const { + bool eof_reached = false; + GDVIRTUAL_CALL(_eof_reached, eof_reached); + return eof_reached; +} + +uint8_t FileAccessExtension::get_8() const { + uint8_t val = 0; + GDVIRTUAL_CALL(_get_8, val); + return val; +} + +uint16_t FileAccessExtension::get_16() const { + uint16_t val = 0; + GDVIRTUAL_CALL(_get_16, val); + return val; +} + +uint32_t FileAccessExtension::get_32() const { + uint32_t val = 0; + GDVIRTUAL_CALL(_get_32, val); + return val; +} + +uint64_t FileAccessExtension::get_64() const { + uint64_t val = 0; + GDVIRTUAL_CALL(_get_64, val); + return val; +} + +float FileAccessExtension::get_float() const { + float val = 0; + GDVIRTUAL_CALL(_get_float, val); + return val; +} + +double FileAccessExtension::get_double() const { + double val = 0; + GDVIRTUAL_CALL(_get_double, val); + return val; +} + +real_t FileAccessExtension::get_real() const { + real_t val = 0; + GDVIRTUAL_CALL(_get_real, val); + return val; +} + +Variant FileAccessExtension::get_var(bool p_allow_objects) const { + Variant var; + GDVIRTUAL_CALL(_get_var, p_allow_objects, var); + return var; +} + +Vector FileAccessExtension::get_buffer(int64_t p_length) const { + Vector buffer; + GDVIRTUAL_CALL(_get_buffer, p_length, buffer); + return buffer; +} + +String FileAccessExtension::get_line() const { + String line; + GDVIRTUAL_CALL(_get_line, line); + return line; +} + +String FileAccessExtension::get_token() const { + String token; + GDVIRTUAL_CALL(_get_token, token); + return token; +} + +Vector FileAccessExtension::get_csv_line(const String &p_delim) const { + Vector csv_line; + GDVIRTUAL_CALL(_get_csv_line, p_delim, csv_line); + return csv_line; +} + +String FileAccessExtension::get_as_text(bool p_skip_cr) const { + String val_as_text; + GDVIRTUAL_CALL(_get_as_text, p_skip_cr, val_as_text); + return val_as_text; +} + +String FileAccessExtension::get_as_utf8_string(bool p_skip_cr) const { + String val_as_utf8_string; + GDVIRTUAL_CALL(_get_as_utf8_string, p_skip_cr, val_as_utf8_string); + return val_as_utf8_string; +} + +void FileAccessExtension::_bind_methods() { + GDVIRTUAL_BIND(_is_open); + + GDVIRTUAL_BIND(_get_path); + GDVIRTUAL_BIND(_get_path_absolute); + + GDVIRTUAL_BIND(_seek, "position"); + GDVIRTUAL_BIND(_seek_end, "position"); + GDVIRTUAL_BIND(_get_position); + GDVIRTUAL_BIND(_get_length); + + GDVIRTUAL_BIND(_eof_reached); + + GDVIRTUAL_BIND(_get_8); + GDVIRTUAL_BIND(_get_16); + GDVIRTUAL_BIND(_get_32); + GDVIRTUAL_BIND(_get_64); + + GDVIRTUAL_BIND(_get_float); + GDVIRTUAL_BIND(_get_double); + GDVIRTUAL_BIND(_get_real); + + GDVIRTUAL_BIND(_get_var, "allow_objects"); + + GDVIRTUAL_BIND(_get_buffer, "length"); + GDVIRTUAL_BIND(_get_line); + GDVIRTUAL_BIND(_get_token); + GDVIRTUAL_BIND(_get_csv_line, "delim"); + GDVIRTUAL_BIND(_get_as_text, "skip_cr"); + GDVIRTUAL_BIND(_get_as_utf8_string, "skip_cr"); +} + +FileAccessExtension::FileAccessExtension() { +} + +FileAccessExtension::~FileAccessExtension() { +} diff --git a/core/io/file_access_extension.h b/core/io/file_access_extension.h new file mode 100644 index 000000000000..ba06093256d9 --- /dev/null +++ b/core/io/file_access_extension.h @@ -0,0 +1,101 @@ +/**************************************************************************/ +/* file_access_extension.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef FILE_ACCESS_EXTENSION_H +#define FILE_ACCESS_EXTENSION_H + +#include "core/io/file_access.h" +#include "core/object/gdvirtual.gen.inc" +#include "core/object/object.h" + +class FileAccessExtension : public FileAccess { + GDCLASS(FileAccessExtension, FileAccess); + +protected: + static void _bind_methods(); + +public: + GDVIRTUAL0RC(bool, _is_open); + virtual bool is_open() const override; + + GDVIRTUAL0RC(String, _get_path); + virtual String get_path() const override; + GDVIRTUAL0RC(String, _get_path_absolute); + virtual String get_path_absolute() const override; + + GDVIRTUAL1(_seek, uint64_t); + virtual void seek(uint64_t p_position) override; + GDVIRTUAL1(_seek_end, int64_t); + virtual void seek_end(int64_t p_position) override; + GDVIRTUAL0RC(uint64_t, _get_position); + virtual uint64_t get_position() const override; + GDVIRTUAL0RC(uint64_t, _get_length); + virtual uint64_t get_length() const override; + + GDVIRTUAL0RC(bool, _eof_reached); + virtual bool eof_reached() const override; + + GDVIRTUAL0RC(uint8_t, _get_8); + virtual uint8_t get_8() const override; + GDVIRTUAL0RC(uint16_t, _get_16); + virtual uint16_t get_16() const override; + GDVIRTUAL0RC(uint32_t, _get_32); + virtual uint32_t get_32() const override; + GDVIRTUAL0RC(uint64_t, _get_64); + virtual uint64_t get_64() const override; + + GDVIRTUAL0RC(float, _get_float); + virtual float get_float() const override; + GDVIRTUAL0RC(double, _get_double); + virtual double get_double() const override; + GDVIRTUAL0RC(real_t, _get_real); + virtual real_t get_real() const override; + + GDVIRTUAL1RC(Variant, _get_var, bool); + Variant get_var(bool p_allow_objects = false) const; + + GDVIRTUAL1RC(Vector, _get_buffer, int64_t); + Vector get_buffer(int64_t p_length) const; + GDVIRTUAL0RC(String, _get_line); + virtual String get_line() const override; + GDVIRTUAL0RC(String, _get_token); + virtual String get_token() const override; + GDVIRTUAL1RC(Vector, _get_csv_line, String); + virtual Vector get_csv_line(const String &p_delim = ",") const override; + GDVIRTUAL1RC(String, _get_as_text, bool); + String get_as_text(bool p_skip_cr = false) const; + GDVIRTUAL1RC(String, _get_as_utf8_string, bool); + virtual String get_as_utf8_string(bool p_skip_cr = false) const override; + + FileAccessExtension(); + ~FileAccessExtension(); +}; + +#endif // FILE_ACCESS_EXTENSION_H diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 4c1ed8a69a83..9c183de85238 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -46,6 +46,8 @@ #include "core/io/config_file.h" #include "core/io/dir_access.h" #include "core/io/dtls_server.h" +#include "core/io/file_access.h" +#include "core/io/file_access_extension.h" #include "core/io/http_client.h" #include "core/io/image_loader.h" #include "core/io/json.h" @@ -242,6 +244,7 @@ void register_core_types() { GDREGISTER_ABSTRACT_CLASS(FileAccess); GDREGISTER_ABSTRACT_CLASS(DirAccess); + GDREGISTER_ABSTRACT_CLASS(FileAccessExtension); GDREGISTER_CLASS(core_bind::Thread); GDREGISTER_CLASS(core_bind::Mutex); GDREGISTER_CLASS(core_bind::Semaphore); From 9f4b3fed843259abac69f35c74f36b404b931247 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Thu, 25 Jan 2024 19:52:30 -0500 Subject: [PATCH 03/20] Fix `FileAccessExtension::get_buffer(uint8_t*, uint64_t)` --- core/io/file_access_extension.cpp | 8 ++++++++ core/io/file_access_extension.h | 1 + 2 files changed, 9 insertions(+) diff --git a/core/io/file_access_extension.cpp b/core/io/file_access_extension.cpp index 167ae40fc63b..42c0a17e0f4d 100644 --- a/core/io/file_access_extension.cpp +++ b/core/io/file_access_extension.cpp @@ -124,6 +124,14 @@ Variant FileAccessExtension::get_var(bool p_allow_objects) const { return var; } +uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const { + ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); + + Vector buffer = get_buffer(p_length); + p_dst = buffer.ptrw(); + return buffer.size(); +} + Vector FileAccessExtension::get_buffer(int64_t p_length) const { Vector buffer; GDVIRTUAL_CALL(_get_buffer, p_length, buffer); diff --git a/core/io/file_access_extension.h b/core/io/file_access_extension.h index ba06093256d9..5d061875c25e 100644 --- a/core/io/file_access_extension.h +++ b/core/io/file_access_extension.h @@ -81,6 +81,7 @@ class FileAccessExtension : public FileAccess { GDVIRTUAL1RC(Variant, _get_var, bool); Variant get_var(bool p_allow_objects = false) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; GDVIRTUAL1RC(Vector, _get_buffer, int64_t); Vector get_buffer(int64_t p_length) const; GDVIRTUAL0RC(String, _get_line); From d6f14e77c7bbb0ead3fdff574bc9f0075e4b240e Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Thu, 25 Jan 2024 21:14:32 -0500 Subject: [PATCH 04/20] Add missing definitions for `FileAccessExtension` --- core/io/file_access_extension.cpp | 154 +++++++++++++++- core/io/file_access_extension.h | 57 ++++++ doc/classes/FileAccessExtension.xml | 260 ++++++++++++++++++++++++++++ 3 files changed, 468 insertions(+), 3 deletions(-) create mode 100644 doc/classes/FileAccessExtension.xml diff --git a/core/io/file_access_extension.cpp b/core/io/file_access_extension.cpp index 42c0a17e0f4d..a119f0725e04 100644 --- a/core/io/file_access_extension.cpp +++ b/core/io/file_access_extension.cpp @@ -32,6 +32,18 @@ #include "core/object/object.h" +Error FileAccessExtension::open_internal(const String &p_path, int p_mode_flags) { + Error err = OK; + GDVIRTUAL_CALL(_open_internal, p_path, p_mode_flags, err); + return err; +} + +uint64_t FileAccessExtension::_get_modified_time(const String &p_file) { + uint64_t time = 0; + GDVIRTUAL_CALL(__get_modified_time, p_file, time); + return time; +} + bool FileAccessExtension::is_open() const { bool is_open = false; GDVIRTUAL_CALL(_is_open, is_open); @@ -124,12 +136,17 @@ Variant FileAccessExtension::get_var(bool p_allow_objects) const { return var; } -uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const { +uint64_t FileAccessExtension::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); Vector buffer = get_buffer(p_length); - p_dst = buffer.ptrw(); - return buffer.size(); + + int64_t i = 0; + for (i = 0; i < buffer.size(); i++) { + p_dst[i] = buffer.get(i); + } + + return i; } Vector FileAccessExtension::get_buffer(int64_t p_length) const { @@ -168,7 +185,107 @@ String FileAccessExtension::get_as_utf8_string(bool p_skip_cr) const { return val_as_utf8_string; } +void FileAccessExtension::set_big_endian(bool p_big_endian) { + GDVIRTUAL_CALL(_set_big_endian, p_big_endian); +} + +Error FileAccessExtension::get_error() const { + Error err = OK; + GDVIRTUAL_CALL(_get_error, err); + return err; +} + +void FileAccessExtension::flush() { + GDVIRTUAL_CALL(_flush); +} + +void FileAccessExtension::store_8(uint8_t p_dest) { + GDVIRTUAL_CALL(_store_8, p_dest); +} + +void FileAccessExtension::store_16(uint16_t p_dest) { + GDVIRTUAL_CALL(_store_16, p_dest); +} + +void FileAccessExtension::store_32(uint32_t p_dest) { + GDVIRTUAL_CALL(_store_32, p_dest); +} + +void FileAccessExtension::store_64(uint64_t p_dest) { + GDVIRTUAL_CALL(_store_64, p_dest); +} + +void FileAccessExtension::store_float(float p_dest) { + GDVIRTUAL_CALL(_store_float, p_dest); +} + +void FileAccessExtension::store_double(double p_dest) { + GDVIRTUAL_CALL(_store_double, p_dest); +} + +void FileAccessExtension::store_real(real_t p_dest) { + GDVIRTUAL_CALL(_store_real, p_dest); +} + +void FileAccessExtension::store_string(const String &p_string) { + GDVIRTUAL_CALL(_store_string, p_string); +} + +void FileAccessExtension::store_line(const String &p_line) { + GDVIRTUAL_CALL(_store_line, p_line); +} + +void FileAccessExtension::store_csv_line(const Vector &p_values, const String &p_delim) { + GDVIRTUAL_CALL(_store_csv_line, p_values, p_delim); +} + +void FileAccessExtension::store_pascal_string(const String &p_string) { + GDVIRTUAL_CALL(_store_pascal_string, p_string); +} + +String FileAccessExtension::get_pascal_string() { + String string; + GDVIRTUAL_CALL(_get_pascal_string, string); + return string; +} + +void FileAccessExtension::store_buffer(const uint8_t *p_src, uint64_t p_length) { + Vector buffer; + uint64_t i = 0; + for (i = 0; i < p_length; i++) { + buffer.insert(i, p_src[i]); + } + store_buffer(buffer); +} + +void FileAccessExtension::store_buffer(const Vector &p_buffer) { + GDVIRTUAL_CALL(_store_buffer, p_buffer); +} + +void FileAccessExtension::store_var(const Variant &p_var, bool p_full_objects) { + GDVIRTUAL_CALL(_store_var, p_var, p_full_objects); +} + +void FileAccessExtension::close() { + GDVIRTUAL_CALL(_close); +} + +bool FileAccessExtension::file_exists(const String &p_name) { + bool file_exists; + GDVIRTUAL_CALL(_file_exists, p_name, file_exists); + return file_exists; +} + +Error FileAccessExtension::reopen(const String &p_path, int p_mode_flags) { + Error err = OK; + GDVIRTUAL_CALL(_reopen, p_path, p_mode_flags, err); + return err; +} + void FileAccessExtension::_bind_methods() { + GDVIRTUAL_BIND(_open_internal, "path", "mode_flags"); + GDVIRTUAL_BIND(__get_modified_time, "file"); + GDVIRTUAL_BIND(_is_open); GDVIRTUAL_BIND(_get_path); @@ -198,6 +315,37 @@ void FileAccessExtension::_bind_methods() { GDVIRTUAL_BIND(_get_csv_line, "delim"); GDVIRTUAL_BIND(_get_as_text, "skip_cr"); GDVIRTUAL_BIND(_get_as_utf8_string, "skip_cr"); + + GDVIRTUAL_BIND(_set_big_endian, "big_endian"); + + GDVIRTUAL_BIND(_get_error); + + GDVIRTUAL_BIND(_flush); + GDVIRTUAL_BIND(_store_8, "dest"); + GDVIRTUAL_BIND(_store_16, "dest"); + GDVIRTUAL_BIND(_store_32, "dest"); + GDVIRTUAL_BIND(_store_64, "dest"); + + GDVIRTUAL_BIND(_store_float, "dest"); + GDVIRTUAL_BIND(_store_double, "dest"); + GDVIRTUAL_BIND(_store_real, "dest"); + + GDVIRTUAL_BIND(_store_string, "string"); + GDVIRTUAL_BIND(_store_line, "line"); + GDVIRTUAL_BIND(_store_csv_line, "values", "delim"); + + GDVIRTUAL_BIND(_store_pascal_string, "string"); + GDVIRTUAL_BIND(_get_pascal_string); + + GDVIRTUAL_BIND(_store_buffer, "buffer"); + + GDVIRTUAL_BIND(_store_var, "var", "full_objects"); + + GDVIRTUAL_BIND(_close); + + GDVIRTUAL_BIND(_file_exists, "name"); + + GDVIRTUAL_BIND(_reopen, "path", "mode_flags"); } FileAccessExtension::FileAccessExtension() { diff --git a/core/io/file_access_extension.h b/core/io/file_access_extension.h index 5d061875c25e..94df6d1e1538 100644 --- a/core/io/file_access_extension.h +++ b/core/io/file_access_extension.h @@ -41,6 +41,11 @@ class FileAccessExtension : public FileAccess { protected: static void _bind_methods(); + GDVIRTUAL2R(Error, _open_internal, String, int); + virtual Error open_internal(const String &p_path, int p_mode_flags) override; + GDVIRTUAL1R(uint64_t, __get_modified_time, String); + virtual uint64_t _get_modified_time(const String &p_file) override; + public: GDVIRTUAL0RC(bool, _is_open); virtual bool is_open() const override; @@ -95,6 +100,58 @@ class FileAccessExtension : public FileAccess { GDVIRTUAL1RC(String, _get_as_utf8_string, bool); virtual String get_as_utf8_string(bool p_skip_cr = false) const override; + GDVIRTUAL1(_set_big_endian, bool); + virtual void set_big_endian(bool p_big_endian) override; + + GDVIRTUAL0RC(Error, _get_error); + virtual Error get_error() const override; + + GDVIRTUAL0(_flush); + virtual void flush() override; + GDVIRTUAL1(_store_8, uint8_t); + virtual void store_8(uint8_t p_dest) override; + GDVIRTUAL1(_store_16, uint16_t); + virtual void store_16(uint16_t p_dest) override; + GDVIRTUAL1(_store_32, uint32_t); + virtual void store_32(uint32_t p_dest) override; + GDVIRTUAL1(_store_64, uint64_t); + virtual void store_64(uint64_t p_dest) override; + + GDVIRTUAL1(_store_float, float); + virtual void store_float(float p_dest) override; + GDVIRTUAL1(_store_double, double); + virtual void store_double(double p_dest) override; + GDVIRTUAL1(_store_real, real_t); + virtual void store_real(real_t p_real) override; + + GDVIRTUAL1(_store_string, String); + virtual void store_string(const String &p_string) override; + GDVIRTUAL1(_store_line, String); + virtual void store_line(const String &p_line) override; + GDVIRTUAL2(_store_csv_line, Vector, String); + virtual void store_csv_line(const Vector &p_values, const String &p_delim = ",") override; + + GDVIRTUAL1(_store_pascal_string, String); + virtual void store_pascal_string(const String &p_string) override; + GDVIRTUAL0RC(String, _get_pascal_string); + virtual String get_pascal_string() override; + + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; + GDVIRTUAL1(_store_buffer, Vector); + void store_buffer(const Vector &p_buffer); + + GDVIRTUAL2(_store_var, Variant, bool); + void store_var(const Variant &p_var, bool p_full_objects = false); + + GDVIRTUAL0(_close); + virtual void close() override; + + GDVIRTUAL1R(bool, _file_exists, String); + virtual bool file_exists(const String &p_name) override; + + GDVIRTUAL2R(Error, _reopen, String, int); + virtual Error reopen(const String &p_path, int p_mode_flags) override; + FileAccessExtension(); ~FileAccessExtension(); }; diff --git a/doc/classes/FileAccessExtension.xml b/doc/classes/FileAccessExtension.xml new file mode 100644 index 000000000000..cd5d710b72df --- /dev/null +++ b/doc/classes/FileAccessExtension.xml @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 0c7cc7ccf270f152432e81bf5e14da704bd6014c Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Fri, 26 Jan 2024 09:00:42 -0500 Subject: [PATCH 05/20] Add missing methods in `FileAccessExtension` --- core/io/file_access_extension.cpp | 236 ++++++++++++++++++++-------- core/io/file_access_extension.h | 19 ++- doc/classes/FileAccessExtension.xml | 45 +++++- modules/gdscript/gdscript.cpp | 9 ++ 4 files changed, 234 insertions(+), 75 deletions(-) diff --git a/core/io/file_access_extension.cpp b/core/io/file_access_extension.cpp index a119f0725e04..22a271369d7b 100644 --- a/core/io/file_access_extension.cpp +++ b/core/io/file_access_extension.cpp @@ -32,108 +32,168 @@ #include "core/object/object.h" +// Ref FileAccessExtension::create() { +// Ref file_access; +// file_access.instantiate(); +// return file_access; +// } + +BitField FileAccessExtension::_get_unix_permissions(const String &p_file) { + BitField permissions = 0; + GDVIRTUAL_REQUIRED_CALL(__get_unix_permissions, p_file, permissions); + return permissions; +} + +Error FileAccessExtension::_set_unix_permissions(const String &p_file, BitField p_permissions) { + Error err = OK; + GDVIRTUAL_REQUIRED_CALL(__set_unix_permissions, p_file, p_permissions, err); + return err; +} + +bool FileAccessExtension::_get_hidden_attribute(const String &p_file) { + bool hidden_attribute = false; + GDVIRTUAL_REQUIRED_CALL(__get_hidden_attribute, p_file, hidden_attribute); + return hidden_attribute; +} + +Error FileAccessExtension::_set_hidden_attribute(const String &p_file, bool p_hidden) { + Error err = OK; + GDVIRTUAL_REQUIRED_CALL(__set_hidden_attribute, p_file, p_hidden, err); + return err; +} + +bool FileAccessExtension::_get_read_only_attribute(const String &p_file) { + bool read_only_attribute = false; + GDVIRTUAL_REQUIRED_CALL(__get_read_only_attribute, p_file, read_only_attribute); + return read_only_attribute; +} + +Error FileAccessExtension::_set_read_only_attribute(const String &p_file, bool p_read_only) { + Error err = OK; + GDVIRTUAL_REQUIRED_CALL(__set_read_only_attribute, p_file, p_read_only, err); + return err; +} + Error FileAccessExtension::open_internal(const String &p_path, int p_mode_flags) { Error err = OK; - GDVIRTUAL_CALL(_open_internal, p_path, p_mode_flags, err); + GDVIRTUAL_REQUIRED_CALL(_open_internal, p_path, p_mode_flags, err); return err; } uint64_t FileAccessExtension::_get_modified_time(const String &p_file) { uint64_t time = 0; - GDVIRTUAL_CALL(__get_modified_time, p_file, time); + GDVIRTUAL_REQUIRED_CALL(__get_modified_time, p_file, time); return time; } bool FileAccessExtension::is_open() const { bool is_open = false; - GDVIRTUAL_CALL(_is_open, is_open); + GDVIRTUAL_REQUIRED_CALL(_is_open, is_open); return is_open; } String FileAccessExtension::get_path() const { String path = ""; - GDVIRTUAL_CALL(_get_path, path); - return path; + if (GDVIRTUAL_CALL(_get_path, path)) { + return path; + } + return FileAccess::get_path(); } String FileAccessExtension::get_path_absolute() const { String path_absolute = ""; - GDVIRTUAL_CALL(_get_path_absolute, path_absolute); - return path_absolute; + if (GDVIRTUAL_CALL(_get_path_absolute, path_absolute)) { + return path_absolute; + } + return FileAccess::get_path_absolute(); } void FileAccessExtension::seek(uint64_t p_position) { - GDVIRTUAL_CALL(_seek, p_position); + GDVIRTUAL_REQUIRED_CALL(_seek, p_position); } void FileAccessExtension::seek_end(int64_t p_position) { - GDVIRTUAL_CALL(_seek_end, p_position); + GDVIRTUAL_REQUIRED_CALL(_seek_end, p_position); } uint64_t FileAccessExtension::get_position() const { uint64_t position = 0; - GDVIRTUAL_CALL(_get_position, position); + GDVIRTUAL_REQUIRED_CALL(_get_position, position); return position; } uint64_t FileAccessExtension::get_length() const { uint64_t length = 0; - GDVIRTUAL_CALL(_get_length, length); + GDVIRTUAL_REQUIRED_CALL(_get_length, length); return length; } bool FileAccessExtension::eof_reached() const { bool eof_reached = false; - GDVIRTUAL_CALL(_eof_reached, eof_reached); + GDVIRTUAL_REQUIRED_CALL(_eof_reached, eof_reached); return eof_reached; } uint8_t FileAccessExtension::get_8() const { uint8_t val = 0; - GDVIRTUAL_CALL(_get_8, val); + GDVIRTUAL_REQUIRED_CALL(_get_8, val); return val; } uint16_t FileAccessExtension::get_16() const { uint16_t val = 0; - GDVIRTUAL_CALL(_get_16, val); - return val; + if (GDVIRTUAL_CALL(_get_16, val)) { + return val; + } + return FileAccess::get_16(); } uint32_t FileAccessExtension::get_32() const { uint32_t val = 0; - GDVIRTUAL_CALL(_get_32, val); - return val; + if (GDVIRTUAL_CALL(_get_32, val)) { + return val; + } + return FileAccess::get_32(); } uint64_t FileAccessExtension::get_64() const { uint64_t val = 0; - GDVIRTUAL_CALL(_get_64, val); - return val; + if (GDVIRTUAL_CALL(_get_64, val)) { + return val; + } + return FileAccess::get_64(); } float FileAccessExtension::get_float() const { float val = 0; - GDVIRTUAL_CALL(_get_float, val); - return val; + if (GDVIRTUAL_CALL(_get_float, val)) { + return val; + } + return FileAccess::get_float(); } double FileAccessExtension::get_double() const { double val = 0; - GDVIRTUAL_CALL(_get_double, val); - return val; + if (GDVIRTUAL_CALL(_get_double, val)) { + return val; + } + return FileAccess::get_double(); } real_t FileAccessExtension::get_real() const { real_t val = 0; - GDVIRTUAL_CALL(_get_real, val); - return val; + if (GDVIRTUAL_CALL(_get_real, val)) { + return val; + } + return FileAccess::get_real(); } Variant FileAccessExtension::get_var(bool p_allow_objects) const { Variant var; - GDVIRTUAL_CALL(_get_var, p_allow_objects, var); - return var; + if (GDVIRTUAL_CALL(_get_var, p_allow_objects, var)) { + return var; + } + return FileAccess::get_var(p_allow_objects); } uint64_t FileAccessExtension::get_buffer(uint8_t *p_dst, uint64_t p_length) const { @@ -151,102 +211,132 @@ uint64_t FileAccessExtension::get_buffer(uint8_t *p_dst, uint64_t p_length) cons Vector FileAccessExtension::get_buffer(int64_t p_length) const { Vector buffer; - GDVIRTUAL_CALL(_get_buffer, p_length, buffer); - return buffer; + if (GDVIRTUAL_CALL(_get_buffer, p_length, buffer)) { + return buffer; + } + return FileAccess::get_buffer(p_length); } String FileAccessExtension::get_line() const { String line; - GDVIRTUAL_CALL(_get_line, line); - return line; + if (GDVIRTUAL_CALL(_get_line, line)) { + return line; + } + return FileAccess::get_line(); } String FileAccessExtension::get_token() const { String token; - GDVIRTUAL_CALL(_get_token, token); - return token; + if (GDVIRTUAL_CALL(_get_token, token)) { + return token; + } + return FileAccess::get_token(); } Vector FileAccessExtension::get_csv_line(const String &p_delim) const { Vector csv_line; - GDVIRTUAL_CALL(_get_csv_line, p_delim, csv_line); - return csv_line; + if (GDVIRTUAL_CALL(_get_csv_line, p_delim, csv_line)) { + return csv_line; + } + return FileAccess::get_csv_line(p_delim); } String FileAccessExtension::get_as_text(bool p_skip_cr) const { String val_as_text; - GDVIRTUAL_CALL(_get_as_text, p_skip_cr, val_as_text); - return val_as_text; + if (GDVIRTUAL_CALL(_get_as_text, p_skip_cr, val_as_text)) { + return val_as_text; + } + return FileAccess::get_as_text(p_skip_cr); } String FileAccessExtension::get_as_utf8_string(bool p_skip_cr) const { String val_as_utf8_string; - GDVIRTUAL_CALL(_get_as_utf8_string, p_skip_cr, val_as_utf8_string); - return val_as_utf8_string; -} - -void FileAccessExtension::set_big_endian(bool p_big_endian) { - GDVIRTUAL_CALL(_set_big_endian, p_big_endian); + if (GDVIRTUAL_CALL(_get_as_utf8_string, p_skip_cr, val_as_utf8_string)) { + return val_as_utf8_string; + } + return FileAccess::get_as_utf8_string(p_skip_cr); } Error FileAccessExtension::get_error() const { Error err = OK; - GDVIRTUAL_CALL(_get_error, err); + GDVIRTUAL_REQUIRED_CALL(_get_error, err); return err; } void FileAccessExtension::flush() { - GDVIRTUAL_CALL(_flush); + GDVIRTUAL_REQUIRED_CALL(_flush); } void FileAccessExtension::store_8(uint8_t p_dest) { - GDVIRTUAL_CALL(_store_8, p_dest); + GDVIRTUAL_REQUIRED_CALL(_store_8, p_dest); } void FileAccessExtension::store_16(uint16_t p_dest) { - GDVIRTUAL_CALL(_store_16, p_dest); + if (!GDVIRTUAL_CALL(_store_16, p_dest)) { + FileAccess::store_16(p_dest); + } } void FileAccessExtension::store_32(uint32_t p_dest) { - GDVIRTUAL_CALL(_store_32, p_dest); + if (!GDVIRTUAL_CALL(_store_32, p_dest)) { + FileAccess::store_32(p_dest); + } } void FileAccessExtension::store_64(uint64_t p_dest) { - GDVIRTUAL_CALL(_store_64, p_dest); + if (!GDVIRTUAL_CALL(_store_64, p_dest)) { + FileAccess::store_64(p_dest); + } } void FileAccessExtension::store_float(float p_dest) { - GDVIRTUAL_CALL(_store_float, p_dest); + if (!GDVIRTUAL_CALL(_store_float, p_dest)) { + FileAccess::store_float(p_dest); + } } void FileAccessExtension::store_double(double p_dest) { - GDVIRTUAL_CALL(_store_double, p_dest); + if (!GDVIRTUAL_CALL(_store_double, p_dest)) { + FileAccess::store_double(p_dest); + } } void FileAccessExtension::store_real(real_t p_dest) { - GDVIRTUAL_CALL(_store_real, p_dest); + if (!GDVIRTUAL_CALL(_store_real, p_dest)) { + FileAccess::store_real(p_dest); + } } void FileAccessExtension::store_string(const String &p_string) { - GDVIRTUAL_CALL(_store_string, p_string); + if (!GDVIRTUAL_CALL(_store_string, p_string)) { + FileAccess::store_string(p_string); + } } void FileAccessExtension::store_line(const String &p_line) { - GDVIRTUAL_CALL(_store_line, p_line); + if (!GDVIRTUAL_CALL(_store_line, p_line)) { + FileAccess::store_line(p_line); + } } void FileAccessExtension::store_csv_line(const Vector &p_values, const String &p_delim) { - GDVIRTUAL_CALL(_store_csv_line, p_values, p_delim); + if (!GDVIRTUAL_CALL(_store_csv_line, p_values, p_delim)) { + FileAccess::store_csv_line(p_values, p_delim); + } } void FileAccessExtension::store_pascal_string(const String &p_string) { - GDVIRTUAL_CALL(_store_pascal_string, p_string); + if (!GDVIRTUAL_CALL(_store_pascal_string, p_string)) { + FileAccess::store_pascal_string(p_string); + } } String FileAccessExtension::get_pascal_string() { String string; - GDVIRTUAL_CALL(_get_pascal_string, string); - return string; + if (GDVIRTUAL_CALL(_get_pascal_string, string)) { + return string; + } + return FileAccess::get_pascal_string(); } void FileAccessExtension::store_buffer(const uint8_t *p_src, uint64_t p_length) { @@ -259,30 +349,46 @@ void FileAccessExtension::store_buffer(const uint8_t *p_src, uint64_t p_length) } void FileAccessExtension::store_buffer(const Vector &p_buffer) { - GDVIRTUAL_CALL(_store_buffer, p_buffer); + if (!GDVIRTUAL_CALL(_store_buffer, p_buffer)) { + FileAccess::store_buffer(p_buffer); + } } void FileAccessExtension::store_var(const Variant &p_var, bool p_full_objects) { - GDVIRTUAL_CALL(_store_var, p_var, p_full_objects); + if (!GDVIRTUAL_CALL(_store_var, p_var, p_full_objects)) { + FileAccess::store_var(p_var, p_full_objects); + } } void FileAccessExtension::close() { - GDVIRTUAL_CALL(_close); + GDVIRTUAL_REQUIRED_CALL(_close); } bool FileAccessExtension::file_exists(const String &p_name) { bool file_exists; - GDVIRTUAL_CALL(_file_exists, p_name, file_exists); + GDVIRTUAL_REQUIRED_CALL(_file_exists, p_name, file_exists); return file_exists; } Error FileAccessExtension::reopen(const String &p_path, int p_mode_flags) { Error err = OK; - GDVIRTUAL_CALL(_reopen, p_path, p_mode_flags, err); - return err; + if (GDVIRTUAL_CALL(_reopen, p_path, p_mode_flags, err)) { + return err; + } + return FileAccess::reopen(p_path, p_mode_flags); } void FileAccessExtension::_bind_methods() { + // ClassDB::bind_static_method("FileAccessExtension", D_METHOD("create"), &FileAccessExtension::create); + + GDVIRTUAL_BIND(__get_unix_permissions, "file"); + GDVIRTUAL_BIND(__set_unix_permissions, "file", "permissions"); + + GDVIRTUAL_BIND(__get_hidden_attribute, "file"); + GDVIRTUAL_BIND(__set_hidden_attribute, "file", "hidden"); + GDVIRTUAL_BIND(__get_read_only_attribute, "file"); + GDVIRTUAL_BIND(__set_read_only_attribute, "file", "ro"); + GDVIRTUAL_BIND(_open_internal, "path", "mode_flags"); GDVIRTUAL_BIND(__get_modified_time, "file"); @@ -316,8 +422,6 @@ void FileAccessExtension::_bind_methods() { GDVIRTUAL_BIND(_get_as_text, "skip_cr"); GDVIRTUAL_BIND(_get_as_utf8_string, "skip_cr"); - GDVIRTUAL_BIND(_set_big_endian, "big_endian"); - GDVIRTUAL_BIND(_get_error); GDVIRTUAL_BIND(_flush); diff --git a/core/io/file_access_extension.h b/core/io/file_access_extension.h index 94df6d1e1538..e73d96833197 100644 --- a/core/io/file_access_extension.h +++ b/core/io/file_access_extension.h @@ -38,6 +38,20 @@ class FileAccessExtension : public FileAccess { GDCLASS(FileAccessExtension, FileAccess); + GDVIRTUAL1R(BitField, __get_unix_permissions, String); + virtual BitField _get_unix_permissions(const String &p_file) override; + GDVIRTUAL2R(Error, __set_unix_permissions, String, BitField); + virtual Error _set_unix_permissions(const String &p_file, BitField p_permissions) override; + + GDVIRTUAL1R(bool, __get_hidden_attribute, String); + virtual bool _get_hidden_attribute(const String &p_file) override; + GDVIRTUAL2R(Error, __set_hidden_attribute, String, bool); + virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override; + GDVIRTUAL1R(bool, __get_read_only_attribute, String); + virtual bool _get_read_only_attribute(const String &p_file) override; + GDVIRTUAL2R(Error, __set_read_only_attribute, String, bool); + virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override; + protected: static void _bind_methods(); @@ -47,6 +61,8 @@ class FileAccessExtension : public FileAccess { virtual uint64_t _get_modified_time(const String &p_file) override; public: + // static Ref create(); + GDVIRTUAL0RC(bool, _is_open); virtual bool is_open() const override; @@ -100,9 +116,6 @@ class FileAccessExtension : public FileAccess { GDVIRTUAL1RC(String, _get_as_utf8_string, bool); virtual String get_as_utf8_string(bool p_skip_cr = false) const override; - GDVIRTUAL1(_set_big_endian, bool); - virtual void set_big_endian(bool p_big_endian) override; - GDVIRTUAL0RC(Error, _get_error); virtual Error get_error() const override; diff --git a/doc/classes/FileAccessExtension.xml b/doc/classes/FileAccessExtension.xml index cd5d710b72df..45ffa3f709da 100644 --- a/doc/classes/FileAccessExtension.xml +++ b/doc/classes/FileAccessExtension.xml @@ -7,12 +7,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -170,12 +209,6 @@ - - - - - - diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 2d6c0c1d1133..b1167fcd9bbe 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -865,6 +865,15 @@ Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int top = top->_base; } + if (native.is_valid()) { + Callable::CallError err; + Variant ret = native->callp(p_method, p_args, p_argcount, err); + if (err.error == Callable::CallError::CALL_OK) { + r_error = err; + return ret; + } + } + //none found, regular return Script::callp(p_method, p_args, p_argcount, r_error); From 7a5946f7e407f70ae86ce0451562aab3ab82f4f3 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Fri, 26 Jan 2024 10:31:36 -0500 Subject: [PATCH 06/20] Finish up `FileAccessExtension` --- core/io/file_access_extension.cpp | 8 -------- core/io/file_access_extension.h | 9 ++++----- core/register_core_types.cpp | 2 +- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/core/io/file_access_extension.cpp b/core/io/file_access_extension.cpp index 22a271369d7b..b92de6ec418f 100644 --- a/core/io/file_access_extension.cpp +++ b/core/io/file_access_extension.cpp @@ -32,12 +32,6 @@ #include "core/object/object.h" -// Ref FileAccessExtension::create() { -// Ref file_access; -// file_access.instantiate(); -// return file_access; -// } - BitField FileAccessExtension::_get_unix_permissions(const String &p_file) { BitField permissions = 0; GDVIRTUAL_REQUIRED_CALL(__get_unix_permissions, p_file, permissions); @@ -379,8 +373,6 @@ Error FileAccessExtension::reopen(const String &p_path, int p_mode_flags) { } void FileAccessExtension::_bind_methods() { - // ClassDB::bind_static_method("FileAccessExtension", D_METHOD("create"), &FileAccessExtension::create); - GDVIRTUAL_BIND(__get_unix_permissions, "file"); GDVIRTUAL_BIND(__set_unix_permissions, "file", "permissions"); diff --git a/core/io/file_access_extension.h b/core/io/file_access_extension.h index e73d96833197..0740852e9185 100644 --- a/core/io/file_access_extension.h +++ b/core/io/file_access_extension.h @@ -38,6 +38,10 @@ class FileAccessExtension : public FileAccess { GDCLASS(FileAccessExtension, FileAccess); +protected: + static void _bind_methods(); + +private: GDVIRTUAL1R(BitField, __get_unix_permissions, String); virtual BitField _get_unix_permissions(const String &p_file) override; GDVIRTUAL2R(Error, __set_unix_permissions, String, BitField); @@ -52,17 +56,12 @@ class FileAccessExtension : public FileAccess { GDVIRTUAL2R(Error, __set_read_only_attribute, String, bool); virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override; -protected: - static void _bind_methods(); - GDVIRTUAL2R(Error, _open_internal, String, int); virtual Error open_internal(const String &p_path, int p_mode_flags) override; GDVIRTUAL1R(uint64_t, __get_modified_time, String); virtual uint64_t _get_modified_time(const String &p_file) override; public: - // static Ref create(); - GDVIRTUAL0RC(bool, _is_open); virtual bool is_open() const override; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 9c183de85238..37ad92ccf4db 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -244,7 +244,7 @@ void register_core_types() { GDREGISTER_ABSTRACT_CLASS(FileAccess); GDREGISTER_ABSTRACT_CLASS(DirAccess); - GDREGISTER_ABSTRACT_CLASS(FileAccessExtension); + GDREGISTER_VIRTUAL_CLASS(FileAccessExtension); GDREGISTER_CLASS(core_bind::Thread); GDREGISTER_CLASS(core_bind::Mutex); GDREGISTER_CLASS(core_bind::Semaphore); From 7373ba87eca716e9eb6b7ed158e2de547d3b2722 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Fri, 26 Jan 2024 12:26:55 -0500 Subject: [PATCH 07/20] Add `resource_path_class` --- core/io/file_access.cpp | 92 +++++++++++++++++++++++++++++------------ core/io/file_access.h | 10 +++++ 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index cf1cf8889bd4..0fe494978ad2 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -43,6 +43,7 @@ FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = {}; FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr; HashMap FileAccess::resource_paths = HashMap(); +HashMap> FileAccess::resource_paths_class = HashMap>(); bool FileAccess::backup_save = false; thread_local Error FileAccess::last_file_open_error = OK; @@ -858,56 +859,44 @@ String FileAccess::get_sha256(const String &p_file) { return String::hex_encode_buffer(hash, 32); } -void FileAccess::add_resource_path(const String &p_protocol, const String &p_path) { - ERR_FAIL_COND_MSG(p_protocol.length() == 0, "Protocol parameter is empty."); - +String FileAccess::_get_protocol(const String &p_protocol) { String protocol = p_protocol; if (protocol.ends_with("://")) { - protocol = protocol.left(protocol.length() - 3); + return protocol.left(protocol.length() - 3); } + return protocol; +} +void FileAccess::add_resource_path(const String &p_protocol, const String &p_path) { + ERR_FAIL_COND_MSG(p_protocol.length() == 0, "Protocol parameter is empty."); + String protocol = _get_protocol(p_protocol); ERR_FAIL_COND_MSG(protocol == "res" || protocol == "user", vformat("Protocol \"%s://\" is built-in.", protocol)); - ERR_FAIL_COND_MSG(resource_paths.has(p_protocol), vformat("Protocol \"%s://\" is already registered.", protocol)); + ERR_FAIL_COND_MSG(resource_paths.has(protocol), vformat("Protocol \"%s://\" is already registered as a resource path.", protocol)); + ERR_FAIL_COND_MSG(resource_paths_class.has(protocol), vformat("Protocol \"%s://\" is already registered as a resource path class.", protocol)); resource_paths[protocol] = p_path; } void FileAccess::remove_resource_path(const String &p_protocol) { ERR_FAIL_COND_MSG(p_protocol.length() == 0, "Protocol parameter is empty."); - - String protocol = p_protocol; - if (protocol.ends_with("://")) { - protocol = protocol.left(protocol.length() - 3); - } - + String protocol = _get_protocol(p_protocol); ERR_FAIL_COND_MSG(protocol == "res" || protocol == "user", vformat("Protocol \"%s://\" is built-in.", protocol)); - ERR_FAIL_COND_MSG(!resource_paths.has(p_protocol), vformat("Protocol \"%s://\" is not registered.", protocol)); + ERR_FAIL_COND_MSG(!resource_paths.has(protocol), vformat("Protocol \"%s://\" is not registered as a resource class.", protocol)); resource_paths.erase(protocol); } bool FileAccess::is_resource_path(const String &p_protocol) { ERR_FAIL_COND_V_MSG(p_protocol.length() == 0, false, "Protocol parameter is empty."); - - String protocol = p_protocol; - if (protocol.ends_with("://")) { - protocol = protocol.left(protocol.length() - 3); - } - + String protocol = _get_protocol(p_protocol); ERR_FAIL_COND_V_MSG(protocol == "res" || protocol == "user", false, vformat("Protocol \"%s://\" is built-in.", protocol)); return resource_paths.has(protocol); } String FileAccess::get_resource_path(const String &p_protocol) { - if (!is_resource_path(p_protocol)) { - return ""; - } - - String protocol = p_protocol; - if (protocol.ends_with("://")) { - protocol = protocol.left(protocol.length() - 3); - } + ERR_FAIL_COND_V_MSG(!is_resource_path(p_protocol), "", "Getting resource path from non resource path."); + String protocol = _get_protocol(p_protocol); return resource_paths[protocol]; } @@ -922,6 +911,49 @@ Dictionary FileAccess::get_resource_paths() { return output; } +void FileAccess::add_resource_path_class(const String &p_protocol, const String &p_file_access_class, const String &p_dir_access_class) { + ERR_FAIL_COND_MSG(p_protocol.length() == 0, "Protocol parameter is empty."); + String protocol = _get_protocol(p_protocol); + ERR_FAIL_COND_MSG(protocol == "res" || protocol == "user", vformat("Protocol \"%s://\" is built-in.", protocol)); + ERR_FAIL_COND_MSG(resource_paths.has(protocol), vformat("Protocol \"%s://\" is already registered as a resource path.", protocol)); + ERR_FAIL_COND_MSG(resource_paths_class.has(protocol), vformat("Protocol \"%s://\" is already registered as a resource path class.", protocol)); + + resource_paths_class[protocol] = Vector({ p_file_access_class, p_dir_access_class }); +} + +void FileAccess::remove_resource_path_class(const String &p_protocol) { + ERR_FAIL_COND_MSG(p_protocol.length() == 0, "Protocol parameter is empty."); + String protocol = _get_protocol(p_protocol); + ERR_FAIL_COND_MSG(protocol == "res" || protocol == "user", vformat("Protocol \"%s://\" is built-in.", protocol)); + ERR_FAIL_COND_MSG(!resource_paths_class.has(protocol) && !resource_paths_class.has(protocol), vformat("Protocol \"%s://\" is not registered as a resource path class.", protocol)); + + resource_paths_class.erase(protocol); +} + +bool FileAccess::is_resource_path_class(const String &p_protocol) { + ERR_FAIL_COND_V_MSG(p_protocol.length() == 0, false, "Protocol parameter is empty."); + String protocol = _get_protocol(p_protocol); + ERR_FAIL_COND_V_MSG(protocol == "res" || protocol == "user", false, vformat("Protocol \"%s://\" is built-in.", protocol)); + + return resource_paths_class.has(protocol); +} + +Vector FileAccess::get_resource_path_class(const String &p_protocol) { + ERR_FAIL_COND_V_MSG(!is_resource_path(p_protocol), Vector(), "Getting resource path class from non resource path."); + String protocol = _get_protocol(p_protocol); + return resource_paths_class[protocol]; +} + +Dictionary FileAccess::get_resource_paths_class() { + Dictionary output; + + for (KeyValue> kv : resource_paths_class) { + output[kv.key] = kv.value; + } + + return output; +} + void FileAccess::_bind_methods() { ClassDB::bind_static_method("FileAccess", D_METHOD("open", "path", "flags"), &FileAccess::_open); ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::open_encrypted); @@ -988,12 +1020,20 @@ void FileAccess::_bind_methods() { ClassDB::bind_static_method("FileAccess", D_METHOD("set_read_only_attribute", "file", "ro"), &FileAccess::set_read_only_attribute); ClassDB::bind_static_method("FileAccess", D_METHOD("get_read_only_attribute", "file"), &FileAccess::get_read_only_attribute); + // Resource paths ClassDB::bind_static_method("FileAccess", D_METHOD("add_resource_path", "protocol", "path"), &FileAccess::add_resource_path); ClassDB::bind_static_method("FileAccess", D_METHOD("remove_resource_path", "protocol"), &FileAccess::remove_resource_path); ClassDB::bind_static_method("FileAccess", D_METHOD("is_resource_path", "protocol"), &FileAccess::is_resource_path); ClassDB::bind_static_method("FileAccess", D_METHOD("get_resource_path", "protocol"), &FileAccess::get_resource_path); ClassDB::bind_static_method("FileAccess", D_METHOD("get_resource_paths"), &FileAccess::get_resource_paths); + ClassDB::bind_static_method("FileAccess", D_METHOD("add_resource_path_class", "protocol", "file_access_class", "dir_access_class"), &FileAccess::add_resource_path_class); + ClassDB::bind_static_method("FileAccess", D_METHOD("remove_resource_path_class", "protocol"), &FileAccess::remove_resource_path_class); + ClassDB::bind_static_method("FileAccess", D_METHOD("is_resource_path_class", "protocol"), &FileAccess::is_resource_path_class); + ClassDB::bind_static_method("FileAccess", D_METHOD("get_resource_path_class", "protocol"), &FileAccess::get_resource_path_class); + ClassDB::bind_static_method("FileAccess", D_METHOD("get_resource_paths_class"), &FileAccess::get_resource_paths_class); + // End resource paths + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian"); BIND_ENUM_CONSTANT(READ); diff --git a/core/io/file_access.h b/core/io/file_access.h index bc479b1cb97c..632be7380131 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -122,6 +122,8 @@ class FileAccess : public RefCounted { static Ref _open(const String &p_path, ModeFlags p_mode_flags); static HashMap resource_paths; + static HashMap> resource_paths_class; + static String _get_protocol(const String &p_protocol); public: static void set_file_close_fail_notify_callback(FileCloseFailNotify p_cbk) { close_fail_notify = p_cbk; } @@ -228,12 +230,20 @@ class FileAccess : public RefCounted { static PackedByteArray _get_file_as_bytes(const String &p_path) { return get_file_as_bytes(p_path, &last_file_open_error); } static String _get_file_as_string(const String &p_path) { return get_file_as_string(p_path, &last_file_open_error); } + // Resource paths static void add_resource_path(const String &p_protocol, const String &p_path); static void remove_resource_path(const String &p_protocol); static bool is_resource_path(const String &p_protocol); static String get_resource_path(const String &p_protocol); static Dictionary get_resource_paths(); + static void add_resource_path_class(const String &p_protocol, const String &p_custom_file_access_class, const String &p_custom_dir_access_class); + static void remove_resource_path_class(const String &p_protocol); + static bool is_resource_path_class(const String &p_protocol); + static Vector get_resource_path_class(const String &p_protocol); + static Dictionary get_resource_paths_class(); + // End resource paths + template static void make_default(AccessType p_access) { create_func[p_access] = _create_builtin; From 06bd1580ecba292eebc3d9c848c5cd60edd071b5 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Fri, 26 Jan 2024 14:28:33 -0500 Subject: [PATCH 08/20] Add logic to bind custom FileAccess --- core/io/file_access.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index 0fe494978ad2..c411abf8a892 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -36,6 +36,8 @@ #include "core/io/file_access_encrypted.h" #include "core/io/file_access_pack.h" #include "core/io/marshalls.h" +#include "core/io/resource_loader.h" +#include "core/object/script_language.h" #include "core/os/os.h" FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = {}; @@ -79,7 +81,32 @@ Ref FileAccess::create_for_path(const String &p_path) { } else if (p_path.begins_with("user://")) { ret = create(ACCESS_USERDATA); } else { - ret = create(ACCESS_FILESYSTEM); + for (KeyValue> kv : resource_paths_class) { + if (p_path.begins_with(kv.key + "://")) { + if (ScriptServer::is_global_class(kv.value[0])) { + String path = ScriptServer::get_global_class_path(kv.value[0]); + Ref