summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/project_settings.cpp28
-rw-r--r--core/core_bind.cpp645
-rw-r--r--core/core_bind.h157
-rw-r--r--core/doc_data.h1
-rw-r--r--core/extension/extension_api_dump.cpp9
-rw-r--r--core/extension/gdnative_interface.cpp2
-rw-r--r--core/extension/make_wrappers.py83
-rw-r--r--core/input/gamecontrollerdb.txt20
-rw-r--r--core/input/input_event.cpp2
-rw-r--r--core/io/dir_access.cpp162
-rw-r--r--core/io/dir_access.h33
-rw-r--r--core/io/file_access.cpp206
-rw-r--r--core/io/file_access.h50
-rw-r--r--core/io/file_access_compressed.cpp2
-rw-r--r--core/io/file_access_compressed.h2
-rw-r--r--core/io/file_access_encrypted.cpp2
-rw-r--r--core/io/file_access_encrypted.h2
-rw-r--r--core/io/file_access_memory.cpp2
-rw-r--r--core/io/file_access_memory.h2
-rw-r--r--core/io/file_access_network.cpp2
-rw-r--r--core/io/file_access_network.h2
-rw-r--r--core/io/file_access_pack.cpp2
-rw-r--r--core/io/file_access_pack.h2
-rw-r--r--core/io/file_access_zip.cpp4
-rw-r--r--core/io/file_access_zip.h2
-rw-r--r--core/io/image_loader.cpp54
-rw-r--r--core/io/image_loader.h51
-rw-r--r--core/io/json.cpp23
-rw-r--r--core/io/json.h6
-rw-r--r--core/io/resource.cpp2
-rw-r--r--core/io/resource_format_binary.cpp4
-rw-r--r--core/io/stream_peer_gzip.cpp209
-rw-r--r--core/io/stream_peer_gzip.h76
-rw-r--r--core/math/bvh_structs.inc4
-rw-r--r--core/math/bvh_tree.h2
-rw-r--r--core/math/convex_hull.h6
-rw-r--r--core/math/math_fieldwise.cpp47
-rw-r--r--core/math/math_funcs.h44
-rw-r--r--core/math/vector2i.h2
-rw-r--r--core/math/vector3i.h2
-rw-r--r--core/math/vector4.h2
-rw-r--r--core/math/vector4i.h2
-rw-r--r--core/object/make_virtuals.py12
-rw-r--r--core/object/method_bind.h8
-rw-r--r--core/object/ref_counted.cpp3
-rw-r--r--core/object/ref_counted.h2
-rw-r--r--core/object/undo_redo.cpp160
-rw-r--r--core/object/undo_redo.h34
-rw-r--r--core/os/os.cpp4
-rw-r--r--core/os/os.h7
-rw-r--r--core/os/pool_allocator.cpp8
-rw-r--r--core/register_core_types.cpp9
-rw-r--r--core/string/ustring.cpp25
-rw-r--r--core/string/ustring.h4
-rw-r--r--core/templates/hashfuncs.h5
-rw-r--r--core/templates/paged_array.h2
-rw-r--r--core/templates/pooled_list.h5
-rw-r--r--core/variant/array.h2
-rw-r--r--core/variant/callable.cpp15
-rw-r--r--core/variant/callable.h1
-rw-r--r--core/variant/variant_call.cpp9
-rw-r--r--core/variant/variant_construct.cpp1
-rw-r--r--core/variant/variant_construct.h76
-rw-r--r--core/variant/variant_utility.cpp12
64 files changed, 1284 insertions, 1080 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 6275502378..4d19a93991 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -101,10 +101,15 @@ const PackedStringArray ProjectSettings::_get_supported_features() {
features.append(VERSION_BRANCH "." _MKSTR(VERSION_PATCH));
features.append(VERSION_FULL_CONFIG);
features.append(VERSION_FULL_BUILD);
- // For now, assume Vulkan is always supported.
- // This should be removed if it's possible to build the editor without Vulkan.
- features.append("Vulkan Clustered");
- features.append("Vulkan Mobile");
+
+#ifdef VULKAN_ENABLED
+ features.append("Forward Plus");
+ features.append("Mobile");
+#endif
+
+#ifdef GLES3_ENABLED
+ features.append("GL Compatibility");
+#endif
return features;
}
@@ -114,6 +119,10 @@ const PackedStringArray ProjectSettings::get_unsupported_features(const PackedSt
PackedStringArray supported_features = singleton->_get_supported_features();
for (int i = 0; i < p_project_features.size(); i++) {
if (!supported_features.has(p_project_features[i])) {
+ // Temporary compatibility code to ease upgrade to 4.0 beta 2+.
+ if (p_project_features[i].begins_with("Vulkan")) {
+ continue;
+ }
unsupported_features.append(p_project_features[i]);
}
}
@@ -909,7 +918,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
project_features = ProjectSettings::get_required_features();
}
// Check the rendering API.
- const String rendering_api = has_setting("rendering/quality/driver/driver_name") ? (String)get_setting("rendering/quality/driver/driver_name") : String();
+ const String rendering_api = has_setting("rendering/renderer/rendering_method") ? (String)get_setting("rendering/renderer/rendering_method") : String();
if (!rendering_api.is_empty()) {
// Add the rendering API as a project feature if it doesn't already exist.
if (!project_features.has(rendering_api)) {
@@ -1139,6 +1148,7 @@ void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_order", "name"), &ProjectSettings::get_order);
ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &ProjectSettings::set_initial_value);
ClassDB::bind_method(D_METHOD("add_property_info", "hint"), &ProjectSettings::_add_property_info_bind);
+ ClassDB::bind_method(D_METHOD("set_restart_if_changed", "name", "restart"), &ProjectSettings::set_restart_if_changed);
ClassDB::bind_method(D_METHOD("clear", "name"), &ProjectSettings::clear);
ClassDB::bind_method(D_METHOD("localize_path", "path"), &ProjectSettings::localize_path);
ClassDB::bind_method(D_METHOD("globalize_path", "path"), &ProjectSettings::globalize_path);
@@ -1201,10 +1211,16 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC("display/window/size/viewport_height", 648);
custom_prop_info["display/window/size/viewport_height"] = PropertyInfo(Variant::INT, "display/window/size/viewport_height", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"); // 8K resolution
+ GLOBAL_DEF_BASIC("display/window/size/mode", 0);
+ custom_prop_info["display/window/size/mode"] = PropertyInfo(Variant::INT, "display/window/size/mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen,Exclusive Fullscreen");
+
GLOBAL_DEF_BASIC("display/window/size/resizable", true);
GLOBAL_DEF_BASIC("display/window/size/borderless", false);
- GLOBAL_DEF_BASIC("display/window/size/fullscreen", false);
GLOBAL_DEF("display/window/size/always_on_top", false);
+ GLOBAL_DEF("display/window/size/transparent", false);
+ GLOBAL_DEF("display/window/size/extend_to_title", false);
+ GLOBAL_DEF("display/window/size/no_focus", false);
+
GLOBAL_DEF("display/window/size/window_width_override", 0);
custom_prop_info["display/window/size/window_width_override"] = PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"); // 8K resolution
GLOBAL_DEF("display/window/size/window_height_override", 0);
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index ba48adff6a..a164221fc2 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -709,6 +709,17 @@ Vector<Point2> Geometry2D::convex_hull(const Vector<Point2> &p_points) {
return ::Geometry2D::convex_hull(p_points);
}
+TypedArray<PackedVector2Array> Geometry2D::decompose_polygon_in_convex(const Vector<Vector2> &p_polygon) {
+ Vector<Vector<Point2>> decomp = ::Geometry2D::decompose_polygon_in_convex(p_polygon);
+
+ TypedArray<PackedVector2Array> ret;
+
+ for (int i = 0; i < decomp.size(); ++i) {
+ ret.push_back(decomp[i]);
+ }
+ return ret;
+}
+
TypedArray<PackedVector2Array> Geometry2D::merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
Vector<Vector<Point2>> polys = ::Geometry2D::merge_polygons(p_polygon_a, p_polygon_b);
@@ -810,14 +821,13 @@ Dictionary Geometry2D::make_atlas(const Vector<Size2> &p_rects) {
::Geometry2D::make_atlas(rects, result, size);
- Size2 r_size = size;
Vector<Point2> r_result;
for (int i = 0; i < result.size(); i++) {
r_result.push_back(result[i]);
}
ret["points"] = r_result;
- ret["size"] = r_size;
+ ret["size"] = size;
return ret;
}
@@ -841,6 +851,7 @@ void Geometry2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &Geometry2D::triangulate_polygon);
ClassDB::bind_method(D_METHOD("triangulate_delaunay", "points"), &Geometry2D::triangulate_delaunay);
ClassDB::bind_method(D_METHOD("convex_hull", "points"), &Geometry2D::convex_hull);
+ ClassDB::bind_method(D_METHOD("decompose_polygon_in_convex", "polygon"), &Geometry2D::decompose_polygon_in_convex);
ClassDB::bind_method(D_METHOD("merge_polygons", "polygon_a", "polygon_b"), &Geometry2D::merge_polygons);
ClassDB::bind_method(D_METHOD("clip_polygons", "polygon_a", "polygon_b"), &Geometry2D::clip_polygons);
@@ -992,636 +1003,6 @@ void Geometry3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &Geometry3D::clip_polygon);
}
-////// File //////
-
-Error File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) {
- Error err = open(p_path, p_mode_flags);
- if (err) {
- return err;
- }
-
- 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) {
- close();
- return err;
- }
- f = fae;
- return OK;
-}
-
-Error File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass) {
- Error err = open(p_path, p_mode_flags);
- if (err) {
- return err;
- }
-
- 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) {
- close();
- return err;
- }
-
- f = fae;
- return OK;
-}
-
-Error File::open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode) {
- Ref<FileAccessCompressed> fac;
- fac.instantiate();
- fac->configure("GCPF", (Compression::Mode)p_compress_mode);
-
- Error err = fac->_open(p_path, p_mode_flags);
-
- if (err) {
- return err;
- }
-
- f = fac;
- return OK;
-}
-
-Error File::open(const String &p_path, ModeFlags p_mode_flags) {
- Error err;
- f = FileAccess::open(p_path, p_mode_flags, &err);
- if (f.is_valid()) {
- f->set_big_endian(big_endian);
- }
- return err;
-}
-
-void File::flush() {
- ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before flushing.");
- f->flush();
-}
-
-void File::close() {
- ERR_FAIL_COND_MSG(f.is_null(), "File must be opened.");
- f.unref();
-}
-
-bool File::is_open() const {
- return f != nullptr;
-}
-
-String File::get_path() const {
- 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.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.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.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.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.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.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.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.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.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.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.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.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.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.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) {
- return data;
- }
-
- Error err = data.resize(p_length);
- ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements.");
-
- uint8_t *w = data.ptrw();
- int64_t len = f->get_buffer(&w[0], p_length);
-
- if (len < p_length) {
- data.resize(len);
- }
-
- return data;
-}
-
-String File::get_as_text(bool p_skip_cr) const {
- ERR_FAIL_COND_V_MSG(f.is_null(), String(), "File must be opened before use, or is lacking read-write permission.");
-
- uint64_t original_pos = f->get_position();
- const_cast<FileAccess *>(*f)->seek(0);
-
- String text = f->get_as_utf8_string(p_skip_cr);
-
- const_cast<FileAccess *>(*f)->seek(original_pos);
-
- return text;
-}
-
-String File::get_md5(const String &p_path) const {
- return FileAccess::get_md5(p_path);
-}
-
-String File::get_sha256(const String &p_path) const {
- return FileAccess::get_sha256(p_path);
-}
-
-String File::get_line() const {
- 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.is_null(), Vector<String>(), "File must be opened before use, or is lacking read-write permission.");
- return f->get_csv_line(p_delim);
-}
-
-/**< use this for files WRITTEN in _big_ endian machines (i.e. amiga/mac)
- * It's not about the current CPU type but file formats.
- * These flags get reset to false (little endian) on each open
- */
-
-void File::set_big_endian(bool p_big_endian) {
- big_endian = p_big_endian;
- if (f.is_valid()) {
- f->set_big_endian(p_big_endian);
- }
-}
-
-bool File::is_big_endian() {
- return big_endian;
-}
-
-Error File::get_error() const {
- if (f.is_null()) {
- return ERR_UNCONFIGURED;
- }
- return f->get_error();
-}
-
-void File::store_8(uint8_t p_dest) {
- 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.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.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.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.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.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.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.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.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.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.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.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.is_null(), "File must be opened before use, or is lacking read-write permission.");
-
- uint64_t len = p_buffer.size();
- if (len == 0) {
- return;
- }
-
- const uint8_t *r = p_buffer.ptr();
-
- f->store_buffer(&r[0], len);
-}
-
-bool File::file_exists(const String &p_name) {
- return FileAccess::exists(p_name);
-}
-
-void File::store_var(const Variant &p_var, bool p_full_objects) {
- 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.");
-
- Vector<uint8_t> buff;
- buff.resize(len);
-
- uint8_t *w = buff.ptrw();
- err = encode_variant(p_var, &w[0], len, p_full_objects);
- ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
-
- store_32(len);
- store_buffer(buff);
-}
-
-Variant File::get_var(bool p_allow_objects) const {
- 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());
-
- const uint8_t *r = buff.ptr();
-
- Variant v;
- Error err = decode_variant(v, &r[0], len, nullptr, p_allow_objects);
- ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to encode Variant.");
-
- return v;
-}
-
-uint64_t File::get_modified_time(const String &p_file) const {
- return FileAccess::get_modified_time(p_file);
-}
-
-void File::_bind_methods() {
- ClassDB::bind_method(D_METHOD("open_encrypted", "path", "mode_flags", "key"), &File::open_encrypted);
- ClassDB::bind_method(D_METHOD("open_encrypted_with_pass", "path", "mode_flags", "pass"), &File::open_encrypted_pass);
- ClassDB::bind_method(D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &File::open_compressed, DEFVAL(0));
-
- ClassDB::bind_method(D_METHOD("open", "path", "flags"), &File::open);
- ClassDB::bind_method(D_METHOD("flush"), &File::flush);
- ClassDB::bind_method(D_METHOD("close"), &File::close);
- ClassDB::bind_method(D_METHOD("get_path"), &File::get_path);
- ClassDB::bind_method(D_METHOD("get_path_absolute"), &File::get_path_absolute);
- ClassDB::bind_method(D_METHOD("is_open"), &File::is_open);
- ClassDB::bind_method(D_METHOD("seek", "position"), &File::seek);
- ClassDB::bind_method(D_METHOD("seek_end", "position"), &File::seek_end, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_position"), &File::get_position);
- ClassDB::bind_method(D_METHOD("get_length"), &File::get_length);
- ClassDB::bind_method(D_METHOD("eof_reached"), &File::eof_reached);
- ClassDB::bind_method(D_METHOD("get_8"), &File::get_8);
- ClassDB::bind_method(D_METHOD("get_16"), &File::get_16);
- ClassDB::bind_method(D_METHOD("get_32"), &File::get_32);
- ClassDB::bind_method(D_METHOD("get_64"), &File::get_64);
- ClassDB::bind_method(D_METHOD("get_float"), &File::get_float);
- ClassDB::bind_method(D_METHOD("get_double"), &File::get_double);
- ClassDB::bind_method(D_METHOD("get_real"), &File::get_real);
- ClassDB::bind_method(D_METHOD("get_buffer", "length"), &File::get_buffer);
- ClassDB::bind_method(D_METHOD("get_line"), &File::get_line);
- ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &File::get_csv_line, DEFVAL(","));
- ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &File::get_as_text, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_md5", "path"), &File::get_md5);
- ClassDB::bind_method(D_METHOD("get_sha256", "path"), &File::get_sha256);
- ClassDB::bind_method(D_METHOD("is_big_endian"), &File::is_big_endian);
- ClassDB::bind_method(D_METHOD("set_big_endian", "big_endian"), &File::set_big_endian);
- ClassDB::bind_method(D_METHOD("get_error"), &File::get_error);
- ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &File::get_var, DEFVAL(false));
-
- ClassDB::bind_method(D_METHOD("store_8", "value"), &File::store_8);
- ClassDB::bind_method(D_METHOD("store_16", "value"), &File::store_16);
- ClassDB::bind_method(D_METHOD("store_32", "value"), &File::store_32);
- ClassDB::bind_method(D_METHOD("store_64", "value"), &File::store_64);
- ClassDB::bind_method(D_METHOD("store_float", "value"), &File::store_float);
- ClassDB::bind_method(D_METHOD("store_double", "value"), &File::store_double);
- ClassDB::bind_method(D_METHOD("store_real", "value"), &File::store_real);
- ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &File::store_buffer);
- ClassDB::bind_method(D_METHOD("store_line", "line"), &File::store_line);
- ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &File::store_csv_line, DEFVAL(","));
- ClassDB::bind_method(D_METHOD("store_string", "string"), &File::store_string);
- ClassDB::bind_method(D_METHOD("store_var", "value", "full_objects"), &File::store_var, DEFVAL(false));
-
- ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &File::store_pascal_string);
- ClassDB::bind_method(D_METHOD("get_pascal_string"), &File::get_pascal_string);
-
- ClassDB::bind_static_method("File", D_METHOD("file_exists", "path"), &File::file_exists);
- ClassDB::bind_method(D_METHOD("get_modified_time", "file"), &File::get_modified_time);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian");
-
- BIND_ENUM_CONSTANT(READ);
- BIND_ENUM_CONSTANT(WRITE);
- BIND_ENUM_CONSTANT(READ_WRITE);
- BIND_ENUM_CONSTANT(WRITE_READ);
-
- BIND_ENUM_CONSTANT(COMPRESSION_FASTLZ);
- BIND_ENUM_CONSTANT(COMPRESSION_DEFLATE);
- BIND_ENUM_CONSTANT(COMPRESSION_ZSTD);
- BIND_ENUM_CONSTANT(COMPRESSION_GZIP);
-}
-
-////// Directory //////
-
-Error Directory::open(const String &p_path) {
- Error err;
- Ref<DirAccess> alt = DirAccess::open(p_path, &err);
- if (alt.is_null()) {
- return err;
- }
- d = alt;
- dir_open = true;
-
- return OK;
-}
-
-bool Directory::is_open() const {
- return d.is_valid() && dir_open;
-}
-
-Error Directory::list_dir_begin() {
- ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
- return d->list_dir_begin();
-}
-
-String Directory::get_next() {
- ERR_FAIL_COND_V_MSG(!is_open(), "", "Directory must be opened before use.");
-
- String next = d->get_next();
- while (!next.is_empty() && ((!include_navigational && (next == "." || next == "..")) || (!include_hidden && d->current_is_hidden()))) {
- next = d->get_next();
- }
- return next;
-}
-
-bool Directory::current_is_dir() const {
- ERR_FAIL_COND_V_MSG(!is_open(), false, "Directory must be opened before use.");
- return d->current_is_dir();
-}
-
-void Directory::list_dir_end() {
- ERR_FAIL_COND_MSG(!is_open(), "Directory must be opened before use.");
- d->list_dir_end();
-}
-
-PackedStringArray Directory::get_files() {
- return _get_contents(false);
-}
-
-PackedStringArray Directory::get_directories() {
- return _get_contents(true);
-}
-
-PackedStringArray Directory::_get_contents(bool p_directories) {
- PackedStringArray ret;
- ERR_FAIL_COND_V_MSG(!is_open(), ret, "Directory must be opened before use.");
-
- list_dir_begin();
- String s = get_next();
- while (!s.is_empty()) {
- if (current_is_dir() == p_directories) {
- ret.append(s);
- }
- s = get_next();
- }
-
- ret.sort();
- return ret;
-}
-
-void Directory::set_include_navigational(bool p_enable) {
- include_navigational = p_enable;
-}
-
-bool Directory::get_include_navigational() const {
- return include_navigational;
-}
-
-void Directory::set_include_hidden(bool p_enable) {
- include_hidden = p_enable;
-}
-
-bool Directory::get_include_hidden() const {
- return include_hidden;
-}
-
-int Directory::get_drive_count() {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "Directory must be opened before use.");
- return d->get_drive_count();
-}
-
-String Directory::get_drive(int p_drive) {
- ERR_FAIL_COND_V_MSG(!is_open(), "", "Directory must be opened before use.");
- return d->get_drive(p_drive);
-}
-
-int Directory::get_current_drive() {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "Directory must be opened before use.");
- return d->get_current_drive();
-}
-
-Error Directory::change_dir(String p_dir) {
- 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) {
- return err;
- }
- dir_open = true;
-
- return OK;
-}
-
-String Directory::get_current_dir() {
- ERR_FAIL_COND_V_MSG(!is_open(), "", "Directory must be opened before use.");
- return d->get_current_dir();
-}
-
-Error Directory::make_dir(String p_dir) {
- ERR_FAIL_COND_V_MSG(d.is_null(), ERR_UNCONFIGURED, "Directory is not configured properly.");
- if (!p_dir.is_relative_path()) {
- 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.is_null(), ERR_UNCONFIGURED, "Directory is not configured properly.");
- if (!p_dir.is_relative_path()) {
- 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.is_null(), false, "Directory is not configured properly.");
- if (!p_file.is_relative_path()) {
- return FileAccess::exists(p_file);
- }
- return d->file_exists(p_file);
-}
-
-bool Directory::dir_exists(String p_dir) {
- 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);
- }
- return d->dir_exists(p_dir);
-}
-
-uint64_t Directory::get_space_left() {
- 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.
-}
-
-Error Directory::copy(String p_from, String p_to) {
- ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
- return d->copy(p_from, p_to);
-}
-
-Error Directory::rename(String p_from, String p_to) {
- ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
- 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()) {
- 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);
- }
-
- ERR_FAIL_COND_V_MSG(!d->file_exists(p_from) && !d->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
- return d->rename(p_from, 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()) {
- Ref<DirAccess> da = DirAccess::create_for_path(p_name);
- return da->remove(p_name);
- }
-
- return d->remove(p_name);
-}
-
-void Directory::_bind_methods() {
- ClassDB::bind_method(D_METHOD("open", "path"), &Directory::open);
- ClassDB::bind_method(D_METHOD("list_dir_begin"), &Directory::list_dir_begin, DEFVAL(false), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_next"), &Directory::get_next);
- ClassDB::bind_method(D_METHOD("current_is_dir"), &Directory::current_is_dir);
- ClassDB::bind_method(D_METHOD("list_dir_end"), &Directory::list_dir_end);
- ClassDB::bind_method(D_METHOD("get_files"), &Directory::get_files);
- ClassDB::bind_method(D_METHOD("get_directories"), &Directory::get_directories);
- ClassDB::bind_method(D_METHOD("get_drive_count"), &Directory::get_drive_count);
- ClassDB::bind_method(D_METHOD("get_drive", "idx"), &Directory::get_drive);
- ClassDB::bind_method(D_METHOD("get_current_drive"), &Directory::get_current_drive);
- ClassDB::bind_method(D_METHOD("change_dir", "todir"), &Directory::change_dir);
- ClassDB::bind_method(D_METHOD("get_current_dir"), &Directory::get_current_dir);
- ClassDB::bind_method(D_METHOD("make_dir", "path"), &Directory::make_dir);
- ClassDB::bind_method(D_METHOD("make_dir_recursive", "path"), &Directory::make_dir_recursive);
- ClassDB::bind_method(D_METHOD("file_exists", "path"), &Directory::file_exists);
- ClassDB::bind_method(D_METHOD("dir_exists", "path"), &Directory::dir_exists);
- ClassDB::bind_method(D_METHOD("get_space_left"), &Directory::get_space_left);
- ClassDB::bind_method(D_METHOD("copy", "from", "to"), &Directory::copy);
- ClassDB::bind_method(D_METHOD("rename", "from", "to"), &Directory::rename);
- ClassDB::bind_method(D_METHOD("remove", "path"), &Directory::remove);
-
- ClassDB::bind_method(D_METHOD("set_include_navigational", "enable"), &Directory::set_include_navigational);
- ClassDB::bind_method(D_METHOD("get_include_navigational"), &Directory::get_include_navigational);
- ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &Directory::set_include_hidden);
- ClassDB::bind_method(D_METHOD("get_include_hidden"), &Directory::get_include_hidden);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_navigational"), "set_include_navigational", "get_include_navigational");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_hidden"), "set_include_hidden", "get_include_hidden");
-}
-
-Directory::Directory() {
- d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
-}
-
////// Marshalls //////
Marshalls *Marshalls::singleton = nullptr;
diff --git a/core/core_bind.h b/core/core_bind.h
index 0f85e473a5..ba22971d78 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -32,9 +32,6 @@
#define CORE_BIND_H
#include "core/debugger/engine_profiler.h"
-#include "core/io/compression.h"
-#include "core/io/dir_access.h"
-#include "core/io/file_access.h"
#include "core/io/image.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
@@ -289,6 +286,7 @@ public:
Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon);
Vector<int> triangulate_delaunay(const Vector<Vector2> &p_points);
Vector<Point2> convex_hull(const Vector<Point2> &p_points);
+ TypedArray<PackedVector2Array> decompose_polygon_in_convex(const Vector<Vector2> &p_polygon);
enum PolyBooleanOperation {
OPERATION_UNION,
@@ -355,156 +353,6 @@ public:
Geometry3D() { singleton = this; }
};
-class File : public RefCounted {
- GDCLASS(File, RefCounted);
-
- Ref<FileAccess> f;
- bool big_endian = false;
-
-protected:
- static void _bind_methods();
-
-public:
- enum ModeFlags {
- READ = 1,
- WRITE = 2,
- READ_WRITE = 3,
- WRITE_READ = 7,
- };
-
- enum CompressionMode {
- COMPRESSION_FASTLZ = Compression::MODE_FASTLZ,
- COMPRESSION_DEFLATE = Compression::MODE_DEFLATE,
- COMPRESSION_ZSTD = Compression::MODE_ZSTD,
- COMPRESSION_GZIP = Compression::MODE_GZIP
- };
-
- Error open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key);
- Error open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass);
- Error open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode = COMPRESSION_FASTLZ);
-
- Error open(const String &p_path, ModeFlags p_mode_flags); // open a file.
- void flush(); // Flush a file (write its buffer to disk).
- void close(); // Close a file.
- bool is_open() const; // True when file is open.
-
- String get_path() const; // Returns the path for the current open file.
- String get_path_absolute() const; // Returns the absolute path for the current open file.
-
- void seek(int64_t p_position); // Seek to a given position.
- void seek_end(int64_t p_position = 0); // Seek from the end of file.
- uint64_t get_position() const; // Get position in the file.
- uint64_t get_length() const; // Get size of the file.
-
- bool eof_reached() const; // Reading passed EOF.
-
- uint8_t get_8() const; // Get a byte.
- uint16_t get_16() const; // Get 16 bits uint.
- uint32_t get_32() const; // Get 32 bits uint.
- uint64_t get_64() const; // Get 64 bits uint.
-
- float get_float() const;
- double get_double() const;
- real_t get_real() const;
-
- Variant get_var(bool p_allow_objects = false) const;
-
- Vector<uint8_t> get_buffer(int64_t p_length) const; // Get an array of bytes.
- String get_line() const;
- Vector<String> get_csv_line(const String &p_delim = ",") const;
- String get_as_text(bool p_skip_cr = false) const;
- String get_md5(const String &p_path) const;
- String get_sha256(const String &p_path) const;
-
- /*
- * Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac).
- * It's not about the current CPU type but file formats.
- * This flag gets reset to `false` (little endian) on each open.
- */
- void set_big_endian(bool p_big_endian);
- bool is_big_endian();
-
- Error get_error() const; // Get last error.
-
- void store_8(uint8_t p_dest); // Store a byte.
- void store_16(uint16_t p_dest); // Store 16 bits uint.
- void store_32(uint32_t p_dest); // Store 32 bits uint.
- void store_64(uint64_t p_dest); // Store 64 bits uint.
-
- void store_float(float p_dest);
- void store_double(double p_dest);
- void store_real(real_t p_real);
-
- void store_string(const String &p_string);
- void store_line(const String &p_string);
- void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
-
- virtual void store_pascal_string(const String &p_string);
- virtual String get_pascal_string();
-
- void store_buffer(const Vector<uint8_t> &p_buffer); // Store an array of bytes.
-
- void store_var(const Variant &p_var, bool p_full_objects = false);
-
- static bool file_exists(const String &p_name); // Return true if a file exists.
-
- uint64_t get_modified_time(const String &p_file) const;
-
- File() {}
-};
-
-class Directory : public RefCounted {
- GDCLASS(Directory, RefCounted);
- Ref<DirAccess> d;
-
- bool dir_open = false;
- bool include_navigational = false;
- bool include_hidden = false;
-
-protected:
- static void _bind_methods();
-
-public:
- Error open(const String &p_path);
-
- bool is_open() const;
-
- Error list_dir_begin();
- String get_next();
- bool current_is_dir() const;
- void list_dir_end();
-
- PackedStringArray get_files();
- PackedStringArray get_directories();
- PackedStringArray _get_contents(bool p_directories);
-
- void set_include_navigational(bool p_enable);
- bool get_include_navigational() const;
- void set_include_hidden(bool p_enable);
- bool get_include_hidden() const;
-
- int get_drive_count();
- String get_drive(int p_drive);
- int get_current_drive();
-
- Error change_dir(String p_dir); // Can be relative or absolute, return false on success.
- String get_current_dir(); // Return current dir location.
-
- Error make_dir(String p_dir);
- Error make_dir_recursive(String p_dir);
-
- bool file_exists(String p_file);
- bool dir_exists(String p_dir);
-
- uint64_t get_space_left();
-
- Error copy(String p_from, String p_to);
- Error rename(String p_from, String p_to);
- Error remove(String p_name);
-
- Directory();
-};
-
class Marshalls : public Object {
GDCLASS(Marshalls, Object);
@@ -738,9 +586,6 @@ VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyBooleanOperation);
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyJoinType);
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyEndType);
-VARIANT_ENUM_CAST(core_bind::File::ModeFlags);
-VARIANT_ENUM_CAST(core_bind::File::CompressionMode);
-
VARIANT_ENUM_CAST(core_bind::Thread::Priority);
#endif // CORE_BIND_H
diff --git a/core/doc_data.h b/core/doc_data.h
index 3b7bf149b4..bb356f027e 100644
--- a/core/doc_data.h
+++ b/core/doc_data.h
@@ -32,7 +32,6 @@
#define DOC_DATA_H
#include "core/io/xml_parser.h"
-#include "core/templates/rb_map.h"
#include "core/variant/variant.h"
struct ScriptMemberInfo {
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 5cf951a93c..e6e0fff266 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -46,6 +46,9 @@ static String get_type_name(const PropertyInfo &p_info) {
return p_info.hint_string + "*";
}
}
+ if (p_info.type == Variant::ARRAY && (p_info.hint == PROPERTY_HINT_ARRAY_TYPE)) {
+ return String("typedarray::") + p_info.hint_string;
+ }
if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM))) {
return String("enum::") + String(p_info.class_name);
}
@@ -215,7 +218,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
Dictionary d2;
d2["name"] = name;
- uint32_t size;
+ uint32_t size = 0;
switch (i) {
case 0:
size = type_size_array[j].size_32_bits_real_float;
@@ -330,7 +333,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
last_type = t;
}
Dictionary d3;
- uint32_t offset;
+ uint32_t offset = 0;
switch (i) {
case 0:
offset = member_offset_array[idx].offset_32_bits_real_float;
@@ -462,7 +465,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
d["indexing_return_type"] = index_type == Variant::NIL ? String("Variant") : Variant::get_type_name(index_type);
}
- d["is_keyed"] = Variant::ValidatedKeyedSetter(type);
+ d["is_keyed"] = Variant::is_keyed(type);
{
//members
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index 6c680e82c9..67dc55bdb7 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -884,7 +884,7 @@ static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const char *p_clas
MethodBind *mb = ClassDB::get_method(StringName(p_classname), StringName(p_methodname));
ERR_FAIL_COND_V(!mb, nullptr);
if (mb->get_hash() != p_hash) {
- ERR_PRINT_ONCE("Hash mismatch for method '" + String(p_classname) + "." + String(p_methodname) + "'.");
+ ERR_PRINT("Hash mismatch for method '" + String(p_classname) + "." + String(p_methodname) + "'.");
return nullptr;
}
// MethodBind *mb = ClassDB::get_method("Node", "get_name");
diff --git a/core/extension/make_wrappers.py b/core/extension/make_wrappers.py
index 862d313fba..1e4634ad2c 100644
--- a/core/extension/make_wrappers.py
+++ b/core/extension/make_wrappers.py
@@ -1,4 +1,60 @@
-proto = """
+proto_mod = """
+#define MODBIND$VER($RETTYPE m_name$ARG) \\
+virtual $RETVAL _##m_name($FUNCARGS) $CONST; \\
+_FORCE_INLINE_ virtual $RETVAL m_name($FUNCARGS) $CONST override { \\
+ $RETX _##m_name($CALLARGS);\\
+}
+"""
+
+
+def generate_mod_version(argcount, const=False, returns=False):
+ s = proto_mod
+ sproto = str(argcount)
+ method_info = ""
+ if returns:
+ sproto += "R"
+ s = s.replace("$RETTYPE", "m_ret, ")
+ s = s.replace("$RETVAL", "m_ret")
+ s = s.replace("$RETX", "return")
+
+ else:
+ s = s.replace("$RETTYPE", "")
+ s = s.replace("$RETVAL", "void")
+ s = s.replace("$RETX", "")
+
+ if const:
+ sproto += "C"
+ s = s.replace("$CONST", "const")
+ else:
+ s = s.replace("$CONST", "")
+
+ s = s.replace("$VER", sproto)
+ argtext = ""
+ funcargs = ""
+ callargs = ""
+
+ for i in range(argcount):
+ if i > 0:
+ funcargs += ", "
+ callargs += ", "
+
+ argtext += ", m_type" + str(i + 1)
+ funcargs += "m_type" + str(i + 1) + " arg" + str(i + 1)
+ callargs += "arg" + str(i + 1)
+
+ if argcount:
+ s = s.replace("$ARG", argtext)
+ s = s.replace("$FUNCARGS", funcargs)
+ s = s.replace("$CALLARGS", callargs)
+ else:
+ s = s.replace("$ARG", "")
+ s = s.replace("$FUNCARGS", funcargs)
+ s = s.replace("$CALLARGS", callargs)
+
+ return s
+
+
+proto_ex = """
#define EXBIND$VER($RETTYPE m_name$ARG) \\
GDVIRTUAL$VER($RETTYPE_##m_name$ARG)\\
virtual $RETVAL m_name($FUNCARGS) $CONST override { \\
@@ -9,8 +65,8 @@ virtual $RETVAL m_name($FUNCARGS) $CONST override { \\
"""
-def generate_version(argcount, const=False, returns=False):
- s = proto
+def generate_ex_version(argcount, const=False, returns=False):
+ s = proto_ex
sproto = str(argcount)
method_info = ""
if returns:
@@ -63,25 +119,28 @@ def generate_version(argcount, const=False, returns=False):
def run(target, source, env):
-
max_versions = 12
txt = """
#ifndef GDEXTENSION_WRAPPERS_GEN_H
#define GDEXTENSION_WRAPPERS_GEN_H
-
-
"""
for i in range(max_versions + 1):
+ txt += "\n/* Extension Wrapper " + str(i) + " Arguments */\n"
+ txt += generate_ex_version(i, False, False)
+ txt += generate_ex_version(i, False, True)
+ txt += generate_ex_version(i, True, False)
+ txt += generate_ex_version(i, True, True)
- txt += "/* " + str(i) + " Arguments */\n\n"
- txt += generate_version(i, False, False)
- txt += generate_version(i, False, True)
- txt += generate_version(i, True, False)
- txt += generate_version(i, True, True)
+ for i in range(max_versions + 1):
+ txt += "\n/* Module Wrapper " + str(i) + " Arguments */\n"
+ txt += generate_mod_version(i, False, False)
+ txt += generate_mod_version(i, False, True)
+ txt += generate_mod_version(i, True, False)
+ txt += generate_mod_version(i, True, True)
- txt += "#endif"
+ txt += "\n#endif\n"
with open(target[0], "w") as f:
f.write(txt)
diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt
index 5ae3b2c799..774d1be6b5 100644
--- a/core/input/gamecontrollerdb.txt
+++ b/core/input/gamecontrollerdb.txt
@@ -21,6 +21,7 @@
03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000151000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
@@ -68,6 +69,7 @@
03000000c82d00000121000000000000,8BitDo SN30 Pro for Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,paddle1:b23,paddle2:b19,platform:Windows,
03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
@@ -367,6 +369,7 @@
030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,
+03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
@@ -439,6 +442,7 @@
03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000006f0e00008501000000000000,PDP Fightpad Pro,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Windows,
030000006f0e00000901000000000000,PDP Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows,
03000000e30500009605000000000000,PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000632500002306000000000000,PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
@@ -463,6 +467,7 @@
03000000666600006706000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000151a00006222000000000000,PS2 Dual Plus Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000120a00000100000000000000,PS3 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -735,11 +740,14 @@
03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000450c00002043000000000000,Xeox SL6556BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000006f0e00000300000000000000,XGear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
-03000000172700004431000000000000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000172700004431000000000000,Xiaomi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000bc2000005060000000000000,Xiaomi XMGP01YM,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,-lefty:-a1,+lefty:+a2,rightx:a3,-righty:-a4,+righty:+a5,lefttrigger:b8,righttrigger:b9,platform:Windows,
+03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Windows,
03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows,
03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000120c00000500000000000000,Zeroplus Adapter,a:b2,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
# Mac OS X
@@ -1045,11 +1053,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
03000000050b00000579000011010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b36,paddle1:b52,paddle2:b53,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b21,paddle1:b22,paddle2:b23,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-03000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,
-03000000503200000110000011010000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,
-05000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,
-05000000503200000110000044010000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,
-05000000503200000110000046010000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,
+03000000503200000110000000000000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
+03000000503200000110000011010000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
+05000000503200000110000000000000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
+05000000503200000110000044010000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
+05000000503200000110000046010000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
03000000503200000210000000000000,Atari Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux,
03000000503200000210000011010000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
05000000503200000210000000000000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 596b704732..712fc68c93 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -1325,7 +1325,7 @@ bool InputEventAction::is_match(const Ref<InputEvent> &p_event, bool p_exact_mat
return false;
}
- return p_event->is_action(action);
+ return p_event->is_action(action, p_exact_match);
}
bool InputEventAction::is_action(const StringName &p_action) const {
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
index bed41b8d89..79e7fa16e3 100644
--- a/core/io/dir_access.cpp
+++ b/core/io/dir_access.cpp
@@ -36,6 +36,8 @@
#include "core/os/os.h"
#include "core/templates/local_vector.h"
+thread_local Error DirAccess::last_dir_open_error = OK;
+
String DirAccess::_get_root_path() const {
switch (_access_type) {
case ACCESS_RESOURCES:
@@ -249,6 +251,61 @@ Ref<DirAccess> DirAccess::open(const String &p_path, Error *r_error) {
return da;
}
+Ref<DirAccess> DirAccess::_open(const String &p_path) {
+ Error err = OK;
+ Ref<DirAccess> da = open(p_path, &err);
+ last_dir_open_error = err;
+ if (err) {
+ return Ref<DirAccess>();
+ }
+ return da;
+}
+
+int DirAccess::_get_drive_count() {
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ return d->get_drive_count();
+}
+
+String DirAccess::get_drive_name(int p_idx) {
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ return d->get_drive(p_idx);
+}
+
+Error DirAccess::make_dir_absolute(const String &p_dir) {
+ Ref<DirAccess> d = DirAccess::create_for_path(p_dir);
+ return d->make_dir(p_dir);
+}
+
+Error DirAccess::make_dir_recursive_absolute(const String &p_dir) {
+ Ref<DirAccess> d = DirAccess::create_for_path(p_dir);
+ return d->make_dir_recursive(p_dir);
+}
+
+bool DirAccess::dir_exists_absolute(const String &p_dir) {
+ Ref<DirAccess> d = DirAccess::create_for_path(p_dir);
+ return d->dir_exists(p_dir);
+}
+
+Error DirAccess::copy_absolute(const String &p_from, const String &p_to, int p_chmod_flags) {
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ // Support copying from res:// to user:// etc.
+ String from = ProjectSettings::get_singleton()->globalize_path(p_from);
+ String to = ProjectSettings::get_singleton()->globalize_path(p_to);
+ return d->copy(from, to, p_chmod_flags);
+}
+
+Error DirAccess::rename_absolute(const String &p_from, const String &p_to) {
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ String from = ProjectSettings::get_singleton()->globalize_path(p_from);
+ String to = ProjectSettings::get_singleton()->globalize_path(p_to);
+ return d->rename(from, to);
+}
+
+Error DirAccess::remove_absolute(const String &p_path) {
+ Ref<DirAccess> d = DirAccess::create_for_path(p_path);
+ return d->remove(p_path);
+}
+
Ref<DirAccess> DirAccess::create(AccessType p_access) {
Ref<DirAccess> da = create_func[p_access] ? create_func[p_access]() : nullptr;
if (da.is_valid()) {
@@ -266,6 +323,10 @@ Ref<DirAccess> DirAccess::create(AccessType p_access) {
return da;
}
+Error DirAccess::get_open_error() {
+ return last_dir_open_error;
+}
+
String DirAccess::get_full_path(const String &p_path, AccessType p_access) {
Ref<DirAccess> d = DirAccess::create(p_access);
if (d.is_null()) {
@@ -424,3 +485,104 @@ bool DirAccess::exists(String p_dir) {
Ref<DirAccess> da = DirAccess::create_for_path(p_dir);
return da->change_dir(p_dir) == OK;
}
+
+PackedStringArray DirAccess::get_files() {
+ return _get_contents(false);
+}
+
+PackedStringArray DirAccess::get_files_at(const String &p_path) {
+ Ref<DirAccess> da = DirAccess::open(p_path);
+ ERR_FAIL_COND_V_MSG(da.is_null(), PackedStringArray(), vformat("Couldn't open directory at path \"%s\".", p_path));
+ return da->get_files();
+}
+
+PackedStringArray DirAccess::get_directories() {
+ return _get_contents(true);
+}
+
+PackedStringArray DirAccess::get_directories_at(const String &p_path) {
+ Ref<DirAccess> da = DirAccess::open(p_path);
+ ERR_FAIL_COND_V_MSG(da.is_null(), PackedStringArray(), vformat("Couldn't open directory at path \"%s\".", p_path));
+ return da->get_directories();
+}
+
+PackedStringArray DirAccess::_get_contents(bool p_directories) {
+ PackedStringArray ret;
+
+ list_dir_begin();
+ String s = _get_next();
+ while (!s.is_empty()) {
+ if (current_is_dir() == p_directories) {
+ ret.append(s);
+ }
+ s = _get_next();
+ }
+
+ ret.sort();
+ return ret;
+}
+
+String DirAccess::_get_next() {
+ String next = get_next();
+ while (!next.is_empty() && ((!include_navigational && (next == "." || next == "..")) || (!include_hidden && current_is_hidden()))) {
+ next = get_next();
+ }
+ return next;
+}
+
+void DirAccess::set_include_navigational(bool p_enable) {
+ include_navigational = p_enable;
+}
+
+bool DirAccess::get_include_navigational() const {
+ return include_navigational;
+}
+
+void DirAccess::set_include_hidden(bool p_enable) {
+ include_hidden = p_enable;
+}
+
+bool DirAccess::get_include_hidden() const {
+ return include_hidden;
+}
+
+void DirAccess::_bind_methods() {
+ ClassDB::bind_static_method("DirAccess", D_METHOD("open", "path"), &DirAccess::_open);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("get_open_error"), &DirAccess::get_open_error);
+
+ ClassDB::bind_method(D_METHOD("list_dir_begin"), &DirAccess::list_dir_begin, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_next"), &DirAccess::_get_next);
+ ClassDB::bind_method(D_METHOD("current_is_dir"), &DirAccess::current_is_dir);
+ ClassDB::bind_method(D_METHOD("list_dir_end"), &DirAccess::list_dir_end);
+ ClassDB::bind_method(D_METHOD("get_files"), &DirAccess::get_files);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("get_files_at", "path"), &DirAccess::get_files_at);
+ ClassDB::bind_method(D_METHOD("get_directories"), &DirAccess::get_directories);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("get_directories_at", "path"), &DirAccess::get_directories_at);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("get_drive_count"), &DirAccess::_get_drive_count);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("get_drive_name", "idx"), &DirAccess::get_drive_name);
+ ClassDB::bind_method(D_METHOD("get_current_drive"), &DirAccess::get_current_drive);
+ ClassDB::bind_method(D_METHOD("change_dir", "to_dir"), &DirAccess::change_dir);
+ ClassDB::bind_method(D_METHOD("get_current_dir", "include_drive"), &DirAccess::get_current_dir, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("make_dir", "path"), &DirAccess::make_dir);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("make_dir_absolute", "path"), &DirAccess::make_dir_absolute);
+ ClassDB::bind_method(D_METHOD("make_dir_recursive", "path"), &DirAccess::make_dir_recursive);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("make_dir_recursive_absolute", "path"), &DirAccess::make_dir_recursive_absolute);
+ ClassDB::bind_method(D_METHOD("file_exists", "path"), &DirAccess::file_exists);
+ ClassDB::bind_method(D_METHOD("dir_exists", "path"), &DirAccess::dir_exists);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("dir_exists_absolute", "path"), &DirAccess::dir_exists_absolute);
+ ClassDB::bind_method(D_METHOD("get_space_left"), &DirAccess::get_space_left);
+ ClassDB::bind_method(D_METHOD("copy", "from", "to", "chmod_flags"), &DirAccess::copy, DEFVAL(-1));
+ ClassDB::bind_static_method("DirAccess", D_METHOD("copy_absolute", "from", "to", "chmod_flags"), &DirAccess::copy_absolute, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("rename", "from", "to"), &DirAccess::rename);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("rename_absolute", "from", "to"), &DirAccess::rename_absolute);
+ ClassDB::bind_method(D_METHOD("remove", "path"), &DirAccess::remove);
+ ClassDB::bind_static_method("DirAccess", D_METHOD("remove_absolute", "path"), &DirAccess::remove_absolute);
+
+ ClassDB::bind_method(D_METHOD("set_include_navigational", "enable"), &DirAccess::set_include_navigational);
+ ClassDB::bind_method(D_METHOD("get_include_navigational"), &DirAccess::get_include_navigational);
+ ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &DirAccess::set_include_hidden);
+ ClassDB::bind_method(D_METHOD("get_include_hidden"), &DirAccess::get_include_hidden);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_navigational"), "set_include_navigational", "get_include_navigational");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_hidden"), "set_include_hidden", "get_include_hidden");
+}
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
index 2469c2a080..bd24214e73 100644
--- a/core/io/dir_access.h
+++ b/core/io/dir_access.h
@@ -37,6 +37,8 @@
//@ TODO, excellent candidate for THREAD_SAFE MACRO, should go through all these and add THREAD_SAFE where it applies
class DirAccess : public RefCounted {
+ GDCLASS(DirAccess, RefCounted);
+
public:
enum AccessType {
ACCESS_RESOURCES,
@@ -50,10 +52,18 @@ public:
private:
AccessType _access_type = ACCESS_FILESYSTEM;
static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
+ static Ref<DirAccess> _open(const String &p_path);
Error _copy_dir(Ref<DirAccess> &p_target_da, String p_to, int p_chmod_flags, bool p_copy_links);
+ PackedStringArray _get_contents(bool p_directories);
+
+ thread_local static Error last_dir_open_error;
+ bool include_navigational = false;
+ bool include_hidden = false;
protected:
+ static void _bind_methods();
+
String _get_root_path() const;
virtual String _get_root_string() const;
@@ -118,6 +128,7 @@ public:
static Ref<DirAccess> create_for_path(const String &p_path);
static Ref<DirAccess> create(AccessType p_access);
+ static Error get_open_error();
template <class T>
static void make_default(AccessType p_access) {
@@ -126,6 +137,28 @@ public:
static Ref<DirAccess> open(const String &p_path, Error *r_error = nullptr);
+ static int _get_drive_count();
+ static String get_drive_name(int p_idx);
+
+ static Error make_dir_absolute(const String &p_dir);
+ static Error make_dir_recursive_absolute(const String &p_dir);
+ static bool dir_exists_absolute(const String &p_dir);
+
+ static Error copy_absolute(const String &p_from, const String &p_to, int p_chmod_flags = -1);
+ static Error rename_absolute(const String &p_from, const String &p_to);
+ static Error remove_absolute(const String &p_path);
+
+ PackedStringArray get_files();
+ static PackedStringArray get_files_at(const String &p_path);
+ PackedStringArray get_directories();
+ static PackedStringArray get_directories_at(const String &p_path);
+ String _get_next();
+
+ void set_include_navigational(bool p_enable);
+ bool get_include_navigational() const;
+ void set_include_hidden(bool p_enable);
+ bool get_include_hidden() const;
+
DirAccess() {}
virtual ~DirAccess() {}
};
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index 72c00bd678..499f083f51 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -32,6 +32,8 @@
#include "core/config/project_settings.h"
#include "core/crypto/crypto_core.h"
+#include "core/io/file_access_compressed.h"
+#include "core/io/file_access_encrypted.h"
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
@@ -41,6 +43,7 @@ FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = { nullptr, nullptr
FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr;
bool FileAccess::backup_save = false;
+thread_local Error FileAccess::last_file_open_error = OK;
Ref<FileAccess> FileAccess::create(AccessType p_access) {
ERR_FAIL_INDEX_V(p_access, ACCESS_MAX, nullptr);
@@ -81,7 +84,7 @@ Ref<FileAccess> FileAccess::create_for_path(const String &p_path) {
}
Error FileAccess::reopen(const String &p_path, int p_mode_flags) {
- return _open(p_path, p_mode_flags);
+ return open_internal(p_path, p_mode_flags);
}
Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
@@ -99,7 +102,7 @@ Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error *
}
ret = create_for_path(p_path);
- Error err = ret->_open(p_path, p_mode_flags);
+ Error err = ret->open_internal(p_path, p_mode_flags);
if (r_error) {
*r_error = err;
@@ -111,6 +114,66 @@ Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error *
return ret;
}
+Ref<FileAccess> FileAccess::_open(const String &p_path, ModeFlags p_mode_flags) {
+ Error err = OK;
+ Ref<FileAccess> fa = open(p_path, p_mode_flags, &err);
+ last_file_open_error = err;
+ if (err) {
+ return Ref<FileAccess>();
+ }
+ return fa;
+}
+
+Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) {
+ Ref<FileAccess> fa = _open(p_path, p_mode_flags);
+ if (fa.is_null()) {
+ return fa;
+ }
+
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
+ Error err = fae->open_and_parse(fa, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ);
+ if (err) {
+ last_file_open_error = err;
+ return Ref<FileAccess>();
+ }
+ return fae;
+}
+
+Ref<FileAccess> FileAccess::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass) {
+ Ref<FileAccess> fa = _open(p_path, p_mode_flags);
+ if (fa.is_null()) {
+ return fa;
+ }
+
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
+ Error err = fae->open_and_parse_password(fa, p_pass, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ);
+ if (err) {
+ last_file_open_error = err;
+ return Ref<FileAccess>();
+ }
+ return fae;
+}
+
+Ref<FileAccess> FileAccess::open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode) {
+ Ref<FileAccessCompressed> fac;
+ fac.instantiate();
+ fac->configure("GCPF", (Compression::Mode)p_compress_mode);
+ Error err = fac->open_internal(p_path, p_mode_flags);
+
+ if (err) {
+ last_file_open_error = err;
+ return Ref<FileAccess>();
+ }
+
+ return fac;
+}
+
+Error FileAccess::get_open_error() {
+ return last_file_open_error;
+}
+
FileAccess::CreateFunc FileAccess::get_create_func(AccessType p_access) {
return create_func[p_access];
}
@@ -227,6 +290,20 @@ real_t FileAccess::get_real() const {
}
}
+Variant FileAccess::get_var(bool p_allow_objects) const {
+ uint32_t len = get_32();
+ Vector<uint8_t> buff = _get_buffer(len);
+ ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant());
+
+ const uint8_t *r = buff.ptr();
+
+ Variant v;
+ Error err = decode_variant(v, &r[0], len, nullptr, p_allow_objects);
+ ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to encode Variant.");
+
+ return v;
+}
+
double FileAccess::get_double() const {
MarshallDouble m;
m.l = get_64();
@@ -370,6 +447,17 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
return strings;
}
+String FileAccess::get_as_text(bool p_skip_cr) const {
+ uint64_t original_pos = get_position();
+ const_cast<FileAccess *>(this)->seek(0);
+
+ String text = get_as_utf8_string(p_skip_cr);
+
+ const_cast<FileAccess *>(this)->seek(original_pos);
+
+ return text;
+}
+
uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
@@ -381,6 +469,27 @@ uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
return i;
}
+Vector<uint8_t> FileAccess::_get_buffer(int64_t p_length) const {
+ Vector<uint8_t> data;
+
+ ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0.");
+ if (p_length == 0) {
+ return data;
+ }
+
+ Error err = data.resize(p_length);
+ ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements.");
+
+ uint8_t *w = data.ptrw();
+ int64_t len = get_buffer(&w[0], p_length);
+
+ if (len < p_length) {
+ data.resize(len);
+ }
+
+ return data;
+}
+
String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
Vector<uint8_t> sourcef;
uint64_t len = get_length();
@@ -554,6 +663,33 @@ void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
}
}
+void FileAccess::_store_buffer(const Vector<uint8_t> &p_buffer) {
+ uint64_t len = p_buffer.size();
+ if (len == 0) {
+ return;
+ }
+
+ const uint8_t *r = p_buffer.ptr();
+
+ store_buffer(&r[0], len);
+}
+
+void FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
+ 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.");
+
+ Vector<uint8_t> buff;
+ buff.resize(len);
+
+ uint8_t *w = buff.ptrw();
+ err = encode_variant(p_var, &w[0], len, p_full_objects);
+ ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
+
+ store_32(len);
+ _store_buffer(buff);
+}
+
Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) {
Ref<FileAccess> f = FileAccess::open(p_path, READ, r_error);
if (f.is_null()) {
@@ -666,3 +802,69 @@ String FileAccess::get_sha256(const String &p_file) {
return String::hex_encode_buffer(hash, 32);
}
+
+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);
+ ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted_with_pass", "path", "mode_flags", "pass"), &FileAccess::open_encrypted_pass);
+ ClassDB::bind_static_method("FileAccess", D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &FileAccess::open_compressed, DEFVAL(0));
+ ClassDB::bind_static_method("FileAccess", D_METHOD("get_open_error"), &FileAccess::get_open_error);
+
+ ClassDB::bind_method(D_METHOD("flush"), &FileAccess::flush);
+ ClassDB::bind_method(D_METHOD("get_path"), &FileAccess::get_path);
+ ClassDB::bind_method(D_METHOD("get_path_absolute"), &FileAccess::get_path_absolute);
+ ClassDB::bind_method(D_METHOD("is_open"), &FileAccess::is_open);
+ ClassDB::bind_method(D_METHOD("seek", "position"), &FileAccess::seek);
+ ClassDB::bind_method(D_METHOD("seek_end", "position"), &FileAccess::seek_end, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_position"), &FileAccess::get_position);
+ ClassDB::bind_method(D_METHOD("get_length"), &FileAccess::get_length);
+ ClassDB::bind_method(D_METHOD("eof_reached"), &FileAccess::eof_reached);
+ ClassDB::bind_method(D_METHOD("get_8"), &FileAccess::get_8);
+ ClassDB::bind_method(D_METHOD("get_16"), &FileAccess::get_16);
+ ClassDB::bind_method(D_METHOD("get_32"), &FileAccess::get_32);
+ ClassDB::bind_method(D_METHOD("get_64"), &FileAccess::get_64);
+ ClassDB::bind_method(D_METHOD("get_float"), &FileAccess::get_float);
+ ClassDB::bind_method(D_METHOD("get_double"), &FileAccess::get_double);
+ ClassDB::bind_method(D_METHOD("get_real"), &FileAccess::get_real);
+ ClassDB::bind_method(D_METHOD("get_buffer", "length"), &FileAccess::_get_buffer);
+ ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line);
+ ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(","));
+ ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text, DEFVAL(false));
+ ClassDB::bind_static_method("FileAccess", D_METHOD("get_md5", "path"), &FileAccess::get_md5);
+ ClassDB::bind_static_method("FileAccess", D_METHOD("get_sha256", "path"), &FileAccess::get_sha256);
+ ClassDB::bind_method(D_METHOD("is_big_endian"), &FileAccess::is_big_endian);
+ ClassDB::bind_method(D_METHOD("set_big_endian", "big_endian"), &FileAccess::set_big_endian);
+ ClassDB::bind_method(D_METHOD("get_error"), &FileAccess::get_error);
+ ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &FileAccess::get_var, DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("store_8", "value"), &FileAccess::store_8);
+ ClassDB::bind_method(D_METHOD("store_16", "value"), &FileAccess::store_16);
+ ClassDB::bind_method(D_METHOD("store_32", "value"), &FileAccess::store_32);
+ ClassDB::bind_method(D_METHOD("store_64", "value"), &FileAccess::store_64);
+ ClassDB::bind_method(D_METHOD("store_float", "value"), &FileAccess::store_float);
+ ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double);
+ ClassDB::bind_method(D_METHOD("store_real", "value"), &FileAccess::store_real);
+ ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &FileAccess::_store_buffer);
+ ClassDB::bind_method(D_METHOD("store_line", "line"), &FileAccess::store_line);
+ ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &FileAccess::store_csv_line, DEFVAL(","));
+ ClassDB::bind_method(D_METHOD("store_string", "string"), &FileAccess::store_string);
+ ClassDB::bind_method(D_METHOD("store_var", "value", "full_objects"), &FileAccess::store_var, DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string);
+ ClassDB::bind_method(D_METHOD("get_pascal_string"), &FileAccess::get_pascal_string);
+
+ ClassDB::bind_static_method("FileAccess", D_METHOD("file_exists", "path"), &FileAccess::exists);
+ ClassDB::bind_static_method("FileAccess", D_METHOD("get_modified_time", "file"), &FileAccess::get_modified_time);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian");
+
+ BIND_ENUM_CONSTANT(READ);
+ BIND_ENUM_CONSTANT(WRITE);
+ BIND_ENUM_CONSTANT(READ_WRITE);
+ BIND_ENUM_CONSTANT(WRITE_READ);
+
+ BIND_ENUM_CONSTANT(COMPRESSION_FASTLZ);
+ BIND_ENUM_CONSTANT(COMPRESSION_DEFLATE);
+ BIND_ENUM_CONSTANT(COMPRESSION_ZSTD);
+ BIND_ENUM_CONSTANT(COMPRESSION_GZIP);
+}
diff --git a/core/io/file_access.h b/core/io/file_access.h
index fc0eb95d44..8ca44306a0 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -31,6 +31,7 @@
#ifndef FILE_ACCESS_H
#define FILE_ACCESS_H
+#include "core/io/compression.h"
#include "core/math/math_defs.h"
#include "core/object/ref_counted.h"
#include "core/os/memory.h"
@@ -42,6 +43,8 @@
*/
class FileAccess : public RefCounted {
+ GDCLASS(FileAccess, RefCounted);
+
public:
enum AccessType {
ACCESS_RESOURCES,
@@ -50,6 +53,20 @@ public:
ACCESS_MAX
};
+ enum ModeFlags {
+ READ = 1,
+ WRITE = 2,
+ READ_WRITE = 3,
+ WRITE_READ = 7,
+ };
+
+ enum CompressionMode {
+ COMPRESSION_FASTLZ = Compression::MODE_FASTLZ,
+ COMPRESSION_DEFLATE = Compression::MODE_DEFLATE,
+ COMPRESSION_ZSTD = Compression::MODE_ZSTD,
+ COMPRESSION_GZIP = Compression::MODE_GZIP
+ };
+
typedef void (*FileCloseFailNotify)(const String &);
typedef Ref<FileAccess> (*CreateFunc)();
@@ -60,15 +77,19 @@ public:
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) = 0;
protected:
+ static void _bind_methods();
+
AccessType get_access_type() const;
String fix_path(const String &p_path) const;
- virtual Error _open(const String &p_path, int p_mode_flags) = 0; ///< open a file
+ virtual Error open_internal(const String &p_path, int p_mode_flags) = 0; ///< open a file
virtual uint64_t _get_modified_time(const String &p_file) = 0;
+ virtual void _set_access_type(AccessType p_access);
static FileCloseFailNotify close_fail_notify;
private:
static bool backup_save;
+ thread_local static Error last_file_open_error;
AccessType _access_type = ACCESS_FILESYSTEM;
static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */
@@ -77,18 +98,11 @@ private:
return memnew(T);
}
+ static Ref<FileAccess> _open(const String &p_path, ModeFlags p_mode_flags);
+
public:
static void set_file_close_fail_notify_callback(FileCloseFailNotify p_cbk) { close_fail_notify = p_cbk; }
- virtual void _set_access_type(AccessType p_access);
-
- enum ModeFlags {
- READ = 1,
- WRITE = 2,
- READ_WRITE = 3,
- WRITE_READ = 7,
- };
-
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
@@ -110,10 +124,14 @@ public:
virtual double get_double() const;
virtual real_t get_real() const;
+ Variant get_var(bool p_allow_objects = false) const;
+
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes
+ Vector<uint8_t> _get_buffer(int64_t p_length) const;
virtual String get_line() const;
virtual String get_token() const;
virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
+ String get_as_text(bool p_skip_cr = false) const;
virtual String get_as_utf8_string(bool p_skip_cr = false) const;
/**
@@ -144,6 +162,9 @@ public:
virtual String get_pascal_string();
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
+ void _store_buffer(const Vector<uint8_t> &p_buffer);
+
+ void store_var(const Variant &p_var, bool p_full_objects = false);
virtual bool file_exists(const String &p_name) = 0; ///< return true if a file exists
@@ -152,6 +173,12 @@ public:
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 Ref<FileAccess> open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key);
+ static Ref<FileAccess> open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass);
+ static Ref<FileAccess> open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode = COMPRESSION_FASTLZ);
+ static Error get_open_error();
+
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);
@@ -177,4 +204,7 @@ public:
virtual ~FileAccess() {}
};
+VARIANT_ENUM_CAST(FileAccess::CompressionMode);
+VARIANT_ENUM_CAST(FileAccess::ModeFlags);
+
#endif // FILE_ACCESS_H
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 1d0a718166..d2c8a88269 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -95,7 +95,7 @@ Error FileAccessCompressed::open_after_magic(Ref<FileAccess> p_base) {
return ret == -1 ? ERR_FILE_CORRUPT : OK;
}
-Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
+Error FileAccessCompressed::open_internal(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(p_mode_flags == READ_WRITE, ERR_UNAVAILABLE);
_close();
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index e41491a92c..ee114c2c65 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -70,7 +70,7 @@ public:
Error open_after_magic(Ref<FileAccess> p_base);
- virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file
+ virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file
virtual bool is_open() const override; ///< true when file is open
virtual void seek(uint64_t p_position) override; ///< seek to a given position
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index d1b014a0be..be502dacd9 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -111,7 +111,7 @@ Error FileAccessEncrypted::open_and_parse_password(Ref<FileAccess> p_base, const
return open_and_parse(p_base, key, p_mode);
}
-Error FileAccessEncrypted::_open(const String &p_path, int p_mode_flags) {
+Error FileAccessEncrypted::open_internal(const String &p_path, int p_mode_flags) {
return OK;
}
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index 6200f87a7a..6b4588841d 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -60,7 +60,7 @@ public:
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) override; ///< open a file
+ virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file
virtual bool is_open() const override; ///< true when file is open
virtual String get_path() const override; /// 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 499d001234..21ded4247f 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -78,7 +78,7 @@ Error FileAccessMemory::open_custom(const uint8_t *p_data, uint64_t p_len) {
return OK;
}
-Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) {
+Error FileAccessMemory::open_internal(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND);
String name = fix_path(p_path);
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index f2bd2aa832..b1f408eb98 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -45,7 +45,7 @@ public:
static void cleanup();
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) override; ///< open a file
+ virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file
virtual bool is_open() const override; ///< true when file is open
virtual void seek(uint64_t p_position) override; ///< seek to a given position
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 1365b4b593..13730518bf 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -252,7 +252,7 @@ void FileAccessNetwork::_respond(uint64_t p_len, Error p_status) {
pages.resize(pc);
}
-Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) {
+Error FileAccessNetwork::open_internal(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(p_mode_flags != READ, ERR_UNAVAILABLE);
_close();
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index ceadc715a1..ee92d3b9db 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -132,7 +132,7 @@ public:
RESPONSE_GET_MODTIME,
};
- virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file
+ virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file
virtual bool is_open() const override; ///< true when file is open
virtual void seek(uint64_t p_position) override; ///< seek to a given position
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index adae0db0f4..dfcce30ab5 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -259,7 +259,7 @@ Ref<FileAccess> PackedSourcePCK::get_file(const String &p_path, PackedData::Pack
//////////////////////////////////////////////////////////////////
-Error FileAccessPack::_open(const String &p_path, int p_mode_flags) {
+Error FileAccessPack::open_internal(const String &p_path, int p_mode_flags) {
ERR_FAIL_V(ERR_UNAVAILABLE);
return ERR_UNAVAILABLE;
}
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 023758ac0f..4b9b49a161 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -148,7 +148,7 @@ class FileAccessPack : public FileAccess {
uint64_t off;
Ref<FileAccess> f;
- virtual Error _open(const String &p_path, int p_mode_flags) override;
+ virtual Error open_internal(const String &p_path, int p_mode_flags) override;
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index 17f2335a8e..72503851c1 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -234,7 +234,7 @@ ZipArchive::~ZipArchive() {
packages.clear();
}
-Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
+Error FileAccessZip::open_internal(const String &p_path, int p_mode_flags) {
_close();
ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED);
@@ -337,7 +337,7 @@ bool FileAccessZip::file_exists(const String &p_name) {
}
FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) {
- _open(p_path, FileAccess::READ);
+ open_internal(p_path, FileAccess::READ);
}
FileAccessZip::~FileAccessZip() {
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 74a48192f3..6d61b9a291 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -85,7 +85,7 @@ class FileAccessZip : public FileAccess {
void _close();
public:
- virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file
+ virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file
virtual bool is_open() const override; ///< true when file is open
virtual void seek(uint64_t p_position) override; ///< seek to a given position
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index d09697b951..d6854666c0 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -32,6 +32,12 @@
#include "core/string/print_string.h"
+void ImageFormatLoader::_bind_methods() {
+ BIND_BITFIELD_FLAG(FLAG_NONE);
+ BIND_BITFIELD_FLAG(FLAG_FORCE_LINEAR);
+ BIND_BITFIELD_FLAG(FLAG_CONVERT_COLORS);
+}
+
bool ImageFormatLoader::recognize(const String &p_extension) const {
List<String> extensions;
get_recognized_extensions(&extensions);
@@ -44,7 +50,39 @@ bool ImageFormatLoader::recognize(const String &p_extension) const {
return false;
}
-Error ImageLoader::load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom, uint32_t p_flags, float p_scale) {
+Error ImageFormatLoaderExtension::load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, BitField<ImageFormatLoader::LoaderFlags> p_flags, float p_scale) {
+ Error err;
+ if (GDVIRTUAL_CALL(_load_image, p_image, p_fileaccess, p_flags, p_scale, err)) {
+ return err;
+ }
+ return ERR_UNAVAILABLE;
+}
+
+void ImageFormatLoaderExtension::get_recognized_extensions(List<String> *p_extension) const {
+ PackedStringArray ext;
+ if (GDVIRTUAL_CALL(_get_recognized_extensions, ext)) {
+ for (int i = 0; i < ext.size(); i++) {
+ p_extension->push_back(ext[i]);
+ }
+ }
+}
+
+void ImageFormatLoaderExtension::add_format_loader() {
+ ImageLoader::add_image_format_loader(this);
+}
+
+void ImageFormatLoaderExtension::remove_format_loader() {
+ ImageLoader::remove_image_format_loader(this);
+}
+
+void ImageFormatLoaderExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_recognized_extensions);
+ GDVIRTUAL_BIND(_load_image, "image", "fileaccess", "flags", "scale");
+ ClassDB::bind_method(D_METHOD("add_format_loader"), &ImageFormatLoaderExtension::add_format_loader);
+ ClassDB::bind_method(D_METHOD("remove_format_loader"), &ImageFormatLoaderExtension::remove_format_loader);
+}
+
+Error ImageLoader::load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom, BitField<ImageFormatLoader::LoaderFlags> p_flags, 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.");
Ref<FileAccess> f = p_custom;
@@ -60,7 +98,7 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, Ref<FileAccess>
if (!loader[i]->recognize(extension)) {
continue;
}
- Error err = loader[i]->load_image(p_image, f, p_flags, p_scale);
+ Error err = loader.write[i]->load_image(p_image, f, p_flags, p_scale);
if (err != OK) {
ERR_PRINT("Error loading image: " + p_file);
}
@@ -79,7 +117,7 @@ void ImageLoader::get_recognized_extensions(List<String> *p_extensions) {
}
}
-ImageFormatLoader *ImageLoader::recognize(const String &p_extension) {
+Ref<ImageFormatLoader> ImageLoader::recognize(const String &p_extension) {
for (int i = 0; i < loader.size(); i++) {
if (loader[i]->recognize(p_extension)) {
return loader[i];
@@ -89,17 +127,17 @@ ImageFormatLoader *ImageLoader::recognize(const String &p_extension) {
return nullptr;
}
-Vector<ImageFormatLoader *> ImageLoader::loader;
+Vector<Ref<ImageFormatLoader>> ImageLoader::loader;
-void ImageLoader::add_image_format_loader(ImageFormatLoader *p_loader) {
+void ImageLoader::add_image_format_loader(Ref<ImageFormatLoader> p_loader) {
loader.push_back(p_loader);
}
-void ImageLoader::remove_image_format_loader(ImageFormatLoader *p_loader) {
+void ImageLoader::remove_image_format_loader(Ref<ImageFormatLoader> p_loader) {
loader.erase(p_loader);
}
-const Vector<ImageFormatLoader *> &ImageLoader::get_image_format_loaders() {
+const Vector<Ref<ImageFormatLoader>> &ImageLoader::get_image_format_loaders() {
return loader;
}
@@ -152,7 +190,7 @@ Ref<Resource> ResourceFormatLoaderImage::load(const String &p_path, const String
Ref<Image> image;
image.instantiate();
- Error err = ImageLoader::loader[idx]->load_image(image, f);
+ Error err = ImageLoader::loader.write[idx]->load_image(image, f);
if (err != OK) {
if (r_error) {
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index bf78005e40..f70fdf22aa 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -31,23 +31,23 @@
#ifndef IMAGE_LOADER_H
#define IMAGE_LOADER_H
+#include "core/core_bind.h"
#include "core/io/file_access.h"
#include "core/io/image.h"
#include "core/io/resource_loader.h"
+#include "core/object/gdvirtual.gen.inc"
#include "core/string/ustring.h"
#include "core/templates/list.h"
+#include "core/variant/binder_common.h"
class ImageLoader;
-class ImageFormatLoader {
+class ImageFormatLoader : public RefCounted {
+ GDCLASS(ImageFormatLoader, RefCounted);
+
friend class ImageLoader;
friend class ResourceFormatLoaderImage;
-protected:
- virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, uint32_t p_flags = (uint32_t)FLAG_NONE, float p_scale = 1.0) = 0;
- virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
- bool recognize(const String &p_extension) const;
-
public:
enum LoaderFlags {
FLAG_NONE = 0,
@@ -55,23 +55,50 @@ public:
FLAG_CONVERT_COLORS = 2,
};
+protected:
+ static void _bind_methods();
+
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, BitField<ImageFormatLoader::LoaderFlags> p_flags = FLAG_NONE, float p_scale = 1.0) = 0;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
+ bool recognize(const String &p_extension) const;
+
+public:
virtual ~ImageFormatLoader() {}
};
+VARIANT_BITFIELD_CAST(ImageFormatLoader::LoaderFlags);
+
+class ImageFormatLoaderExtension : public ImageFormatLoader {
+ GDCLASS(ImageFormatLoaderExtension, ImageFormatLoader);
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, BitField<ImageFormatLoader::LoaderFlags> p_flags = FLAG_NONE, float p_scale = 1.0) override;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const override;
+
+ void add_format_loader();
+ void remove_format_loader();
+
+ GDVIRTUAL0RC(PackedStringArray, _get_recognized_extensions);
+ GDVIRTUAL4R(Error, _load_image, Ref<Image>, Ref<FileAccess>, BitField<ImageFormatLoader::LoaderFlags>, float);
+};
+
class ImageLoader {
- static Vector<ImageFormatLoader *> loader;
+ static Vector<Ref<ImageFormatLoader>> loader;
friend class ResourceFormatLoaderImage;
protected:
public:
- static Error load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom = Ref<FileAccess>(), uint32_t p_flags = (uint32_t)ImageFormatLoader::FLAG_NONE, float p_scale = 1.0);
+ static Error load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom = Ref<FileAccess>(), BitField<ImageFormatLoader::LoaderFlags> p_flags = ImageFormatLoader::FLAG_NONE, float p_scale = 1.0);
static void get_recognized_extensions(List<String> *p_extensions);
- static ImageFormatLoader *recognize(const String &p_extension);
+ static Ref<ImageFormatLoader> recognize(const String &p_extension);
- static void add_image_format_loader(ImageFormatLoader *p_loader);
- static void remove_image_format_loader(ImageFormatLoader *p_loader);
+ static void add_image_format_loader(Ref<ImageFormatLoader> p_loader);
+ static void remove_image_format_loader(Ref<ImageFormatLoader> p_loader);
- static const Vector<ImageFormatLoader *> &get_image_format_loaders();
+ static const Vector<Ref<ImageFormatLoader>> &get_image_format_loaders();
static void cleanup();
};
diff --git a/core/io/json.cpp b/core/io/json.cpp
index a685fcb718..7e267d35d4 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -56,6 +56,8 @@ String JSON::_make_indent(const String &p_indent, int p_size) {
}
String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, HashSet<const void *> &p_markers, bool p_full_precision) {
+ ERR_FAIL_COND_V_MSG(p_cur_indent > Variant::MAX_RECURSION_DEPTH, "...", "JSON structure is too deep. Bailing.");
+
String colon = ":";
String end_statement = "";
@@ -357,17 +359,22 @@ Error JSON::_get_token(const char32_t *p_str, int &index, int p_len, Token &r_to
return ERR_PARSE_ERROR;
}
-Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) {
+Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str) {
+ if (p_depth > Variant::MAX_RECURSION_DEPTH) {
+ r_err_str = "JSON structure is too deep. Bailing.";
+ return ERR_OUT_OF_MEMORY;
+ }
+
if (token.type == TK_CURLY_BRACKET_OPEN) {
Dictionary d;
- Error err = _parse_object(d, p_str, index, p_len, line, r_err_str);
+ Error err = _parse_object(d, p_str, index, p_len, line, p_depth + 1, r_err_str);
if (err) {
return err;
}
value = d;
} else if (token.type == TK_BRACKET_OPEN) {
Array a;
- Error err = _parse_array(a, p_str, index, p_len, line, r_err_str);
+ Error err = _parse_array(a, p_str, index, p_len, line, p_depth + 1, r_err_str);
if (err) {
return err;
}
@@ -396,7 +403,7 @@ Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, in
return OK;
}
-Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) {
+Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str) {
Token token;
bool need_comma = false;
@@ -421,7 +428,7 @@ Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_
}
Variant v;
- err = _parse_value(v, token, p_str, index, p_len, line, r_err_str);
+ err = _parse_value(v, token, p_str, index, p_len, line, p_depth, r_err_str);
if (err) {
return err;
}
@@ -434,7 +441,7 @@ Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_
return ERR_PARSE_ERROR;
}
-Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) {
+Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str) {
bool at_key = true;
String key;
Token token;
@@ -483,7 +490,7 @@ Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index,
}
Variant v;
- err = _parse_value(v, token, p_str, index, p_len, line, r_err_str);
+ err = _parse_value(v, token, p_str, index, p_len, line, p_depth, r_err_str);
if (err) {
return err;
}
@@ -514,7 +521,7 @@ Error JSON::_parse_string(const String &p_json, Variant &r_ret, String &r_err_st
return err;
}
- err = _parse_value(r_ret, token, str, idx, len, r_err_line, r_err_str);
+ err = _parse_value(r_ret, token, str, idx, len, r_err_line, 0, r_err_str);
// Check if EOF is reached
// or it's a type of the next token.
diff --git a/core/io/json.h b/core/io/json.h
index 208d4ad625..829a5f922b 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -74,9 +74,9 @@ class JSON : public RefCounted {
static String _make_indent(const String &p_indent, int p_size);
static String _stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, HashSet<const void *> &p_markers, bool p_full_precision = false);
static Error _get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str);
- static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
- static Error _parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
- static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
+ static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str);
+ static Error _parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str);
+ static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str);
static Error _parse_string(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
protected:
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 553698f8a6..ab30fb1ca3 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -489,7 +489,7 @@ bool ResourceCache::has(const String &p_path) {
Resource **res = resources.getptr(p_path);
- if (res && (*res)->reference_get_count() == 0) {
+ if (res && (*res)->get_reference_count() == 0) {
// This resource is in the process of being deleted, ignore its existence.
(*res)->path_cache = String();
resources.erase(p_path);
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 4f1204fc48..06649aba5b 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1206,7 +1206,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
Ref<FileAccessCompressed> facw;
facw.instantiate();
facw->configure("RSCC");
- err = facw->_open(p_path + ".depren", FileAccess::WRITE);
+ err = facw->open_internal(p_path + ".depren", FileAccess::WRITE);
ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".depren'.");
fw = facw;
@@ -1986,7 +1986,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
fac.instantiate();
fac->configure("RSCC");
f = fac;
- err = fac->_open(p_path, FileAccess::WRITE);
+ err = fac->open_internal(p_path, FileAccess::WRITE);
} else {
f = FileAccess::open(p_path, FileAccess::WRITE, &err);
}
diff --git a/core/io/stream_peer_gzip.cpp b/core/io/stream_peer_gzip.cpp
new file mode 100644
index 0000000000..ca8be2d62e
--- /dev/null
+++ b/core/io/stream_peer_gzip.cpp
@@ -0,0 +1,209 @@
+/*************************************************************************/
+/* stream_peer_gzip.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 "core/io/stream_peer_gzip.h"
+
+#include "core/io/zip_io.h"
+#include <zlib.h>
+
+void StreamPeerGZIP::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("start_compression", "use_deflate", "buffer_size"), &StreamPeerGZIP::start_compression, DEFVAL(false), DEFVAL(65535));
+ ClassDB::bind_method(D_METHOD("start_decompression", "use_deflate", "buffer_size"), &StreamPeerGZIP::start_decompression, DEFVAL(false), DEFVAL(65535));
+ ClassDB::bind_method(D_METHOD("finish"), &StreamPeerGZIP::finish);
+ ClassDB::bind_method(D_METHOD("clear"), &StreamPeerGZIP::clear);
+}
+
+StreamPeerGZIP::StreamPeerGZIP() {
+}
+
+StreamPeerGZIP::~StreamPeerGZIP() {
+ _close();
+}
+
+void StreamPeerGZIP::_close() {
+ if (ctx) {
+ z_stream *strm = (z_stream *)ctx;
+ if (compressing) {
+ deflateEnd(strm);
+ } else {
+ inflateEnd(strm);
+ }
+ memfree(strm);
+ ctx = nullptr;
+ }
+}
+
+void StreamPeerGZIP::clear() {
+ _close();
+ rb.clear();
+ buffer.clear();
+}
+
+Error StreamPeerGZIP::start_compression(bool p_is_deflate, int buffer_size) {
+ return _start(true, p_is_deflate, buffer_size);
+}
+
+Error StreamPeerGZIP::start_decompression(bool p_is_deflate, int buffer_size) {
+ return _start(false, p_is_deflate, buffer_size);
+}
+
+Error StreamPeerGZIP::_start(bool p_compress, bool p_is_deflate, int buffer_size) {
+ ERR_FAIL_COND_V(ctx != nullptr, ERR_ALREADY_IN_USE);
+ clear();
+ compressing = p_compress;
+ rb.resize(nearest_shift(buffer_size - 1));
+ buffer.resize(1024);
+
+ // Create ctx.
+ ctx = memalloc(sizeof(z_stream));
+ z_stream &strm = *(z_stream *)ctx;
+ strm.next_in = Z_NULL;
+ strm.avail_in = 0;
+ strm.zalloc = zipio_alloc;
+ strm.zfree = zipio_free;
+ strm.opaque = Z_NULL;
+ int window_bits = p_is_deflate ? 15 : (15 + 16);
+ int err = Z_OK;
+ int level = Z_DEFAULT_COMPRESSION;
+ if (compressing) {
+ err = deflateInit2(&strm, level, Z_DEFLATED, window_bits, 8, Z_DEFAULT_STRATEGY);
+ } else {
+ err = inflateInit2(&strm, window_bits);
+ }
+ ERR_FAIL_COND_V(err != Z_OK, FAILED);
+ return OK;
+}
+
+Error StreamPeerGZIP::_process(uint8_t *p_dst, int p_dst_size, const uint8_t *p_src, int p_src_size, int &r_consumed, int &r_out, bool p_close) {
+ ERR_FAIL_COND_V(!ctx, ERR_UNCONFIGURED);
+ z_stream &strm = *(z_stream *)ctx;
+ strm.avail_in = p_src_size;
+ strm.avail_out = p_dst_size;
+ strm.next_in = (Bytef *)p_src;
+ strm.next_out = (Bytef *)p_dst;
+ int flush = p_close ? Z_FINISH : Z_NO_FLUSH;
+ if (compressing) {
+ int err = deflate(&strm, flush);
+ ERR_FAIL_COND_V(err != (p_close ? Z_STREAM_END : Z_OK), FAILED);
+ } else {
+ int err = inflate(&strm, flush);
+ ERR_FAIL_COND_V(err != Z_OK && err != Z_STREAM_END, FAILED);
+ }
+ r_out = p_dst_size - strm.avail_out;
+ r_consumed = p_src_size - strm.avail_in;
+ return OK;
+}
+
+Error StreamPeerGZIP::put_data(const uint8_t *p_data, int p_bytes) {
+ int wrote = 0;
+ Error err = put_partial_data(p_data, p_bytes, wrote);
+ if (err != OK) {
+ return err;
+ }
+ ERR_FAIL_COND_V(p_bytes != wrote, ERR_OUT_OF_MEMORY);
+ return OK;
+}
+
+Error StreamPeerGZIP::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
+ ERR_FAIL_COND_V(!ctx, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V(p_bytes < 0, ERR_INVALID_PARAMETER);
+
+ // Ensure we have enough space in temporary buffer.
+ if (buffer.size() < p_bytes) {
+ buffer.resize(p_bytes);
+ }
+
+ r_sent = 0;
+ while (r_sent < p_bytes && rb.space_left() > 1024) { // Keep the ring buffer size meaningful.
+ int sent = 0;
+ int to_write = 0;
+ // Compress or decompress
+ Error err = _process(buffer.ptrw(), MIN(buffer.size(), rb.space_left()), p_data + r_sent, p_bytes - r_sent, sent, to_write);
+ if (err != OK) {
+ return err;
+ }
+ // When decompressing, we might need to do another round.
+ r_sent += sent;
+
+ // We can't write more than this buffer is full.
+ if (sent == 0 && to_write == 0) {
+ return OK;
+ }
+ if (to_write) {
+ // Copy to ring buffer.
+ int wrote = rb.write(buffer.ptr(), to_write);
+ ERR_FAIL_COND_V(wrote != to_write, ERR_BUG);
+ }
+ }
+ return OK;
+}
+
+Error StreamPeerGZIP::get_data(uint8_t *p_buffer, int p_bytes) {
+ int received = 0;
+ Error err = get_partial_data(p_buffer, p_bytes, received);
+ if (err != OK) {
+ return err;
+ }
+ ERR_FAIL_COND_V(p_bytes != received, ERR_UNAVAILABLE);
+ return OK;
+}
+
+Error StreamPeerGZIP::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
+ ERR_FAIL_COND_V(p_bytes < 0, ERR_INVALID_PARAMETER);
+
+ r_received = MIN(p_bytes, rb.data_left());
+ if (r_received == 0) {
+ return OK;
+ }
+ int received = rb.read(p_buffer, r_received);
+ ERR_FAIL_COND_V(received != r_received, ERR_BUG);
+ return OK;
+}
+
+int StreamPeerGZIP::get_available_bytes() const {
+ return rb.data_left();
+}
+
+Error StreamPeerGZIP::finish() {
+ ERR_FAIL_COND_V(!ctx || !compressing, ERR_UNAVAILABLE);
+ // Ensure we have enough space in temporary buffer.
+ if (buffer.size() < 1024) {
+ buffer.resize(1024); // 1024 should be more than enough.
+ }
+ int consumed = 0;
+ int to_write = 0;
+ Error err = _process(buffer.ptrw(), 1024, nullptr, 0, consumed, to_write, true); // compress
+ if (err != OK) {
+ return err;
+ }
+ int wrote = rb.write(buffer.ptr(), to_write);
+ ERR_FAIL_COND_V(wrote != to_write, ERR_OUT_OF_MEMORY);
+ return OK;
+}
diff --git a/core/io/stream_peer_gzip.h b/core/io/stream_peer_gzip.h
new file mode 100644
index 0000000000..5bafdbca9b
--- /dev/null
+++ b/core/io/stream_peer_gzip.h
@@ -0,0 +1,76 @@
+/*************************************************************************/
+/* stream_peer_gzip.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 STREAM_PEER_GZIP_H
+#define STREAM_PEER_GZIP_H
+
+#include "core/io/stream_peer.h"
+
+#include "core/core_bind.h"
+#include "core/io/compression.h"
+#include "core/templates/ring_buffer.h"
+
+class StreamPeerGZIP : public StreamPeer {
+ GDCLASS(StreamPeerGZIP, StreamPeer);
+
+private:
+ void *ctx = nullptr; // Will hold our z_stream instance.
+ bool compressing = true;
+
+ RingBuffer<uint8_t> rb;
+ Vector<uint8_t> buffer;
+
+ Error _process(uint8_t *p_dst, int p_dst_size, const uint8_t *p_src, int p_src_size, int &r_consumed, int &r_out, bool p_close = false);
+ void _close();
+ Error _start(bool p_compress, bool p_is_deflate, int buffer_size = 65535);
+
+protected:
+ static void _bind_methods();
+
+public:
+ Error start_compression(bool p_is_deflate, int buffer_size = 65535);
+ Error start_decompression(bool p_is_deflate, int buffer_size = 65535);
+
+ Error finish();
+ void clear();
+
+ virtual Error put_data(const uint8_t *p_data, int p_bytes) override;
+ virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
+
+ virtual Error get_data(uint8_t *p_buffer, int p_bytes) override;
+ virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
+
+ virtual int get_available_bytes() const override;
+
+ StreamPeerGZIP();
+ ~StreamPeerGZIP();
+};
+
+#endif // STREAM_PEER_GZIP_H
diff --git a/core/math/bvh_structs.inc b/core/math/bvh_structs.inc
index 58c8f0479a..06f6e5d05d 100644
--- a/core/math/bvh_structs.inc
+++ b/core/math/bvh_structs.inc
@@ -100,7 +100,11 @@ public:
num_items++;
return id;
}
+#ifdef DEV_ENABLED
return -1;
+#else
+ ERR_FAIL_V_MSG(0, "BVH request_item error.");
+#endif
}
};
diff --git a/core/math/bvh_tree.h b/core/math/bvh_tree.h
index cdb2bb4413..8291394b31 100644
--- a/core/math/bvh_tree.h
+++ b/core/math/bvh_tree.h
@@ -235,7 +235,7 @@ private:
// no need to keep back references for children at the moment
- uint32_t sibling_id; // always a node id, as tnode is never a leaf
+ uint32_t sibling_id = 0; // always a node id, as tnode is never a leaf
bool sibling_present = false;
// if there are more children, or this is the root node, don't try and delete
diff --git a/core/math/convex_hull.h b/core/math/convex_hull.h
index bd86fe0eba..cc41a794bd 100644
--- a/core/math/convex_hull.h
+++ b/core/math/convex_hull.h
@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef CONVEX_HULL_H
+#define CONVEX_HULL_H
+
/*
Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
This software is provided 'as-is', without any express or implied warranty.
@@ -40,9 +43,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#ifndef CONVEX_HULL_H
-#define CONVEX_HULL_H
-
#include "core/math/geometry_3d.h"
#include "core/math/vector3.h"
#include "core/templates/local_vector.h"
diff --git a/core/math/math_fieldwise.cpp b/core/math/math_fieldwise.cpp
index 208f89f449..726a2aeb97 100644
--- a/core/math/math_fieldwise.cpp
+++ b/core/math/math_fieldwise.cpp
@@ -56,6 +56,15 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
+ case Variant::VECTOR2I: {
+ SETUP_TYPE(Vector2i)
+
+ /**/ TRY_TRANSFER_FIELD("x", x)
+ else TRY_TRANSFER_FIELD("y", y)
+
+ return target;
+ }
+
case Variant::RECT2: {
SETUP_TYPE(Rect2)
@@ -67,6 +76,17 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
+ case Variant::RECT2I: {
+ SETUP_TYPE(Rect2i)
+
+ /**/ TRY_TRANSFER_FIELD("x", position.x)
+ else TRY_TRANSFER_FIELD("y", position.y)
+ else TRY_TRANSFER_FIELD("w", size.x)
+ else TRY_TRANSFER_FIELD("h", size.y)
+
+ return target;
+ }
+
case Variant::VECTOR3: {
SETUP_TYPE(Vector3)
@@ -76,6 +96,7 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
+
case Variant::VECTOR3I: {
SETUP_TYPE(Vector3i)
@@ -85,6 +106,7 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
+
case Variant::VECTOR4: {
SETUP_TYPE(Vector4)
@@ -95,6 +117,7 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
+
case Variant::VECTOR4I: {
SETUP_TYPE(Vector4i)
@@ -106,7 +129,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
-
case Variant::PLANE: {
SETUP_TYPE(Plane)
@@ -190,6 +212,29 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
+ case Variant::PROJECTION: {
+ SETUP_TYPE(Projection)
+
+ /**/ TRY_TRANSFER_FIELD("xx", matrix[0].x)
+ else TRY_TRANSFER_FIELD("xy", matrix[0].y)
+ else TRY_TRANSFER_FIELD("xz", matrix[0].z)
+ else TRY_TRANSFER_FIELD("xw", matrix[0].w)
+ else TRY_TRANSFER_FIELD("yx", matrix[1].x)
+ else TRY_TRANSFER_FIELD("yy", matrix[1].y)
+ else TRY_TRANSFER_FIELD("yz", matrix[1].z)
+ else TRY_TRANSFER_FIELD("yw", matrix[1].w)
+ else TRY_TRANSFER_FIELD("zx", matrix[2].x)
+ else TRY_TRANSFER_FIELD("zy", matrix[2].y)
+ else TRY_TRANSFER_FIELD("zz", matrix[2].z)
+ else TRY_TRANSFER_FIELD("zw", matrix[2].w)
+ else TRY_TRANSFER_FIELD("xo", matrix[3].x)
+ else TRY_TRANSFER_FIELD("yo", matrix[3].y)
+ else TRY_TRANSFER_FIELD("zo", matrix[3].z)
+ else TRY_TRANSFER_FIELD("wo", matrix[3].w)
+
+ return target;
+ }
+
default: {
ERR_FAIL_V(p_target);
}
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 656fc9f798..7fa674a23d 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -267,6 +267,7 @@ public:
return cubic_interpolate(from_rot, to_rot, pre_rot, post_rot, p_weight);
}
+
static _ALWAYS_INLINE_ float cubic_interpolate_angle(float p_from, float p_to, float p_pre, float p_post, float p_weight) {
float from_rot = fmod(p_from, (float)Math_TAU);
@@ -293,6 +294,7 @@ public:
double b2 = Math::lerp(a2, a3, p_post_t == 0 ? 1.0 : t / p_post_t);
return Math::lerp(b1, b2, p_to_t == 0 ? 0.5 : t / p_to_t);
}
+
static _ALWAYS_INLINE_ float cubic_interpolate_in_time(float p_from, float p_to, float p_pre, float p_post, float p_weight,
float p_to_t, float p_pre_t, float p_post_t) {
/* Barry-Goldman method */
@@ -320,6 +322,7 @@ public:
return cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t);
}
+
static _ALWAYS_INLINE_ float cubic_interpolate_angle_in_time(float p_from, float p_to, float p_pre, float p_post, float p_weight,
float p_to_t, float p_pre_t, float p_post_t) {
float from_rot = fmod(p_from, (float)Math_TAU);
@@ -346,6 +349,7 @@ public:
return p_start * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
}
+
static _ALWAYS_INLINE_ float bezier_interpolate(float p_start, float p_control_1, float p_control_2, float p_end, float p_t) {
/* Formula from Wikipedia article on Bezier curves. */
float omt = (1.0f - p_t);
@@ -368,11 +372,19 @@ public:
return p_from + distance * p_weight;
}
- static _ALWAYS_INLINE_ double inverse_lerp(double p_from, double p_to, double p_value) { return (p_value - p_from) / (p_to - p_from); }
- static _ALWAYS_INLINE_ float inverse_lerp(float p_from, float p_to, float p_value) { return (p_value - p_from) / (p_to - p_from); }
+ static _ALWAYS_INLINE_ double inverse_lerp(double p_from, double p_to, double p_value) {
+ return (p_value - p_from) / (p_to - p_from);
+ }
+ static _ALWAYS_INLINE_ float inverse_lerp(float p_from, float p_to, float p_value) {
+ return (p_value - p_from) / (p_to - p_from);
+ }
- static _ALWAYS_INLINE_ double remap(double p_value, double p_istart, double p_istop, double p_ostart, double p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); }
- static _ALWAYS_INLINE_ float remap(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); }
+ static _ALWAYS_INLINE_ double remap(double p_value, double p_istart, double p_istop, double p_ostart, double p_ostop) {
+ return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value));
+ }
+ static _ALWAYS_INLINE_ float remap(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) {
+ return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value));
+ }
static _ALWAYS_INLINE_ double smoothstep(double p_from, double p_to, double p_s) {
if (is_equal_approx(p_from, p_to)) {
@@ -388,14 +400,26 @@ public:
float s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0f, 1.0f);
return s * s * (3.0f - 2.0f * s);
}
- static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; }
- static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; }
+ static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) {
+ return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta;
+ }
+ static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) {
+ return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta;
+ }
- static _ALWAYS_INLINE_ double linear_to_db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; }
- static _ALWAYS_INLINE_ float linear_to_db(float p_linear) { return Math::log(p_linear) * (float)8.6858896380650365530225783783321; }
+ static _ALWAYS_INLINE_ double linear_to_db(double p_linear) {
+ return Math::log(p_linear) * 8.6858896380650365530225783783321;
+ }
+ static _ALWAYS_INLINE_ float linear_to_db(float p_linear) {
+ return Math::log(p_linear) * (float)8.6858896380650365530225783783321;
+ }
- static _ALWAYS_INLINE_ double db_to_linear(double p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); }
- static _ALWAYS_INLINE_ float db_to_linear(float p_db) { return Math::exp(p_db * (float)0.11512925464970228420089957273422); }
+ static _ALWAYS_INLINE_ double db_to_linear(double p_db) {
+ return Math::exp(p_db * 0.11512925464970228420089957273422);
+ }
+ static _ALWAYS_INLINE_ float db_to_linear(float p_db) {
+ return Math::exp(p_db * (float)0.11512925464970228420089957273422);
+ }
static _ALWAYS_INLINE_ double round(double p_val) { return ::round(p_val); }
static _ALWAYS_INLINE_ float round(float p_val) { return ::roundf(p_val); }
diff --git a/core/math/vector2i.h b/core/math/vector2i.h
index 0245900a3b..e131bdea94 100644
--- a/core/math/vector2i.h
+++ b/core/math/vector2i.h
@@ -38,6 +38,8 @@ class String;
struct Vector2;
struct _NO_DISCARD_ Vector2i {
+ static const int AXIS_COUNT = 2;
+
enum Axis {
AXIS_X,
AXIS_Y,
diff --git a/core/math/vector3i.h b/core/math/vector3i.h
index 825ce40318..c6d03cd031 100644
--- a/core/math/vector3i.h
+++ b/core/math/vector3i.h
@@ -38,6 +38,8 @@ class String;
struct Vector3;
struct _NO_DISCARD_ Vector3i {
+ static const int AXIS_COUNT = 3;
+
enum Axis {
AXIS_X,
AXIS_Y,
diff --git a/core/math/vector4.h b/core/math/vector4.h
index f964264108..d89f3ddb05 100644
--- a/core/math/vector4.h
+++ b/core/math/vector4.h
@@ -37,6 +37,8 @@
#include "core/string/ustring.h"
struct _NO_DISCARD_ Vector4 {
+ static const int AXIS_COUNT = 4;
+
enum Axis {
AXIS_X,
AXIS_Y,
diff --git a/core/math/vector4i.h b/core/math/vector4i.h
index d08e40d754..fdf33b9569 100644
--- a/core/math/vector4i.h
+++ b/core/math/vector4i.h
@@ -38,6 +38,8 @@ class String;
struct Vector4;
struct _NO_DISCARD_ Vector4i {
+ static const int AXIS_COUNT = 4;
+
enum Axis {
AXIS_X,
AXIS_Y,
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index c18d70d9f6..326a9277ff 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -5,11 +5,11 @@ mutable bool _gdvirtual_##m_name##_initialized = false;\\
mutable GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\
template<bool required>\\
_FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
- ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
- if (script_instance) {\\
+ ScriptInstance *_script_instance = ((Object*)(this))->get_script_instance();\\
+ if (_script_instance) {\\
Callable::CallError ce; \\
$CALLSIARGS\\
- $CALLSIBEGINscript_instance->callp(_gdvirtual_##m_name##_sn, $CALLSIARGPASS, ce);\\
+ $CALLSIBEGIN_script_instance->callp(_gdvirtual_##m_name##_sn, $CALLSIARGPASS, ce);\\
if (ce.error == Callable::CallError::CALL_OK) {\\
$CALLSIRET\\
return true;\\
@@ -35,9 +35,9 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
return false;\\
}\\
_FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const { \\
- ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
- if (script_instance) {\\
- return script_instance->has_method(_gdvirtual_##m_name##_sn);\\
+ ScriptInstance *_script_instance = ((Object*)(this))->get_script_instance();\\
+ if (_script_instance) {\\
+ return _script_instance->has_method(_gdvirtual_##m_name##_sn);\\
}\\
if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\
_gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index d60550c899..0d3e40f709 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -241,9 +241,17 @@ class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>,
friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
public:
+#if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+ // Workaround GH-66343 raised only with UBSAN, seems to be a false positive.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override {
return (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)(p_args, p_arg_count, r_error);
}
+#if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
MethodBindVarArgTR(
R (T::*p_method)(const Variant **, int, Callable::CallError &),
diff --git a/core/object/ref_counted.cpp b/core/object/ref_counted.cpp
index cac2400744..50467d795d 100644
--- a/core/object/ref_counted.cpp
+++ b/core/object/ref_counted.cpp
@@ -48,9 +48,10 @@ void RefCounted::_bind_methods() {
ClassDB::bind_method(D_METHOD("init_ref"), &RefCounted::init_ref);
ClassDB::bind_method(D_METHOD("reference"), &RefCounted::reference);
ClassDB::bind_method(D_METHOD("unreference"), &RefCounted::unreference);
+ ClassDB::bind_method(D_METHOD("get_reference_count"), &RefCounted::get_reference_count);
}
-int RefCounted::reference_get_count() const {
+int RefCounted::get_reference_count() const {
return refcount.get();
}
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
index bd06a84bd8..71790fb825 100644
--- a/core/object/ref_counted.h
+++ b/core/object/ref_counted.h
@@ -47,7 +47,7 @@ public:
bool init_ref();
bool reference(); // returns false if refcount is at zero and didn't get increased
bool unreference();
- int reference_get_count() const;
+ int get_reference_count() const;
RefCounted();
~RefCounted() {}
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index d3c48853f1..aa66e86bc0 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -126,27 +126,28 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
force_keep_in_merge_ends = false;
}
-void UndoRedo::add_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
- ERR_FAIL_COND(p_object == nullptr);
+void UndoRedo::add_do_method(const Callable &p_callable) {
+ ERR_FAIL_COND(p_callable.is_null());
ERR_FAIL_COND(action_level <= 0);
ERR_FAIL_COND((current_action + 1) >= actions.size());
+
+ Object *object = p_callable.get_object();
+ ERR_FAIL_NULL(object);
+
Operation do_op;
- do_op.object = p_object->get_instance_id();
- if (Object::cast_to<RefCounted>(p_object)) {
- do_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(p_object));
+ do_op.callable = p_callable;
+ do_op.object = p_callable.get_object_id();
+ if (Object::cast_to<RefCounted>(object)) {
+ do_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(object));
}
-
do_op.type = Operation::TYPE_METHOD;
- do_op.name = p_method;
+ do_op.name = p_callable.get_method();
- for (int i = 0; i < p_argcount; i++) {
- do_op.args.push_back(*p_args[i]);
- }
actions.write[current_action + 1].do_ops.push_back(do_op);
}
-void UndoRedo::add_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
- ERR_FAIL_COND(p_object == nullptr);
+void UndoRedo::add_undo_method(const Callable &p_callable) {
+ ERR_FAIL_COND(p_callable.is_null());
ERR_FAIL_COND(action_level <= 0);
ERR_FAIL_COND((current_action + 1) >= actions.size());
@@ -155,19 +156,19 @@ void UndoRedo::add_undo_methodp(Object *p_object, const StringName &p_method, co
return;
}
+ Object *object = p_callable.get_object();
+ ERR_FAIL_NULL(object);
+
Operation undo_op;
- undo_op.object = p_object->get_instance_id();
- if (Object::cast_to<RefCounted>(p_object)) {
- undo_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(p_object));
+ undo_op.callable = p_callable;
+ undo_op.object = p_callable.get_object_id();
+ if (Object::cast_to<RefCounted>(object)) {
+ undo_op.ref = Ref<RefCounted>(Object::cast_to<RefCounted>(object));
}
-
undo_op.type = Operation::TYPE_METHOD;
undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
- undo_op.name = p_method;
+ undo_op.name = p_callable.get_method();
- for (int i = 0; i < p_argcount; i++) {
- undo_op.args.push_back(*p_args[i]);
- }
actions.write[current_action + 1].undo_ops.push_back(undo_op);
}
@@ -183,7 +184,7 @@ void UndoRedo::add_do_property(Object *p_object, const StringName &p_property, c
do_op.type = Operation::TYPE_PROPERTY;
do_op.name = p_property;
- do_op.args.push_back(p_value);
+ do_op.value = p_value;
actions.write[current_action + 1].do_ops.push_back(do_op);
}
@@ -206,7 +207,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property,
undo_op.type = Operation::TYPE_PROPERTY;
undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_property;
- undo_op.args.push_back(p_value);
+ undo_op.value = p_value;
actions.write[current_action + 1].undo_ops.push_back(undo_op);
}
@@ -312,33 +313,42 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
switch (op.type) {
case Operation::TYPE_METHOD: {
- int argc = op.args.size();
- Vector<const Variant *> argptrs;
- argptrs.resize(argc);
-
- for (int i = 0; i < argc; i++) {
- argptrs.write[i] = &op.args[i];
- }
-
Callable::CallError ce;
- obj->callp(op.name, (const Variant **)argptrs.ptr(), argc, ce);
+ Variant ret;
+ op.callable.callp(nullptr, 0, ret, ce);
if (ce.error != Callable::CallError::CALL_OK) {
- ERR_PRINT("Error calling UndoRedo method operation '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, (const Variant **)argptrs.ptr(), argc, ce));
+ ERR_PRINT("Error calling UndoRedo method operation '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, nullptr, 0, ce));
}
#ifdef TOOLS_ENABLED
Resource *res = Object::cast_to<Resource>(obj);
if (res) {
res->set_edited(true);
}
-
#endif
if (method_callback) {
- method_callback(method_callback_ud, obj, op.name, (const Variant **)argptrs.ptr(), argc);
+ Vector<Variant> binds;
+ if (op.callable.is_custom()) {
+ CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(op.callable.get_custom());
+ if (ccb) {
+ binds = ccb->get_binds();
+ }
+ }
+
+ if (binds.is_empty()) {
+ method_callback(method_callback_ud, obj, op.name, nullptr, 0);
+ } else {
+ const Variant **args = (const Variant **)alloca(sizeof(const Variant **) * binds.size());
+ for (int i = 0; i < binds.size(); i++) {
+ args[i] = (const Variant *)&binds[i];
+ }
+
+ method_callback(method_callback_ud, obj, op.name, args, binds.size());
+ }
}
} break;
case Operation::TYPE_PROPERTY: {
- obj->set(op.name, op.args[0]);
+ obj->set(op.name, op.value);
#ifdef TOOLS_ENABLED
Resource *res = Object::cast_to<Resource>(obj);
if (res) {
@@ -346,7 +356,7 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
}
#endif
if (property_callback) {
- property_callback(prop_callback_ud, obj, op.name, op.args[0]);
+ property_callback(prop_callback_ud, obj, op.name, op.value);
}
} break;
case Operation::TYPE_REFERENCE: {
@@ -444,87 +454,13 @@ UndoRedo::~UndoRedo() {
clear_history();
}
-void UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- if (p_argcount < 2) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 0;
- return;
- }
-
- if (p_args[0]->get_type() != Variant::OBJECT) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::OBJECT;
- return;
- }
-
- if (p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 1;
- r_error.expected = Variant::STRING_NAME;
- return;
- }
-
- r_error.error = Callable::CallError::CALL_OK;
-
- Object *object = *p_args[0];
- StringName method = *p_args[1];
-
- add_do_methodp(object, method, p_args + 2, p_argcount - 2);
-}
-
-void UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- if (p_argcount < 2) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 0;
- return;
- }
-
- if (p_args[0]->get_type() != Variant::OBJECT) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::OBJECT;
- return;
- }
-
- if (p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 1;
- r_error.expected = Variant::STRING_NAME;
- return;
- }
-
- r_error.error = Callable::CallError::CALL_OK;
-
- Object *object = *p_args[0];
- StringName method = *p_args[1];
-
- add_undo_methodp(object, method, p_args + 2, p_argcount - 2);
-}
-
void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_action", "name", "merge_mode"), &UndoRedo::create_action, DEFVAL(MERGE_DISABLE));
ClassDB::bind_method(D_METHOD("commit_action", "execute"), &UndoRedo::commit_action, DEFVAL(true));
ClassDB::bind_method(D_METHOD("is_committing_action"), &UndoRedo::is_committing_action);
- {
- MethodInfo mi;
- mi.name = "add_do_method";
- mi.arguments.push_back(PropertyInfo(Variant::OBJECT, "object"));
- mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
-
- ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "add_do_method", &UndoRedo::_add_do_method, mi, varray(), false);
- }
-
- {
- MethodInfo mi;
- mi.name = "add_undo_method";
- mi.arguments.push_back(PropertyInfo(Variant::OBJECT, "object"));
- mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
-
- ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "add_undo_method", &UndoRedo::_add_undo_method, mi, varray(), false);
- }
-
+ ClassDB::bind_method(D_METHOD("add_do_method", "callable"), &UndoRedo::add_do_method);
+ ClassDB::bind_method(D_METHOD("add_undo_method", "callable"), &UndoRedo::add_undo_method);
ClassDB::bind_method(D_METHOD("add_do_property", "object", "property", "value"), &UndoRedo::add_do_property);
ClassDB::bind_method(D_METHOD("add_undo_property", "object", "property", "value"), &UndoRedo::add_undo_property);
ClassDB::bind_method(D_METHOD("add_do_reference", "object"), &UndoRedo::add_do_reference);
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index 63cf3e5cbe..c7c58697c3 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -46,8 +46,6 @@ public:
};
typedef void (*CommitNotifyCallback)(void *p_ud, const String &p_name);
- void _add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- void _add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
typedef void (*MethodNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount);
typedef void (*PropertyNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value);
@@ -58,14 +56,14 @@ private:
TYPE_METHOD,
TYPE_PROPERTY,
TYPE_REFERENCE
- };
+ } type;
- Type type;
bool force_keep_in_merge_ends;
Ref<RefCounted> ref;
ObjectID object;
StringName name;
- Vector<Variant> args;
+ Callable callable;
+ Variant value;
void delete_reference();
};
@@ -106,30 +104,8 @@ protected:
public:
void create_action(const String &p_name = "", MergeMode p_mode = MERGE_DISABLE);
- void add_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
- void add_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
-
- template <typename... VarArgs>
- void add_do_method(Object *p_object, const StringName &p_method, VarArgs... p_args) {
- Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
- const Variant *argptrs[sizeof...(p_args) + 1];
- for (uint32_t i = 0; i < sizeof...(p_args); i++) {
- argptrs[i] = &args[i];
- }
-
- add_do_methodp(p_object, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
- }
- template <typename... VarArgs>
- void add_undo_method(Object *p_object, const StringName &p_method, VarArgs... p_args) {
- Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
- const Variant *argptrs[sizeof...(p_args) + 1];
- for (uint32_t i = 0; i < sizeof...(p_args); i++) {
- argptrs[i] = &args[i];
- }
-
- add_undo_methodp(p_object, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
- }
-
+ void add_do_method(const Callable &p_callable);
+ void add_undo_method(const Callable &p_callable);
void add_do_property(Object *p_object, const StringName &p_property, const Variant &p_value);
void add_undo_property(Object *p_object, const StringName &p_property, const Variant &p_value);
void add_do_reference(Object *p_object);
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 526b31ae7e..ee8da21751 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -54,10 +54,6 @@ double OS::get_unix_time() const {
return 0;
}
-void OS::debug_break() {
- // something
-}
-
void OS::_set_logger(CompositeLogger *p_logger) {
if (_logger) {
memdelete(_logger);
diff --git a/core/os/os.h b/core/os/os.h
index 6944d29eeb..aa45a3b8a8 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -69,6 +69,7 @@ class OS {
// so we can retrieve the rendering drivers available
int _display_driver_id = -1;
String _current_rendering_driver_name;
+ String _current_rendering_method;
protected:
void _set_logger(CompositeLogger *p_logger);
@@ -98,6 +99,8 @@ protected:
virtual void initialize_joypads() = 0;
void set_current_rendering_driver_name(String p_driver_name) { _current_rendering_driver_name = p_driver_name; }
+ void set_current_rendering_method(String p_name) { _current_rendering_method = p_name; }
+
void set_display_driver_id(int p_display_driver_id) { _display_driver_id = p_display_driver_id; }
virtual void set_main_loop(MainLoop *p_main_loop) = 0;
@@ -116,6 +119,8 @@ public:
static OS *get_singleton();
String get_current_rendering_driver_name() const { return _current_rendering_driver_name; }
+ String get_current_rendering_method() const { return _current_rendering_method; }
+
int get_display_driver_id() const { return _display_driver_id; }
void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, Logger::ErrorType p_type = Logger::ERR_ERROR);
@@ -282,8 +287,6 @@ public:
virtual Error move_to_trash(const String &p_path) { return FAILED; }
- virtual void debug_break();
-
virtual int get_exit_code() const;
// `set_exit_code` should only be used from `SceneTree` (or from a similar
// level, e.g. from the `Main::start` if leaving without creating a `SceneTree`).
diff --git a/core/os/pool_allocator.cpp b/core/os/pool_allocator.cpp
index f622e2c7c5..e7f2cff7c5 100644
--- a/core/os/pool_allocator.cpp
+++ b/core/os/pool_allocator.cpp
@@ -35,8 +35,6 @@
#include "core/os/os.h"
#include "core/string/print_string.h"
-#include <assert.h>
-
#define COMPACT_CHUNK(m_entry, m_to_pos) \
do { \
void *_dst = &((unsigned char *)pool)[m_to_pos]; \
@@ -169,11 +167,6 @@ bool PoolAllocator::find_entry_index(EntryIndicesPos *p_map_pos, const Entry *p_
PoolAllocator::ID PoolAllocator::alloc(int p_size) {
ERR_FAIL_COND_V(p_size < 1, POOL_ALLOCATOR_INVALID_ID);
-#ifdef DEBUG_ENABLED
- if (p_size > free_mem) {
- OS::get_singleton()->debug_break();
- }
-#endif
ERR_FAIL_COND_V(p_size > free_mem, POOL_ALLOCATOR_INVALID_ID);
mt_lock();
@@ -482,7 +475,6 @@ void *PoolAllocator::get(ID p_mem) {
ERR_FAIL_COND_V(!e, nullptr);
}
if (e->lock == 0) {
- //assert(0);
mt_unlock();
ERR_PRINT("e->lock == 0");
return nullptr;
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 6dfb0f82e0..2e144a4c9a 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -44,6 +44,7 @@
#include "core/input/input_map.h"
#include "core/input/shortcut.h"
#include "core/io/config_file.h"
+#include "core/io/dir_access.h"
#include "core/io/dtls_server.h"
#include "core/io/http_client.h"
#include "core/io/image_loader.h"
@@ -58,6 +59,7 @@
#include "core/io/resource_format_binary.h"
#include "core/io/resource_importer.h"
#include "core/io/resource_uid.h"
+#include "core/io/stream_peer_gzip.h"
#include "core/io/stream_peer_tls.h"
#include "core/io/tcp_server.h"
#include "core/io/translation_loader_po.h"
@@ -184,6 +186,7 @@ void register_core_types() {
GDREGISTER_ABSTRACT_CLASS(StreamPeer);
GDREGISTER_CLASS(StreamPeerExtension);
GDREGISTER_CLASS(StreamPeerBuffer);
+ GDREGISTER_CLASS(StreamPeerGZIP);
GDREGISTER_CLASS(StreamPeerTCP);
GDREGISTER_CLASS(TCPServer);
@@ -228,8 +231,8 @@ void register_core_types() {
GDREGISTER_CLASS(ResourceFormatLoader);
GDREGISTER_CLASS(ResourceFormatSaver);
- GDREGISTER_CLASS(core_bind::File);
- GDREGISTER_CLASS(core_bind::Directory);
+ GDREGISTER_ABSTRACT_CLASS(FileAccess);
+ GDREGISTER_ABSTRACT_CLASS(DirAccess);
GDREGISTER_CLASS(core_bind::Thread);
GDREGISTER_CLASS(core_bind::Mutex);
GDREGISTER_CLASS(core_bind::Semaphore);
@@ -249,6 +252,8 @@ void register_core_types() {
GDREGISTER_CLASS(EncodedObjectAsID);
GDREGISTER_CLASS(RandomNumberGenerator);
+ GDREGISTER_ABSTRACT_CLASS(ImageFormatLoader);
+ GDREGISTER_CLASS(ImageFormatLoaderExtension);
GDREGISTER_ABSTRACT_CLASS(ResourceImporter);
GDREGISTER_CLASS(NativeExtension);
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index d8b93998af..75b797d397 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -2624,10 +2624,11 @@ double String::to_float() const {
uint32_t String::hash(const char *p_cstr) {
uint32_t hashv = 5381;
- uint32_t c;
+ uint32_t c = *p_cstr++;
- while ((c = *p_cstr++)) {
+ while (c) {
hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */
+ c = *p_cstr++;
}
return hashv;
@@ -2653,10 +2654,11 @@ uint32_t String::hash(const wchar_t *p_cstr, int p_len) {
uint32_t String::hash(const wchar_t *p_cstr) {
uint32_t hashv = 5381;
- uint32_t c;
+ uint32_t c = *p_cstr++;
- while ((c = *p_cstr++)) {
+ while (c) {
hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */
+ c = *p_cstr++;
}
return hashv;
@@ -2673,10 +2675,11 @@ uint32_t String::hash(const char32_t *p_cstr, int p_len) {
uint32_t String::hash(const char32_t *p_cstr) {
uint32_t hashv = 5381;
- uint32_t c;
+ uint32_t c = *p_cstr++;
- while ((c = *p_cstr++)) {
+ while (c) {
hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */
+ c = *p_cstr++;
}
return hashv;
@@ -2687,10 +2690,11 @@ uint32_t String::hash() const {
const char32_t *chr = get_data();
uint32_t hashv = 5381;
- uint32_t c;
+ uint32_t c = *chr++;
- while ((c = *chr++)) {
+ while (c) {
hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */
+ c = *chr++;
}
return hashv;
@@ -2701,10 +2705,11 @@ uint64_t String::hash64() const {
const char32_t *chr = get_data();
uint64_t hashv = 5381;
- uint64_t c;
+ uint64_t c = *chr++;
- while ((c = *chr++)) {
+ while (c) {
hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */
+ c = *chr++;
}
return hashv;
diff --git a/core/string/ustring.h b/core/string/ustring.h
index b8ae3c2392..4b6568a502 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Note: _GODOT suffix added to avoid conflict with ICU header with the same guard.
-
#ifndef USTRING_GODOT_H
#define USTRING_GODOT_H
+// Note: _GODOT suffix added to header guard to avoid conflict with ICU header.
+
#include "core/string/char_utils.h"
#include "core/templates/cowdata.h"
#include "core/templates/vector.h"
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index d85cdf7adc..456a7b01ed 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -61,10 +61,11 @@
static _FORCE_INLINE_ uint32_t hash_djb2(const char *p_cstr) {
const unsigned char *chr = (const unsigned char *)p_cstr;
uint32_t hash = 5381;
- uint32_t c;
+ uint32_t c = *chr++;
- while ((c = *chr++)) {
+ while (c) {
hash = ((hash << 5) + hash) ^ c; /* hash * 33 ^ c */
+ c = *chr++;
}
return hash;
diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h
index f1ede556e6..2992dd463e 100644
--- a/core/templates/paged_array.h
+++ b/core/templates/paged_array.h
@@ -268,7 +268,7 @@ public:
uint32_t remainder = count & page_size_mask;
T *remainder_page = nullptr;
- uint32_t remainder_page_id;
+ uint32_t remainder_page_id = 0;
if (remainder > 0) {
uint32_t last_page = _get_pages_in_use() - 1;
diff --git a/core/templates/pooled_list.h b/core/templates/pooled_list.h
index f13156b292..08f53572e7 100644
--- a/core/templates/pooled_list.h
+++ b/core/templates/pooled_list.h
@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#pragma once
+#ifndef POOLED_LIST_H
+#define POOLED_LIST_H
// Simple template to provide a pool with O(1) allocate and free.
// The freelist could alternatively be a linked list placed within the unused elements
@@ -206,3 +207,5 @@ private:
LocalVector<U, U> _active_map;
LocalVector<U, U> _active_list;
};
+
+#endif // POOLED_LIST_H
diff --git a/core/variant/array.h b/core/variant/array.h
index c007376734..3d9a794969 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -47,7 +47,6 @@ class Array {
void _unref() const;
protected:
- Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script);
bool _assign(const Array &p_array);
public:
@@ -131,6 +130,7 @@ public:
void set_read_only(bool p_enable);
bool is_read_only() const;
+ Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script);
Array(const Array &p_from);
Array();
~Array();
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index 28efb43fc5..b35e2f004b 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -63,6 +63,21 @@ void Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_ret
}
}
+Variant Callable::callv(const Array &p_arguments) const {
+ int argcount = p_arguments.size();
+ const Variant **argptrs = nullptr;
+ if (argcount) {
+ argptrs = (const Variant **)alloca(sizeof(Variant *) * argcount);
+ for (int i = 0; i < argcount; i++) {
+ argptrs[i] = &p_arguments[i];
+ }
+ }
+ CallError ce;
+ Variant ret;
+ callp(argptrs, argcount, ret, ce);
+ return ret;
+}
+
Error Callable::rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const {
if (is_null()) {
r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
diff --git a/core/variant/callable.h b/core/variant/callable.h
index 1f1c983eb3..0305dc55c3 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -71,6 +71,7 @@ public:
void callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const;
void call_deferredp(const Variant **p_arguments, int p_argcount) const;
+ Variant callv(const Array &p_arguments) const;
Error rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const;
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index f09885b325..1831f7b72a 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1859,6 +1859,7 @@ static void _register_variant_builtin_methods() {
/* Callable */
+ bind_method(Callable, callv, sarray("arguments"), varray());
bind_method(Callable, is_null, sarray(), varray());
bind_method(Callable, is_custom, sarray(), varray());
bind_method(Callable, is_standard, sarray(), varray());
@@ -2065,6 +2066,14 @@ static void _register_variant_builtin_methods() {
bind_method(Array, all, sarray("method"), varray());
bind_method(Array, max, sarray(), varray());
bind_method(Array, min, sarray(), varray());
+ bind_method(Array, typed_assign, sarray("array"), varray());
+ bind_method(Array, set_typed, sarray("type", "class_name", "script"), varray());
+ bind_method(Array, is_typed, sarray(), varray());
+ bind_method(Array, get_typed_builtin, sarray(), varray());
+ bind_method(Array, get_typed_class_name, sarray(), varray());
+ bind_method(Array, get_typed_script, sarray(), varray());
+ bind_method(Array, set_read_only, sarray("enable"), varray());
+ bind_method(Array, is_read_only, sarray(), varray());
/* Byte Array */
bind_method(PackedByteArray, size, sarray(), varray());
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index d048f45737..3b88dc11ca 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -200,6 +200,7 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructNoArgs<Array>>(sarray());
add_constructor<VariantConstructor<Array, Array>>(sarray("from"));
+ add_constructor<VariantConstructorTypedArray>(sarray("base", "type", "class_name", "script"));
add_constructor<VariantConstructorToArray<PackedByteArray>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedInt32Array>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedInt64Array>>(sarray("from"));
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index 58a0f34c1e..34d228f4d2 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -336,6 +336,82 @@ public:
}
};
+class VariantConstructorTypedArray {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ if (p_args[0]->get_type() != Variant::ARRAY) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::ARRAY;
+ return;
+ }
+
+ if (p_args[1]->get_type() != Variant::INT) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::INT;
+ return;
+ }
+
+ if (p_args[2]->get_type() != Variant::STRING_NAME) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 2;
+ r_error.expected = Variant::STRING_NAME;
+ return;
+ }
+
+ const Array &base_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
+ const uint32_t type = p_args[1]->operator uint32_t();
+ const StringName &class_name = *VariantGetInternalPtr<StringName>::get_ptr(p_args[2]);
+ r_ret = Array(base_arr, type, class_name, *p_args[3]);
+ }
+
+ static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+ const Array &base_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
+ const uint32_t type = p_args[1]->operator uint32_t();
+ const StringName &class_name = *VariantGetInternalPtr<StringName>::get_ptr(p_args[2]);
+ *r_ret = Array(base_arr, type, class_name, *p_args[3]);
+ }
+
+ static void ptr_construct(void *base, const void **p_args) {
+ const Array &base_arr = PtrToArg<Array>::convert(p_args[0]);
+ const uint32_t type = PtrToArg<uint32_t>::convert(p_args[1]);
+ const StringName &class_name = PtrToArg<StringName>::convert(p_args[2]);
+ const Variant &script = PtrToArg<Variant>::convert(p_args[3]);
+ Array dst_arr = Array(base_arr, type, class_name, script);
+
+ PtrConstruct<Array>::construct(dst_arr, base);
+ }
+
+ static int get_argument_count() {
+ return 4;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ switch (p_arg) {
+ case 0: {
+ return Variant::ARRAY;
+ } break;
+ case 1: {
+ return Variant::INT;
+ } break;
+ case 2: {
+ return Variant::STRING_NAME;
+ } break;
+ case 3: {
+ return Variant::NIL;
+ } break;
+ default: {
+ return Variant::NIL;
+ } break;
+ }
+ }
+
+ static Variant::Type get_base_type() {
+ return Variant::ARRAY;
+ }
+};
+
template <class T>
class VariantConstructorToArray {
public:
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 7ff64c88f0..670b66d53e 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -128,8 +128,8 @@ struct VariantUtilityFunctions {
return Math::floor(x);
}
- static inline int floori(double x) {
- return int(x);
+ static inline int64_t floori(double x) {
+ return int64_t(Math::floor(x));
}
static inline Variant ceil(Variant x, Callable::CallError &r_error) {
@@ -161,8 +161,8 @@ struct VariantUtilityFunctions {
return Math::ceil(x);
}
- static inline int ceili(double x) {
- return int(Math::ceil(x));
+ static inline int64_t ceili(double x) {
+ return int64_t(Math::ceil(x));
}
static inline Variant round(Variant x, Callable::CallError &r_error) {
@@ -194,8 +194,8 @@ struct VariantUtilityFunctions {
return Math::round(x);
}
- static inline int roundi(double x) {
- return int(Math::round(x));
+ static inline int64_t roundi(double x) {
+ return int64_t(Math::round(x));
}
static inline Variant abs(const Variant &x, Callable::CallError &r_error) {