diff options
Diffstat (limited to 'core')
128 files changed, 5202 insertions, 5002 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index efd7e3dbf5..583a44846f 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -77,11 +77,11 @@ RES _ResourceLoader::load(const String &p_path, const String &p_type_hint, bool return ret; } -PoolVector<String> _ResourceLoader::get_recognized_extensions_for_type(const String &p_type) { +Vector<String> _ResourceLoader::get_recognized_extensions_for_type(const String &p_type) { List<String> exts; ResourceLoader::get_recognized_extensions_for_type(p_type, &exts); - PoolVector<String> ret; + Vector<String> ret; for (List<String>::Element *E = exts.front(); E; E = E->next()) { ret.push_back(E->get()); @@ -95,12 +95,12 @@ void _ResourceLoader::set_abort_on_missing_resources(bool p_abort) { ResourceLoader::set_abort_on_missing_resources(p_abort); } -PoolStringArray _ResourceLoader::get_dependencies(const String &p_path) { +PackedStringArray _ResourceLoader::get_dependencies(const String &p_path) { List<String> deps; ResourceLoader::get_dependencies(p_path, &deps); - PoolStringArray ret; + PackedStringArray ret; for (List<String>::Element *E = deps.front(); E; E = E->next()) { ret.push_back(E->get()); } @@ -108,13 +108,6 @@ PoolStringArray _ResourceLoader::get_dependencies(const String &p_path) { return ret; }; -#ifndef DISABLE_DEPRECATED -bool _ResourceLoader::has(const String &p_path) { - WARN_PRINTS("ResourceLoader.has() is deprecated, please replace it with the equivalent has_cached() or the new exists()."); - return has_cached(p_path); -} -#endif // DISABLE_DEPRECATED - bool _ResourceLoader::has_cached(const String &p_path) { String local_path = ProjectSettings::get_singleton()->localize_path(p_path); @@ -134,9 +127,6 @@ void _ResourceLoader::_bind_methods() { ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &_ResourceLoader::get_dependencies); ClassDB::bind_method(D_METHOD("has_cached", "path"), &_ResourceLoader::has_cached); ClassDB::bind_method(D_METHOD("exists", "path", "type_hint"), &_ResourceLoader::exists, DEFVAL("")); -#ifndef DISABLE_DEPRECATED - ClassDB::bind_method(D_METHOD("has", "path"), &_ResourceLoader::has); -#endif // DISABLE_DEPRECATED } _ResourceLoader::_ResourceLoader() { @@ -149,12 +139,12 @@ Error _ResourceSaver::save(const String &p_path, const RES &p_resource, SaverFla return ResourceSaver::save(p_path, p_resource, p_flags); } -PoolVector<String> _ResourceSaver::get_recognized_extensions(const RES &p_resource) { +Vector<String> _ResourceSaver::get_recognized_extensions(const RES &p_resource) { - ERR_FAIL_COND_V_MSG(p_resource.is_null(), PoolVector<String>(), "It's not a reference to a valid Resource object."); + ERR_FAIL_COND_V_MSG(p_resource.is_null(), Vector<String>(), "It's not a reference to a valid Resource object."); List<String> exts; ResourceSaver::get_recognized_extensions(p_resource, &exts); - PoolVector<String> ret; + Vector<String> ret; for (List<String>::Element *E = exts.front(); E; E = E->next()) { ret.push_back(E->get()); @@ -259,7 +249,7 @@ String _OS::get_audio_driver_name(int p_driver) const { return OS::get_singleton()->get_audio_driver_name(p_driver); } -PoolStringArray _OS::get_connected_midi_inputs() { +PackedStringArray _OS::get_connected_midi_inputs() { return OS::get_singleton()->get_connected_midi_inputs(); } @@ -597,18 +587,6 @@ bool _OS::is_vsync_via_compositor_enabled() const { return OS::get_singleton()->is_vsync_via_compositor_enabled(); } -_OS::PowerState _OS::get_power_state() { - return _OS::PowerState(OS::get_singleton()->get_power_state()); -} - -int _OS::get_power_seconds_left() { - return OS::get_singleton()->get_power_seconds_left(); -} - -int _OS::get_power_percent_left() { - return OS::get_singleton()->get_power_percent_left(); -} - bool _OS::has_feature(const String &p_feature) const { return OS::get_singleton()->has_feature(p_feature); @@ -668,11 +646,6 @@ uint64_t _OS::get_static_memory_peak_usage() const { return OS::get_singleton()->get_static_memory_peak_usage(); } -uint64_t _OS::get_dynamic_memory_usage() const { - - return OS::get_singleton()->get_dynamic_memory_usage(); -} - void _OS::set_native_icon(const String &p_filename) { OS::get_singleton()->set_native_icon(p_filename); @@ -1323,7 +1296,6 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_static_memory_usage"), &_OS::get_static_memory_usage); ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &_OS::get_static_memory_peak_usage); - ClassDB::bind_method(D_METHOD("get_dynamic_memory_usage"), &_OS::get_dynamic_memory_usage); ClassDB::bind_method(D_METHOD("get_user_data_dir"), &_OS::get_user_data_dir); ClassDB::bind_method(D_METHOD("get_system_dir", "dir"), &_OS::get_system_dir); @@ -1358,10 +1330,6 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &_OS::has_feature); - ClassDB::bind_method(D_METHOD("get_power_state"), &_OS::get_power_state); - ClassDB::bind_method(D_METHOD("get_power_seconds_left"), &_OS::get_power_seconds_left); - ClassDB::bind_method(D_METHOD("get_power_percent_left"), &_OS::get_power_percent_left); - ClassDB::bind_method(D_METHOD("request_permission", "name"), &_OS::request_permission); ClassDB::bind_method(D_METHOD("request_permissions"), &_OS::request_permissions); ClassDB::bind_method(D_METHOD("get_granted_permissions"), &_OS::get_granted_permissions); @@ -1410,7 +1378,7 @@ void _OS::_bind_methods() { ADD_PROPERTY_DEFAULT("window_size", Vector2()); BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES2); - BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES3); + BIND_ENUM_CONSTANT(VIDEO_DRIVER_VULKAN); BIND_ENUM_CONSTANT(DAY_SUNDAY); BIND_ENUM_CONSTANT(DAY_MONDAY); @@ -1449,12 +1417,6 @@ void _OS::_bind_methods() { BIND_ENUM_CONSTANT(SYSTEM_DIR_MUSIC); BIND_ENUM_CONSTANT(SYSTEM_DIR_PICTURES); BIND_ENUM_CONSTANT(SYSTEM_DIR_RINGTONES); - - BIND_ENUM_CONSTANT(POWERSTATE_UNKNOWN); - BIND_ENUM_CONSTANT(POWERSTATE_ON_BATTERY); - BIND_ENUM_CONSTANT(POWERSTATE_NO_BATTERY); - BIND_ENUM_CONSTANT(POWERSTATE_CHARGING); - BIND_ENUM_CONSTANT(POWERSTATE_CHARGED); } _OS::_OS() { @@ -1471,16 +1433,16 @@ _Geometry *_Geometry::get_singleton() { return singleton; } -PoolVector<Plane> _Geometry::build_box_planes(const Vector3 &p_extents) { +Vector<Plane> _Geometry::build_box_planes(const Vector3 &p_extents) { return Geometry::build_box_planes(p_extents); } -PoolVector<Plane> _Geometry::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) { +Vector<Plane> _Geometry::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) { return Geometry::build_cylinder_planes(p_radius, p_height, p_sides, p_axis); } -PoolVector<Plane> _Geometry::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { +Vector<Plane> _Geometry::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { return Geometry::build_capsule_planes(p_radius, p_height, p_sides, p_lats, p_axis); } @@ -1516,22 +1478,22 @@ Variant _Geometry::line_intersects_line_2d(const Vector2 &p_from_a, const Vector } } -PoolVector<Vector2> _Geometry::get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) { +Vector<Vector2> _Geometry::get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) { Vector2 r1, r2; Geometry::get_closest_points_between_segments(p1, q1, p2, q2, r1, r2); - PoolVector<Vector2> r; + Vector<Vector2> r; r.resize(2); r.set(0, r1); r.set(1, r2); return r; } -PoolVector<Vector3> _Geometry::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) { +Vector<Vector3> _Geometry::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) { Vector3 r1, r2; Geometry::get_closest_points_between_segments(p1, p2, q1, q2, r1, r2); - PoolVector<Vector3> r; + Vector<Vector3> r; r.resize(2); r.set(0, r1); r.set(1, r2); @@ -1579,9 +1541,9 @@ bool _Geometry::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, con return Geometry::is_point_in_triangle(s, a, b, c); } -PoolVector<Vector3> _Geometry::segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius) { +Vector<Vector3> _Geometry::segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius) { - PoolVector<Vector3> r; + Vector<Vector3> r; Vector3 res, norm; if (!Geometry::segment_intersects_sphere(p_from, p_to, p_sphere_pos, p_sphere_radius, &res, &norm)) return r; @@ -1591,9 +1553,9 @@ PoolVector<Vector3> _Geometry::segment_intersects_sphere(const Vector3 &p_from, r.set(1, norm); return r; } -PoolVector<Vector3> _Geometry::segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius) { +Vector<Vector3> _Geometry::segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius) { - PoolVector<Vector3> r; + Vector<Vector3> r; Vector3 res, norm; if (!Geometry::segment_intersects_cylinder(p_from, p_to, p_height, p_radius, &res, &norm)) return r; @@ -1603,9 +1565,9 @@ PoolVector<Vector3> _Geometry::segment_intersects_cylinder(const Vector3 &p_from r.set(1, norm); return r; } -PoolVector<Vector3> _Geometry::segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes) { +Vector<Vector3> _Geometry::segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes) { - PoolVector<Vector3> r; + Vector<Vector3> r; Vector3 res, norm; if (!Geometry::segment_intersects_convex(p_from, p_to, p_planes.ptr(), p_planes.size(), &res, &norm)) return r; @@ -1994,9 +1956,9 @@ real_t _File::get_real() const { return f->get_real(); } -PoolVector<uint8_t> _File::get_buffer(int p_length) const { +Vector<uint8_t> _File::get_buffer(int p_length) const { - PoolVector<uint8_t> data; + Vector<uint8_t> data; ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use."); ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0."); @@ -2006,11 +1968,9 @@ PoolVector<uint8_t> _File::get_buffer(int p_length) const { Error err = data.resize(p_length); ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements."); - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); int len = f->get_buffer(&w[0], p_length); - ERR_FAIL_COND_V(len < 0, PoolVector<uint8_t>()); - - w.release(); + ERR_FAIL_COND_V(len < 0, Vector<uint8_t>()); if (len < p_length) data.resize(p_length); @@ -2158,7 +2118,7 @@ void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim f->store_csv_line(p_values, p_delim); } -void _File::store_buffer(const PoolVector<uint8_t> &p_buffer) { +void _File::store_buffer(const Vector<uint8_t> &p_buffer) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); @@ -2166,7 +2126,7 @@ void _File::store_buffer(const PoolVector<uint8_t> &p_buffer) { if (len == 0) return; - PoolVector<uint8_t>::Read r = p_buffer.read(); + const uint8_t *r = p_buffer.ptr(); f->store_buffer(&r[0], len); } @@ -2183,13 +2143,12 @@ void _File::store_var(const Variant &p_var, bool p_full_objects) { Error err = encode_variant(p_var, NULL, len, p_full_objects); ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant."); - PoolVector<uint8_t> buff; + Vector<uint8_t> buff; buff.resize(len); - PoolVector<uint8_t>::Write w = buff.write(); + 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."); - w.release(); store_32(len); store_buffer(buff); @@ -2199,10 +2158,10 @@ Variant _File::get_var(bool p_allow_objects) const { ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use."); uint32_t len = get_32(); - PoolVector<uint8_t> buff = get_buffer(len); + Vector<uint8_t> buff = get_buffer(len); ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant()); - PoolVector<uint8_t>::Read r = buff.read(); + const uint8_t *r = buff.ptr(); Variant v; Error err = decode_variant(v, &r[0], len, NULL, p_allow_objects); @@ -2497,9 +2456,9 @@ String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) Error err = encode_variant(p_var, NULL, len, p_full_objects); ERR_FAIL_COND_V_MSG(err != OK, "", "Error when trying to encode Variant."); - PoolVector<uint8_t> buff; + Vector<uint8_t> buff; buff.resize(len); - PoolVector<uint8_t>::Write w = buff.write(); + uint8_t *w = buff.ptrw(); err = encode_variant(p_var, &w[0], len, p_full_objects); ERR_FAIL_COND_V_MSG(err != OK, "", "Error when trying to encode Variant."); @@ -2515,9 +2474,9 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) int strlen = p_str.length(); CharString cstr = p_str.ascii(); - PoolVector<uint8_t> buf; + Vector<uint8_t> buf; buf.resize(strlen / 4 * 3 + 1); - PoolVector<uint8_t>::Write w = buf.write(); + uint8_t *w = buf.ptrw(); size_t len = 0; ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &len, (unsigned char *)cstr.get_data(), strlen) != OK, Variant()); @@ -2529,25 +2488,25 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) return v; }; -String _Marshalls::raw_to_base64(const PoolVector<uint8_t> &p_arr) { +String _Marshalls::raw_to_base64(const Vector<uint8_t> &p_arr) { - String ret = CryptoCore::b64_encode_str(p_arr.read().ptr(), p_arr.size()); + String ret = CryptoCore::b64_encode_str(p_arr.ptr(), p_arr.size()); ERR_FAIL_COND_V(ret == "", ret); return ret; }; -PoolVector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) { +Vector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) { int strlen = p_str.length(); CharString cstr = p_str.ascii(); size_t arr_len = 0; - PoolVector<uint8_t> buf; + Vector<uint8_t> buf; { buf.resize(strlen / 4 * 3 + 1); - PoolVector<uint8_t>::Write w = buf.write(); + uint8_t *w = buf.ptrw(); - ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &arr_len, (unsigned char *)cstr.get_data(), strlen) != OK, PoolVector<uint8_t>()); + ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &arr_len, (unsigned char *)cstr.get_data(), strlen) != OK, Vector<uint8_t>()); } buf.resize(arr_len); @@ -2567,9 +2526,9 @@ String _Marshalls::base64_to_utf8(const String &p_str) { int strlen = p_str.length(); CharString cstr = p_str.ascii(); - PoolVector<uint8_t> buf; + Vector<uint8_t> buf; buf.resize(strlen / 4 * 3 + 1 + 1); - PoolVector<uint8_t>::Write w = buf.write(); + uint8_t *w = buf.ptrw(); size_t len = 0; ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &len, (unsigned char *)cstr.get_data(), strlen) != OK, String()); @@ -2612,7 +2571,7 @@ void _Semaphore::_bind_methods() { _Semaphore::_Semaphore() { - semaphore = Semaphore::create(); + semaphore = SemaphoreOld::create(); } _Semaphore::~_Semaphore() { @@ -2778,12 +2737,12 @@ _Thread::~_Thread() { ///////////////////////////////////// -PoolStringArray _ClassDB::get_class_list() const { +PackedStringArray _ClassDB::get_class_list() const { List<StringName> classes; ClassDB::get_class_list(&classes); - PoolStringArray ret; + PackedStringArray ret; ret.resize(classes.size()); int idx = 0; for (List<StringName>::Element *E = classes.front(); E; E = E->next()) { @@ -2792,12 +2751,12 @@ PoolStringArray _ClassDB::get_class_list() const { return ret; } -PoolStringArray _ClassDB::get_inheriters_from_class(const StringName &p_class) const { +PackedStringArray _ClassDB::get_inheriters_from_class(const StringName &p_class) const { List<StringName> classes; ClassDB::get_inheriters_from_class(p_class, &classes); - PoolStringArray ret; + PackedStringArray ret; ret.resize(classes.size()); int idx = 0; for (List<StringName>::Element *E = classes.front(); E; E = E->next()) { @@ -2915,12 +2874,12 @@ Array _ClassDB::get_method_list(StringName p_class, bool p_no_inheritance) const return ret; } -PoolStringArray _ClassDB::get_integer_constant_list(const StringName &p_class, bool p_no_inheritance) const { +PackedStringArray _ClassDB::get_integer_constant_list(const StringName &p_class, bool p_no_inheritance) const { List<String> constants; ClassDB::get_integer_constant_list(p_class, &constants, p_no_inheritance); - PoolStringArray ret; + PackedStringArray ret; ret.resize(constants.size()); int idx = 0; for (List<String>::Element *E = constants.front(); E; E = E->next()) { @@ -3217,7 +3176,7 @@ Ref<JSONParseResult> _JSON::parse(const String &p_json) { result->error = JSON::parse(p_json, result->result, result->error_string, result->error_line); if (result->error != OK) { - ERR_PRINTS(vformat("Error parsing JSON at line %s: %s", result->error_line, result->error_string)); + ERR_PRINT(vformat("Error parsing JSON at line %s: %s", result->error_line, result->error_string)); } return result; } diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 87da51f97e..342c43802e 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -52,12 +52,9 @@ public: static _ResourceLoader *get_singleton() { return singleton; } Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = ""); RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false); - PoolVector<String> get_recognized_extensions_for_type(const String &p_type); + Vector<String> get_recognized_extensions_for_type(const String &p_type); void set_abort_on_missing_resources(bool p_abort); - PoolStringArray get_dependencies(const String &p_path); -#ifndef DISABLE_DEPRECATED - bool has(const String &p_path); -#endif // DISABLE_DEPRECATED + PackedStringArray get_dependencies(const String &p_path); bool has_cached(const String &p_path); bool exists(const String &p_path, const String &p_type_hint = ""); @@ -86,7 +83,7 @@ public: static _ResourceSaver *get_singleton() { return singleton; } Error save(const String &p_path, const RES &p_resource, SaverFlags p_flags); - PoolVector<String> get_recognized_extensions(const RES &p_resource); + Vector<String> get_recognized_extensions(const RES &p_resource); _ResourceSaver(); }; @@ -104,16 +101,8 @@ protected: public: enum VideoDriver { - VIDEO_DRIVER_GLES3, VIDEO_DRIVER_GLES2, - }; - - enum PowerState { - POWERSTATE_UNKNOWN, // Cannot determine power status. - POWERSTATE_ON_BATTERY, // Not plugged in, running on the battery. - POWERSTATE_NO_BATTERY, // Plugged in, no battery available. - POWERSTATE_CHARGING, // Plugged in, charging battery. - POWERSTATE_CHARGED // Plugged in, battery charged. + VIDEO_DRIVER_VULKAN, }; enum Weekday { @@ -168,7 +157,7 @@ public: virtual int get_audio_driver_count() const; virtual String get_audio_driver_name(int p_driver) const; - virtual PoolStringArray get_connected_midi_inputs(); + virtual PackedStringArray get_connected_midi_inputs(); virtual void open_midi_inputs(); virtual void close_midi_inputs(); @@ -287,7 +276,6 @@ public: uint64_t get_static_memory_usage() const; uint64_t get_static_memory_peak_usage() const; - uint64_t get_dynamic_memory_usage() const; void delay_usec(uint32_t p_usec) const; void delay_msec(uint32_t p_msec) const; @@ -349,10 +337,6 @@ public: void set_vsync_via_compositor(bool p_enable); bool is_vsync_via_compositor_enabled() const; - PowerState get_power_state(); - int get_power_seconds_left(); - int get_power_percent_left(); - bool has_feature(const String &p_feature) const; bool request_permission(const String &p_name); @@ -365,7 +349,6 @@ public: }; VARIANT_ENUM_CAST(_OS::VideoDriver); -VARIANT_ENUM_CAST(_OS::PowerState); VARIANT_ENUM_CAST(_OS::Weekday); VARIANT_ENUM_CAST(_OS::Month); VARIANT_ENUM_CAST(_OS::SystemDir); @@ -382,13 +365,13 @@ protected: public: static _Geometry *get_singleton(); - PoolVector<Plane> build_box_planes(const Vector3 &p_extents); - PoolVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z); - PoolVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z); + Vector<Plane> build_box_planes(const Vector3 &p_extents); + Vector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z); + Vector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z); Variant segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b); Variant line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b); - PoolVector<Vector2> get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2); - PoolVector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2); + Vector<Vector2> get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2); + Vector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2); Vector2 get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b); Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b); Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b); @@ -397,9 +380,9 @@ public: Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2); bool point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const; - PoolVector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius); - PoolVector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius); - PoolVector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes); + Vector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius); + Vector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius); + Vector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes); bool is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius); real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius); int get_uv84_normal_bit(const Vector3 &p_vector); @@ -506,7 +489,7 @@ public: Variant get_var(bool p_allow_objects = false) const; - PoolVector<uint8_t> get_buffer(int p_length) const; // Get an array of bytes. + Vector<uint8_t> get_buffer(int 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() const; @@ -539,7 +522,7 @@ public: virtual void store_pascal_string(const String &p_string); virtual String get_pascal_string(); - void store_buffer(const PoolVector<uint8_t> &p_buffer); // Store an array of bytes. + 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); @@ -613,8 +596,8 @@ public: String variant_to_base64(const Variant &p_var, bool p_full_objects = false); Variant base64_to_variant(const String &p_str, bool p_allow_objects = false); - String raw_to_base64(const PoolVector<uint8_t> &p_arr); - PoolVector<uint8_t> base64_to_raw(const String &p_str); + String raw_to_base64(const Vector<uint8_t> &p_arr); + Vector<uint8_t> base64_to_raw(const String &p_str); String utf8_to_base64(const String &p_str); String base64_to_utf8(const String &p_str); @@ -642,7 +625,7 @@ public: class _Semaphore : public Reference { GDCLASS(_Semaphore, Reference); - Semaphore *semaphore; + SemaphoreOld *semaphore; static void _bind_methods(); @@ -696,8 +679,8 @@ protected: static void _bind_methods(); public: - PoolStringArray get_class_list() const; - PoolStringArray get_inheriters_from_class(const StringName &p_class) const; + PackedStringArray get_class_list() const; + PackedStringArray get_inheriters_from_class(const StringName &p_class) const; StringName get_parent_class(const StringName &p_class) const; bool class_exists(const StringName &p_class) const; bool is_parent_class(const StringName &p_class, const StringName &p_inherits) const; @@ -716,7 +699,7 @@ public: Array get_method_list(StringName p_class, bool p_no_inheritance = false) const; - PoolStringArray get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const; + PackedStringArray get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const; bool has_integer_constant(const StringName &p_class, const StringName &p_name) const; int get_integer_constant(const StringName &p_class, const StringName &p_name) const; StringName get_category(const StringName &p_node) const; diff --git a/core/class_db.cpp b/core/class_db.cpp index 65f0c6008c..2fd0ee2d89 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -335,6 +335,19 @@ StringName ClassDB::get_parent_class_nocheck(const StringName &p_class) { return ti->inherits; } +StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) { + + if (classes.has(p_class)) { + return p_class; + } + + if (compat_classes.has(p_class)) { + return compat_classes[p_class]; + } + + return p_class; +} + StringName ClassDB::get_parent_class(const StringName &p_class) { OBJTYPE_RLOCK; @@ -541,7 +554,7 @@ Object *ClassDB::instance(const StringName &p_class) { } #ifdef TOOLS_ENABLED if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) { - ERR_PRINTS("Class '" + String(p_class) + "' can only be instantiated by editor."); + ERR_PRINT("Class '" + String(p_class) + "' can only be instantiated by editor."); return NULL; } #endif @@ -1397,7 +1410,10 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con cleanup_c = false; } else if (ClassDB::can_instance(p_class)) { c = ClassDB::instance(p_class); - cleanup_c = true; +#ifndef _MSC_VER +#warning FIXME: ObjectID refactoring broke GDScript handling of reference pointers, this needs a proper fix. +#endif + cleanup_c = (p_class != StringName("GDScript")); } if (c) { diff --git a/core/class_db.h b/core/class_db.h index 34301d6cba..404b04f2d0 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -218,6 +218,7 @@ public: static void get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes); static StringName get_parent_class_nocheck(const StringName &p_class); static StringName get_parent_class(const StringName &p_class); + static StringName get_compatibility_remapped_class(const StringName &p_class); static bool class_exists(const StringName &p_class); static bool is_parent_class(const StringName &p_class, const StringName &p_inherits); static bool can_instance(const StringName &p_class); diff --git a/core/color.cpp b/core/color.cpp index 1baa8af45d..03aeb2085b 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -508,13 +508,6 @@ Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const { return Color(m + r, m + g, m + b, p_a); } -// FIXME: Remove once Godot 3.1 has been released -float Color::gray() const { - - WARN_DEPRECATED_MSG("'Color.gray()' is deprecated and will be removed in a future version. Use 'Color.v' for a better grayscale approximation."); - return (r + g + b) / 3.0; -} - Color::operator String() const { return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a); @@ -529,14 +522,6 @@ Color Color::operator+(const Color &p_color) const { a + p_color.a); } -void Color::operator+=(const Color &p_color) { - - r = r + p_color.r; - g = g + p_color.g; - b = b + p_color.b; - a = a + p_color.a; -} - Color Color::operator-(const Color &p_color) const { return Color( diff --git a/core/color.h b/core/color.h index cfdd211b69..a7ab94ab08 100644 --- a/core/color.h +++ b/core/color.h @@ -56,7 +56,6 @@ struct Color { uint64_t to_rgba64() const; uint64_t to_argb64() const; uint64_t to_abgr64() const; - float gray() const; float get_h() const; float get_s() const; float get_v() const; @@ -70,7 +69,12 @@ struct Color { } Color operator+(const Color &p_color) const; - void operator+=(const Color &p_color); + _FORCE_INLINE_ void operator+=(const Color &p_color) { + r = r + p_color.r; + g = g + p_color.g; + b = b + p_color.b; + a = a + p_color.a; + } Color operator-() const; Color operator-(const Color &p_color) const; diff --git a/core/command_queue_mt.cpp b/core/command_queue_mt.cpp index c20735939d..861ca8d1d3 100644 --- a/core/command_queue_mt.cpp +++ b/core/command_queue_mt.cpp @@ -111,11 +111,11 @@ CommandQueueMT::CommandQueueMT(bool p_sync) { for (int i = 0; i < SYNC_SEMAPHORES; i++) { - sync_sems[i].sem = Semaphore::create(); + sync_sems[i].sem = SemaphoreOld::create(); sync_sems[i].in_use = false; } if (p_sync) - sync = Semaphore::create(); + sync = SemaphoreOld::create(); else sync = NULL; } diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h index e5f93bcc36..2b6e0201f0 100644 --- a/core/command_queue_mt.h +++ b/core/command_queue_mt.h @@ -52,9 +52,17 @@ #define _COMMA_11 , #define _COMMA_12 , #define _COMMA_13 , +#define _COMMA_14 , +#define _COMMA_15 , // 1-based comma separated list of ITEMs #define COMMA_SEP_LIST(ITEM, LENGTH) _COMMA_SEP_LIST_##LENGTH(ITEM) +#define _COMMA_SEP_LIST_15(ITEM) \ + _COMMA_SEP_LIST_14(ITEM) \ + , ITEM(15) +#define _COMMA_SEP_LIST_14(ITEM) \ + _COMMA_SEP_LIST_13(ITEM) \ + , ITEM(14) #define _COMMA_SEP_LIST_13(ITEM) \ _COMMA_SEP_LIST_12(ITEM) \ , ITEM(13) @@ -98,6 +106,12 @@ // 1-based semicolon separated list of ITEMs #define SEMIC_SEP_LIST(ITEM, LENGTH) _SEMIC_SEP_LIST_##LENGTH(ITEM) +#define _SEMIC_SEP_LIST_15(ITEM) \ + _SEMIC_SEP_LIST_14(ITEM); \ + ITEM(15) +#define _SEMIC_SEP_LIST_14(ITEM) \ + _SEMIC_SEP_LIST_13(ITEM); \ + ITEM(14) #define _SEMIC_SEP_LIST_13(ITEM) \ _SEMIC_SEP_LIST_12(ITEM); \ ITEM(13) @@ -141,6 +155,12 @@ // 1-based space separated list of ITEMs #define SPACE_SEP_LIST(ITEM, LENGTH) _SPACE_SEP_LIST_##LENGTH(ITEM) +#define _SPACE_SEP_LIST_15(ITEM) \ + _SPACE_SEP_LIST_14(ITEM) \ + ITEM(15) +#define _SPACE_SEP_LIST_14(ITEM) \ + _SPACE_SEP_LIST_13(ITEM) \ + ITEM(14) #define _SPACE_SEP_LIST_13(ITEM) \ _SPACE_SEP_LIST_12(ITEM) \ ITEM(13) @@ -271,13 +291,13 @@ ss->in_use = false; \ } -#define MAX_CMD_PARAMS 13 +#define MAX_CMD_PARAMS 15 class CommandQueueMT { struct SyncSemaphore { - Semaphore *sem; + SemaphoreOld *sem; bool in_use; }; @@ -298,15 +318,15 @@ class CommandQueueMT { }; DECL_CMD(0) - SPACE_SEP_LIST(DECL_CMD, 13) + SPACE_SEP_LIST(DECL_CMD, 15) /* comands that return */ DECL_CMD_RET(0) - SPACE_SEP_LIST(DECL_CMD_RET, 13) + SPACE_SEP_LIST(DECL_CMD_RET, 15) /* commands that don't return but sync */ DECL_CMD_SYNC(0) - SPACE_SEP_LIST(DECL_CMD_SYNC, 13) + SPACE_SEP_LIST(DECL_CMD_SYNC, 15) /***** BASE *******/ @@ -322,7 +342,7 @@ class CommandQueueMT { uint32_t dealloc_ptr; SyncSemaphore sync_sems[SYNC_SEMAPHORES]; Mutex *mutex; - Semaphore *sync; + SemaphoreOld *sync; template <class T> T *allocate() { @@ -443,15 +463,15 @@ class CommandQueueMT { public: /* NORMAL PUSH COMMANDS */ DECL_PUSH(0) - SPACE_SEP_LIST(DECL_PUSH, 13) + SPACE_SEP_LIST(DECL_PUSH, 15) /* PUSH AND RET COMMANDS */ DECL_PUSH_AND_RET(0) - SPACE_SEP_LIST(DECL_PUSH_AND_RET, 13) + SPACE_SEP_LIST(DECL_PUSH_AND_RET, 15) /* PUSH AND RET SYNC COMMANDS*/ DECL_PUSH_AND_SYNC(0) - SPACE_SEP_LIST(DECL_PUSH_AND_SYNC, 13) + SPACE_SEP_LIST(DECL_PUSH_AND_SYNC, 15) void wait_and_flush_one() { ERR_FAIL_COND(!sync); diff --git a/core/compressed_translation.cpp b/core/compressed_translation.cpp index 69b4ec292f..ea84ded3b4 100644 --- a/core/compressed_translation.cpp +++ b/core/compressed_translation.cpp @@ -141,8 +141,8 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { hash_table.resize(size); bucket_table.resize(bucket_table_size); - PoolVector<int>::Write htwb = hash_table.write(); - PoolVector<int>::Write btwb = bucket_table.write(); + int *htwb = hash_table.ptrw(); + int *btwb = bucket_table.ptrw(); uint32_t *htw = (uint32_t *)&htwb[0]; uint32_t *btw = (uint32_t *)&btwb[0]; @@ -174,7 +174,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { } strings.resize(total_compression_size); - PoolVector<uint8_t>::Write cw = strings.write(); + uint8_t *cw = strings.ptrw(); for (int i = 0; i < compressed.size(); i++) { memcpy(&cw[compressed[i].offset], compressed[i].compressed.get_data(), compressed[i].compressed.size()); @@ -228,11 +228,11 @@ StringName PHashTranslation::get_message(const StringName &p_src_text) const { CharString str = p_src_text.operator String().utf8(); uint32_t h = hash(0, str.get_data()); - PoolVector<int>::Read htr = hash_table.read(); + const int *htr = hash_table.ptr(); const uint32_t *htptr = (const uint32_t *)&htr[0]; - PoolVector<int>::Read btr = bucket_table.read(); + const int *btr = bucket_table.ptr(); const uint32_t *btptr = (const uint32_t *)&btr[0]; - PoolVector<uint8_t>::Read sr = strings.read(); + const uint8_t *sr = strings.ptr(); const char *sptr = (const char *)&sr[0]; uint32_t p = htptr[h % htsize]; @@ -279,9 +279,9 @@ StringName PHashTranslation::get_message(const StringName &p_src_text) const { void PHashTranslation::_get_property_list(List<PropertyInfo> *p_list) const { - p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "hash_table")); - p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "bucket_table")); - p_list->push_back(PropertyInfo(Variant::POOL_BYTE_ARRAY, "strings")); + p_list->push_back(PropertyInfo(Variant::PACKED_INT_ARRAY, "hash_table")); + p_list->push_back(PropertyInfo(Variant::PACKED_INT_ARRAY, "bucket_table")); + p_list->push_back(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "strings")); p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR)); } void PHashTranslation::_bind_methods() { diff --git a/core/compressed_translation.h b/core/compressed_translation.h index a72be739a1..d599240dfe 100644 --- a/core/compressed_translation.h +++ b/core/compressed_translation.h @@ -43,9 +43,9 @@ class PHashTranslation : public Translation { //of catching untranslated strings //load/store friendly types - PoolVector<int> hash_table; - PoolVector<int> bucket_table; - PoolVector<uint8_t> strings; + Vector<int> hash_table; + Vector<int> bucket_table; + Vector<uint8_t> strings; struct Bucket { diff --git a/core/core_builders.py b/core/core_builders.py index f3a9e3b221..7720183595 100644 --- a/core/core_builders.py +++ b/core/core_builders.py @@ -1,8 +1,8 @@ """Functions used to generate source files during build time All such functions are invoked in a subprocess on Windows to prevent build flakiness. - """ + from platform_methods import subprocess_main from compat import iteritems, itervalues, open_utf8, escape_string, byte_to_str diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index 3bee34f8e4..3711b26e47 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -82,8 +82,8 @@ void Crypto::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_self_signed_certificate", "key", "issuer_name", "not_before", "not_after"), &Crypto::generate_self_signed_certificate, DEFVAL("CN=myserver,O=myorganisation,C=IT"), DEFVAL("20140101000000"), DEFVAL("20340101000000")); } -PoolByteArray Crypto::generate_random_bytes(int p_bytes) { - ERR_FAIL_V_MSG(PoolByteArray(), "generate_random_bytes is not available when mbedtls module is disabled."); +PackedByteArray Crypto::generate_random_bytes(int p_bytes) { + ERR_FAIL_V_MSG(PackedByteArray(), "generate_random_bytes is not available when mbedtls module is disabled."); } Ref<CryptoKey> Crypto::generate_rsa(int p_bytes) { diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h index adc36255b6..babd0bc4eb 100644 --- a/core/crypto/crypto.h +++ b/core/crypto/crypto.h @@ -76,7 +76,7 @@ public: static Crypto *create(); static void load_default_certificates(String p_path); - virtual PoolByteArray generate_random_bytes(int p_bytes); + virtual PackedByteArray generate_random_bytes(int p_bytes); virtual Ref<CryptoKey> generate_rsa(int p_bytes); virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after); diff --git a/core/crypto/crypto_core.cpp b/core/crypto/crypto_core.cpp index dec52d8ca4..ec25ee0d38 100644 --- a/core/crypto/crypto_core.cpp +++ b/core/crypto/crypto_core.cpp @@ -148,9 +148,9 @@ Error CryptoCore::AESContext::decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst // CryptoCore String CryptoCore::b64_encode_str(const uint8_t *p_src, int p_src_len) { int b64len = p_src_len / 3 * 4 + 4 + 1; - PoolVector<uint8_t> b64buff; + Vector<uint8_t> b64buff; b64buff.resize(b64len); - PoolVector<uint8_t>::Write w64 = b64buff.write(); + uint8_t *w64 = b64buff.ptrw(); size_t strlen = 0; int ret = b64_encode(&w64[0], b64len, &strlen, p_src, p_src_len); w64[strlen] = 0; diff --git a/core/crypto/hashing_context.cpp b/core/crypto/hashing_context.cpp index 7bee8f1200..a4d8a93c8a 100644 --- a/core/crypto/hashing_context.cpp +++ b/core/crypto/hashing_context.cpp @@ -47,11 +47,11 @@ Error HashingContext::start(HashType p_type) { return ERR_UNAVAILABLE; } -Error HashingContext::update(PoolByteArray p_chunk) { +Error HashingContext::update(PackedByteArray p_chunk) { ERR_FAIL_COND_V(ctx == NULL, ERR_UNCONFIGURED); size_t len = p_chunk.size(); ERR_FAIL_COND_V(len == 0, FAILED); - PoolByteArray::Read r = p_chunk.read(); + const uint8_t *r = p_chunk.ptr(); switch (type) { case HASH_MD5: return ((CryptoCore::MD5Context *)ctx)->update(&r[0], len); @@ -63,26 +63,26 @@ Error HashingContext::update(PoolByteArray p_chunk) { return ERR_UNAVAILABLE; } -PoolByteArray HashingContext::finish() { - ERR_FAIL_COND_V(ctx == NULL, PoolByteArray()); - PoolByteArray out; +PackedByteArray HashingContext::finish() { + ERR_FAIL_COND_V(ctx == NULL, PackedByteArray()); + PackedByteArray out; Error err = FAILED; switch (type) { case HASH_MD5: out.resize(16); - err = ((CryptoCore::MD5Context *)ctx)->finish(out.write().ptr()); + err = ((CryptoCore::MD5Context *)ctx)->finish(out.ptrw()); break; case HASH_SHA1: out.resize(20); - err = ((CryptoCore::SHA1Context *)ctx)->finish(out.write().ptr()); + err = ((CryptoCore::SHA1Context *)ctx)->finish(out.ptrw()); break; case HASH_SHA256: out.resize(32); - err = ((CryptoCore::SHA256Context *)ctx)->finish(out.write().ptr()); + err = ((CryptoCore::SHA256Context *)ctx)->finish(out.ptrw()); break; } _delete_ctx(); - ERR_FAIL_COND_V(err != OK, PoolByteArray()); + ERR_FAIL_COND_V(err != OK, PackedByteArray()); return out; } diff --git a/core/crypto/hashing_context.h b/core/crypto/hashing_context.h index af6ed3aa0b..230ba7ee85 100644 --- a/core/crypto/hashing_context.h +++ b/core/crypto/hashing_context.h @@ -54,8 +54,8 @@ protected: public: Error start(HashType p_type); - Error update(PoolByteArray p_chunk); - PoolByteArray finish(); + Error update(PackedByteArray p_chunk); + PackedByteArray finish(); HashingContext(); ~HashingContext(); diff --git a/core/engine.cpp b/core/engine.cpp index 1772cc7c48..85ad175f38 100644 --- a/core/engine.cpp +++ b/core/engine.cpp @@ -214,6 +214,9 @@ Engine *Engine::get_singleton() { return singleton; } +bool Engine::is_abort_on_gpu_errors_enabled() const { + return abort_on_gpu_errors; +} Engine::Engine() { singleton = this; @@ -232,4 +235,5 @@ Engine::Engine() { _frame_ticks = 0; _frame_step = 0; editor_hint = false; + abort_on_gpu_errors = false; } diff --git a/core/engine.h b/core/engine.h index 1aab907ac8..cfe3a918fc 100644 --- a/core/engine.h +++ b/core/engine.h @@ -64,6 +64,7 @@ private: bool _pixel_snap; uint64_t _physics_frames; float _physics_interpolation_fraction; + bool abort_on_gpu_errors; uint64_t _idle_frames; bool _in_physics; @@ -126,6 +127,8 @@ public: Dictionary get_license_info() const; String get_license_text() const; + bool is_abort_on_gpu_errors_enabled() const; + Engine(); virtual ~Engine() {} }; diff --git a/core/error_macros.h b/core/error_macros.h index 8ba6618942..4a3ea28957 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -32,21 +32,8 @@ #define ERROR_MACROS_H #include "core/typedefs.h" -/** - * Error macros. Unlike exceptions and asserts, these macros try to maintain consistency and stability - * inside the code. It is recommended to always return processable data, so in case of an error, - * the engine can keep working well. - * In most cases, bugs and/or invalid data are not fatal and should never allow a perfectly running application - * to fail or crash. - */ - -/** - * Pointer to the error macro printing function. Reassign to any function to have errors printed - */ - -/** Function used by the error macros */ -// function, file, line, error, explanation +class String; enum ErrorHandlerType { ERR_HANDLER_ERROR, @@ -55,7 +42,8 @@ enum ErrorHandlerType { ERR_HANDLER_SHADER, }; -class String; +// Pointer to the error handler printing function. Reassign to any function to have errors printed. +// Parameters: userdata, function, file, line, error, explanation, type. typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, ErrorHandlerType p_type); struct ErrorHandlerList { @@ -75,6 +63,7 @@ struct ErrorHandlerList { void add_error_handler(ErrorHandlerList *p_handler); void remove_error_handler(ErrorHandlerList *p_handler); +// Functions used by the error macros. void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR); void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR); void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR); @@ -84,15 +73,6 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool fatal = false); void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal = false); -#ifndef _STR -#define _STR(m_x) #m_x -#define _MKSTR(m_x) _STR(m_x) -#endif - -#define _FNL __FILE__ ":" - -/** An index has failed if m_index<0 or m_index >=m_size, the function exits */ - #ifdef __GNUC__ //#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying #define FUNCTION_STR __FUNCTION__ @@ -100,15 +80,16 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li #define FUNCTION_STR __FUNCTION__ #endif -// Don't use this directly; instead, use any of the CRASH_* macros #ifdef _MSC_VER -#define GENERATE_TRAP \ - __debugbreak(); \ - /* Avoid warning about control paths */ \ - for (;;) { \ - } +/** + * Don't use GENERATE_TRAP() directly, should only be used be the macros below. + */ +#define GENERATE_TRAP() __debugbreak() #else -#define GENERATE_TRAP __builtin_trap(); +/** + * Don't use GENERATE_TRAP() directly, should only be used be the macros below. + */ +#define GENERATE_TRAP() __builtin_trap() #endif // Used to strip debug messages in release mode @@ -118,411 +99,528 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li #define DEBUG_STR(m_msg) "" #endif -// (*): See https://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for - -/** - * If `m_index` is less than 0 or greater than or equal to `m_size`, prints a generic - * error message and returns from the function. This macro should be preferred to - * `ERR_FAIL_COND` for bounds checking. - */ -#define ERR_FAIL_INDEX(m_index, m_size) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ - return; \ - } \ - } while (0); // (*) - -/** - * If `m_index` is less than 0 or greater than or equal to `m_size`, prints a custom - * error message and returns from the function. This macro should be preferred to - * `ERR_FAIL_COND_MSG` for bounds checking. - */ -#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ - return; \ - } \ - } while (0); // (*) - -/** - * If `m_index` is less than 0 or greater than or equal to `m_size`, - * prints a generic error message and returns the value specified in `m_retval`. - * This macro should be preferred to `ERR_FAIL_COND_V` for bounds checking. - */ -#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ - return m_retval; \ - } \ - } while (0); // (*) - -/** - * If `m_index` is less than 0 or greater than or equal to `m_size`, - * prints a custom error message and returns the value specified in `m_retval`. - * This macro should be preferred to `ERR_FAIL_COND_V_MSG` for bounds checking. - */ -#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ - return m_retval; \ - } \ - } while (0); // (*) - -/** - * If `m_index` is greater than or equal to `m_size`, - * prints a generic error message and returns the value specified in `m_retval`. - * This macro should be preferred to `ERR_FAIL_COND_V` for unsigned bounds checking. - */ -#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \ - do { \ - if (unlikely((m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ - return m_retval; \ - } \ - } while (0); // (*) - -/** - * If `m_index` is greater than or equal to `m_size`, - * prints a custom error message and returns the value specified in `m_retval`. - * This macro should be preferred to `ERR_FAIL_COND_V_MSG` for unsigned bounds checking. - */ -#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \ - do { \ - if (unlikely((m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ - return m_retval; \ - } \ - } while (0); // (*) - -/** - * If `m_index` is less than 0 or greater than or equal to `m_size`, - * crashes the engine immediately with a generic error message. - * Only use this if there's no sensible fallback (i.e. the error is unrecoverable). - * This macro should be preferred to `CRASH_COND` for bounds checking. - */ -#define CRASH_BAD_INDEX(m_index, m_size) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \ - GENERATE_TRAP \ - } \ - } while (0); // (*) - -/** - * If `m_index` is less than 0 or greater than or equal to `m_size`, - * crashes the engine immediately with a custom error message. - * Only use this if there's no sensible fallback (i.e. the error is unrecoverable). - * This macro should be preferred to `CRASH_COND` for bounds checking. - */ -#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \ - GENERATE_TRAP \ - } \ - } while (0); // (*) - -/** - * If `m_param` is `null`, prints a generic error message and returns from the function. - */ -#define ERR_FAIL_NULL(m_param) \ - { \ - if (unlikely(!m_param)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ - return; \ - } \ - } - /** - * If `m_param` is `null`, prints a custom error message and returns from the function. + * Error macros. + * WARNING: These macros work in the opposite way to assert(). + * + * Unlike exceptions and asserts, these macros try to maintain consistency and stability. + * In most cases, bugs and/or invalid data are not fatal. They should never allow a perfectly + * running application to fail or crash. + * Always try to return processable data, so the engine can keep running well. + * Use the _MSG versions to print a meaningful message to help with debugging. */ -#define ERR_FAIL_NULL_MSG(m_param, m_msg) \ - { \ - if (unlikely(!m_param)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ - return; \ - } \ - } -/** - * If `m_param` is `null`, prints a generic error message and returns the value specified in `m_retval`. - */ -#define ERR_FAIL_NULL_V(m_param, m_retval) \ - { \ - if (unlikely(!m_param)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ - return m_retval; \ - } \ - } +// Index out of bounds error macros. +// These macros should be used instead of `ERR_FAIL_COND` for bounds checking. -/** - * If `m_param` is `null`, prints a custom error message and returns the value specified in `m_retval`. - */ -#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \ - { \ - if (unlikely(!m_param)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ - return m_retval; \ - } \ - } +// Integer index out of bounds error macros. /** - * If `m_cond` evaluates to `true`, prints a generic error message and returns from the function. + * Try using `ERR_FAIL_INDEX_MSG`. + * Only use this macro if there is no sensible error message. + * + * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. + * If not, the current function returns. */ -#define ERR_FAIL_COND(m_cond) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \ - return; \ - } \ - } +#define ERR_FAIL_INDEX(m_index, m_size) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return; \ + } else \ + ((void)0) /** - * If `m_cond` evaluates to `true`, prints a custom error message and returns from the function. + * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. + * If not, prints `m_msg` and the current function returns. */ -#define ERR_FAIL_COND_MSG(m_cond, m_msg) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \ - return; \ - } \ - } +#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ + return; \ + } else \ + ((void)0) /** - * If `m_cond` evaluates to `true`, crashes the engine immediately with a generic error message. - * Only use this if there's no sensible fallback (i.e. the error is unrecoverable). + * Try using `ERR_FAIL_INDEX_V_MSG`. + * Only use this macro if there is no sensible error message. + * + * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. + * If not, the current function returns `m_retval`. */ -#define CRASH_COND(m_cond) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \ - GENERATE_TRAP \ - } \ - } +#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return m_retval; \ + } else \ + ((void)0) /** - * If `m_cond` evaluates to `true`, crashes the engine immediately with a custom error message. - * Only use this if there's no sensible fallback (i.e. the error is unrecoverable). - */ -#define CRASH_COND_MSG(m_cond, m_msg) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \ - GENERATE_TRAP \ - } \ - } + * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. + * If not, prints `m_msg` and the current function returns `m_retval`. + */ +#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ + ((void)0) -/** - * If `m_cond` evaluates to `true`, prints a generic error message and returns the value specified in `m_retval`. - */ -#define ERR_FAIL_COND_V(m_cond, m_retval) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returned: " _STR(m_retval)); \ - return m_retval; \ - } \ - } +/** + * Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`. + * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and + * there is no sensible error message. + * + * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. + * If not, the application crashes. + */ +#define CRASH_BAD_INDEX(m_index, m_size) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) /** - * If `m_cond` evaluates to `true`, prints a custom error message and returns the value specified in `m_retval`. - */ -#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returned: " _STR(m_retval), DEBUG_STR(m_msg)); \ - return m_retval; \ - } \ - } + * Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`. + * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable. + * + * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. + * If not, prints `m_msg` and the application crashes. + */ +#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) + +// Unsigned integer index out of bounds error macros. /** - * If `m_cond` evaluates to `true`, prints a custom error message and continues the loop the macro is located in. - */ -#define ERR_CONTINUE(m_cond) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \ - continue; \ - } \ - } + * Try using `ERR_FAIL_UNSIGNED_INDEX_MSG`. + * Only use this macro if there is no sensible error message. + * + * Ensures an unsigned integer index `m_index` is less than `m_size`. + * If not, the current function returns. + */ +#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return; \ + } else \ + ((void)0) + +/** + * Ensures an unsigned integer index `m_index` is less than `m_size`. + * If not, prints `m_msg` and the current function returns. + */ +#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ + return; \ + } else \ + ((void)0) + +/** + * Try using `ERR_FAIL_UNSIGNED_INDEX_V_MSG`. + * Only use this macro if there is no sensible error message. + * + * Ensures an unsigned integer index `m_index` is less than `m_size`. + * If not, the current function returns `m_retval`. + */ +#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return m_retval; \ + } else \ + ((void)0) + +/** + * Ensures an unsigned integer index `m_index` is less than `m_size`. + * If not, prints `m_msg` and the current function returns `m_retval`. + */ +#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ + ((void)0) + +/** + * Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`. + * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and + * there is no sensible error message. + * + * Ensures an unsigned integer index `m_index` is less than `m_size`. + * If not, the application crashes. + */ +#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) + +/** + * Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`. + * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable. + * + * Ensures an unsigned integer index `m_index` is less than `m_size`. + * If not, prints `m_msg` and the application crashes. + */ +#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) + +// Null reference error macros. + +/** + * Try using `ERR_FAIL_NULL_MSG`. + * Only use this macro if there is no sensible error message. + * + * Ensures a pointer `m_param` is not null. + * If it is null, the current function returns. + */ +#define ERR_FAIL_NULL(m_param) \ + if (unlikely(!m_param)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ + return; \ + } else \ + ((void)0) + +/** + * Ensures a pointer `m_param` is not null. + * If it is null, prints `m_msg` and the current function returns. + */ +#define ERR_FAIL_NULL_MSG(m_param, m_msg) \ + if (unlikely(!m_param)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ + return; \ + } else \ + ((void)0) + +/** + * Try using `ERR_FAIL_NULL_V_MSG`. + * Only use this macro if there is no sensible error message. + * + * Ensures a pointer `m_param` is not null. + * If it is null, the current function returns `m_retval`. + */ +#define ERR_FAIL_NULL_V(m_param, m_retval) \ + if (unlikely(!m_param)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ + return m_retval; \ + } else \ + ((void)0) + +/** + * Ensures a pointer `m_param` is not null. + * If it is null, prints `m_msg` and the current function returns `m_retval`. + */ +#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \ + if (unlikely(!m_param)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ + ((void)0) + +/** + * Try using `ERR_FAIL_COND_MSG`. + * Only use this macro if there is no sensible error message. + * If checking for null use ERR_FAIL_NULL_MSG instead. + * If checking index bounds use ERR_FAIL_INDEX_MSG instead. + * + * Ensures `m_cond` is false. + * If `m_cond` is true, the current function returns. + */ +#define ERR_FAIL_COND(m_cond) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \ + return; \ + } else \ + ((void)0) + +/** + * Ensures `m_cond` is false. + * If `m_cond` is true, prints `m_msg` and the current function returns. + * + * If checking for null use ERR_FAIL_NULL_MSG instead. + * If checking index bounds use ERR_FAIL_INDEX_MSG instead. + */ +#define ERR_FAIL_COND_MSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \ + return; \ + } else \ + ((void)0) + +/** + * Try using `ERR_FAIL_COND_V_MSG`. + * Only use this macro if there is no sensible error message. + * If checking for null use ERR_FAIL_NULL_V_MSG instead. + * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead. + * + * Ensures `m_cond` is false. + * If `m_cond` is true, the current function returns `m_retval`. + */ +#define ERR_FAIL_COND_V(m_cond, m_retval) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. returned: " _STR(m_retval)); \ + return m_retval; \ + } else \ + ((void)0) + +/** + * Ensures `m_cond` is false. + * If `m_cond` is true, prints `m_msg` and the current function returns `m_retval`. + * + * If checking for null use ERR_FAIL_NULL_V_MSG instead. + * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead. + */ +#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. returned: " _STR(m_retval), DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ + ((void)0) + +/** + * Try using `ERR_CONTINUE_MSG`. + * Only use this macro if there is no sensible error message. + * + * Ensures `m_cond` is false. + * If `m_cond` is true, the current loop continues. + */ +#define ERR_CONTINUE(m_cond) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \ + continue; \ + } else \ + ((void)0) + +/** + * Ensures `m_cond` is false. + * If `m_cond` is true, prints `m_msg` and the current loop continues. + */ +#define ERR_CONTINUE_MSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", DEBUG_STR(m_msg)); \ + continue; \ + } else \ + ((void)0) + +/** + * Try using `ERR_BREAK_MSG`. + * Only use this macro if there is no sensible error message. + * + * Ensures `m_cond` is false. + * If `m_cond` is true, the current loop breaks. + */ +#define ERR_BREAK(m_cond) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \ + break; \ + } else \ + ((void)0) + +/** + * Ensures `m_cond` is false. + * If `m_cond` is true, prints `m_msg` and the current loop breaks. + */ +#define ERR_BREAK_MSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", DEBUG_STR(m_msg)); \ + break; \ + } else \ + ((void)0) + +/** + * Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`. + * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and + * there is no sensible error message. + * + * Ensures `m_cond` is false. + * If `m_cond` is true, the application crashes. + */ +#define CRASH_COND(m_cond) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) + +/** + * Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`. + * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable. + * + * Ensures `m_cond` is false. + * If `m_cond` is true, prints `m_msg` and the application crashes. + */ +#define CRASH_COND_MSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) + +// Generic error macros. + +/** + * Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_MSG`. + * Only use this macro if more complex error detection or recovery is required, and + * there is no sensible error message. + * + * The current function returns. + */ +#define ERR_FAIL() \ + if (1) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed."); \ + return; \ + } else \ + ((void)0) /** - * If `m_cond` evaluates to `true`, prints a custom error message and continues the loop the macro is located in. + * Try using `ERR_FAIL_COND_MSG`. + * Only use this macro if more complex error detection or recovery is required. + * + * Prints `m_msg`, and the current function returns. */ -#define ERR_CONTINUE_MSG(m_cond, m_msg) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", DEBUG_STR(m_msg)); \ - continue; \ - } \ - } +#define ERR_FAIL_MSG(m_msg) \ + if (1) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed.", DEBUG_STR(m_msg)); \ + return; \ + } else \ + ((void)0) /** - * If `m_cond` evaluates to `true`, prints a generic error message and breaks from the loop the macro is located in. + * Try using `ERR_FAIL_COND_V_MSG` or `ERR_FAIL_V_MSG`. + * Only use this macro if more complex error detection or recovery is required, and + * there is no sensible error message. + * + * The current function returns `m_retval`. */ -#define ERR_BREAK(m_cond) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \ - break; \ - } \ - } +#define ERR_FAIL_V(m_retval) \ + if (1) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " __STR(m_value)); \ + return m_retval; \ + } else \ + ((void)0) /** - * If `m_cond` evaluates to `true`, prints a custom error message and breaks from the loop the macro is located in. + * Try using `ERR_FAIL_COND_V_MSG`. + * Only use this macro if more complex error detection or recovery is required. + * + * Prints `m_msg`, and the current function returns `m_retval`. */ -#define ERR_BREAK_MSG(m_cond, m_msg) \ - { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", DEBUG_STR(m_msg)); \ - break; \ - } \ - } - -/** - * Prints a generic error message and returns from the function. - */ -#define ERR_FAIL() \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method failed."); \ - return; \ - } - -/** - * Prints a custom error message and returns from the function. - */ -#define ERR_FAIL_MSG(m_msg) \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method failed.", DEBUG_STR(m_msg)); \ - return; \ - } - -/** - * Prints a generic error message and returns the value specified in `m_retval`. - */ -#define ERR_FAIL_V(m_retval) \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method failed. Returning: " __STR(m_retval)); \ - return m_retval; \ - } - -/** - * Prints a custom error message and returns the value specified in `m_retval`. - */ -#define ERR_FAIL_V_MSG(m_retval, m_msg) \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method failed. Returning: " __STR(m_retval), DEBUG_STR(m_msg)); \ - return m_retval; \ - } - -/** - * Crashes the engine immediately with a generic error message. - * Only use this if there's no sensible fallback (i.e. the error is unrecoverable). - */ -#define CRASH_NOW() \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method failed."); \ - GENERATE_TRAP \ - } - -/** - * Crashes the engine immediately with a custom error message. - * Only use this if there's no sensible fallback (i.e. the error is unrecoverable). - */ -#define CRASH_NOW_MSG(m_msg) \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method failed.", DEBUG_STR(m_msg)); \ - GENERATE_TRAP \ - } +#define ERR_FAIL_V_MSG(m_retval, m_msg) \ + if (1) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " __STR(m_value), DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ + ((void)0) /** - * Prints an error message without returning. + * Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG. + * Only use this macro at the start of a function that has not been implemented yet, or + * if more complex error detection or recovery is required. + * + * Prints `m_msg`. */ -#define ERR_PRINT(m_string) \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string); \ - } +#define ERR_PRINT(m_msg) \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)) /** - * Prints an error message without returning. - * FIXME: Remove this macro and replace all uses with `ERR_PRINT` as it's identical. + * Prints `m_msg` once during the application lifetime. */ -#define ERR_PRINTS(m_string) \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string); \ - } +#define ERR_PRINT_ONCE(m_msg) \ + if (1) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)); \ + first_print = false; \ + } \ + } else \ + ((void)0) -/** - * Prints an error message without returning, but only do so once in the application lifecycle. - * This can be used to avoid spamming the console with error messages. - */ -#define ERR_PRINT_ONCE(m_string) \ - { \ - static bool first_print = true; \ - if (first_print) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string); \ - first_print = false; \ - } \ - } +// Print warning message macros. /** - * Prints a warning message without returning. To warn about deprecated usage, - * use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. + * Prints `m_msg`. + * + * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ -#define WARN_PRINT(m_string) \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING); \ - } +#define WARN_PRINT(m_msg) \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING) /** - * Prints a warning message without returning. - * FIXME: Remove this macro and replace all uses with `WARN_PRINT` as it's identical. + * Prints `m_msg` once during the application lifetime. + * + * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ -#define WARN_PRINTS(m_string) \ - { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING); \ - } +#define WARN_PRINT_ONCE(m_msg) \ + if (1) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \ + first_print = false; \ + } \ + } else \ + ((void)0) -/** - * Prints a warning message without returning, but only do so once in the application lifecycle. - * This can be used to avoid spamming the console with warning messages. - */ -#define WARN_PRINT_ONCE(m_string) \ - { \ - static bool first_print = true; \ - if (first_print) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING); \ - first_print = false; \ - } \ - } +// Print deprecated warning message macros. /** - * Prints a generic deprecation warning message without returning. - * This should be preferred to `WARN_PRINT` for deprecation warnings. + * Warns that the current function is deprecated. */ #define WARN_DEPRECATED \ - { \ + if (1) { \ static volatile bool warning_shown = false; \ if (!warning_shown) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", ERR_HANDLER_WARNING); \ warning_shown = true; \ } \ - } - -/** - * Prints a custom deprecation warning message without returning. - * This should be preferred to `WARN_PRINT` for deprecation warnings. - */ -#define WARN_DEPRECATED_MSG(m_msg) \ - { \ - static volatile bool warning_shown = false; \ - if (!warning_shown) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, ERR_HANDLER_WARNING); \ - warning_shown = true; \ - } \ - } + } else \ + ((void)0) + +/** + * Warns that the current function is deprecated and prints `m_msg`. + */ +#define WARN_DEPRECATED_MSG(m_msg) \ + if (1) { \ + static volatile bool warning_shown = false; \ + if (!warning_shown) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \ + warning_shown = true; \ + } \ + } else \ + ((void)0) + +/** + * Do not use. + * If the application should never reach this point use CRASH_NOW_MSG(m_msg) to explain why. + * + * The application crashes. + */ +#define CRASH_NOW() \ + if (1) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/Function Failed."); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) + +/** + * Only use if the application should never reach this point. + * + * Prints `m_msg`, and then the application crashes. + */ +#define CRASH_NOW_MSG(m_msg) \ + if (1) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/Function Failed.", DEBUG_STR(m_msg)); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) #endif diff --git a/core/func_ref.cpp b/core/func_ref.cpp index 2dffb30bab..e20188c813 100644 --- a/core/func_ref.cpp +++ b/core/func_ref.cpp @@ -32,7 +32,7 @@ Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { - if (id == 0) { + if (id.is_null()) { r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL; return Variant(); } @@ -48,7 +48,7 @@ Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::Call Variant FuncRef::call_funcv(const Array &p_args) { - ERR_FAIL_COND_V(id == 0, Variant()); + ERR_FAIL_COND_V(id.is_null(), Variant()); Object *obj = ObjectDB::get_instance(id); @@ -69,7 +69,7 @@ void FuncRef::set_function(const StringName &p_func) { } bool FuncRef::is_valid() const { - if (id == 0) + if (id.is_null()) return false; Object *obj = ObjectDB::get_instance(id); @@ -95,6 +95,5 @@ void FuncRef::_bind_methods() { ClassDB::bind_method(D_METHOD("is_valid"), &FuncRef::is_valid); } -FuncRef::FuncRef() : - id(0) { +FuncRef::FuncRef() { } diff --git a/core/global_constants.cpp b/core/global_constants.cpp index e48556c064..94713b4ee6 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -611,13 +611,13 @@ void register_global_constants() { BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_OBJECT", Variant::OBJECT); BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_DICTIONARY", Variant::DICTIONARY); // 20 BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_ARRAY", Variant::ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_RAW_ARRAY", Variant::POOL_BYTE_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_INT_ARRAY", Variant::POOL_INT_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_REAL_ARRAY", Variant::POOL_REAL_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_STRING_ARRAY", Variant::POOL_STRING_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2_ARRAY", Variant::POOL_VECTOR2_ARRAY); // 25 - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3_ARRAY", Variant::POOL_VECTOR3_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_COLOR_ARRAY", Variant::POOL_COLOR_ARRAY); + BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_RAW_ARRAY", Variant::PACKED_BYTE_ARRAY); + BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_INT_ARRAY", Variant::PACKED_INT_ARRAY); + BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_REAL_ARRAY", Variant::PACKED_REAL_ARRAY); + BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_STRING_ARRAY", Variant::PACKED_STRING_ARRAY); + BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2_ARRAY", Variant::PACKED_VECTOR2_ARRAY); // 25 + BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3_ARRAY", Variant::PACKED_VECTOR3_ARRAY); + BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_COLOR_ARRAY", Variant::PACKED_COLOR_ARRAY); BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_MAX", Variant::VARIANT_MAX); //comparison diff --git a/core/hashfuncs.h b/core/hashfuncs.h index 647e8a40b2..d6cf04e560 100644 --- a/core/hashfuncs.h +++ b/core/hashfuncs.h @@ -34,10 +34,10 @@ #include "core/math/math_defs.h" #include "core/math/math_funcs.h" #include "core/node_path.h" +#include "core/object_id.h" #include "core/string_name.h" #include "core/typedefs.h" #include "core/ustring.h" - /** * Hashing functions */ @@ -137,6 +137,7 @@ struct HashMapHasherDefault { static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } + static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); } static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); } static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); } diff --git a/core/image.cpp b/core/image.cpp index f43c26ab19..a188447f90 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -79,12 +79,16 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "ETC2_RGB8", "ETC2_RGBA8", "ETC2_RGB8A1", + "ETC2_RA_AS_RG", + "FORMAT_DXT5_RA_AS_RG", }; SavePNGFunc Image::save_png_func = NULL; SaveEXRFunc Image::save_exr_func = NULL; +SavePNGBufferFunc Image::save_png_buffer_func = NULL; + void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) { uint32_t ofs = (p_y * width + p_x) * p_pixelsize; @@ -115,7 +119,7 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_RGB8: return 3; case FORMAT_RGBA8: return 4; case FORMAT_RGBA4444: return 2; - case FORMAT_RGBA5551: return 2; + case FORMAT_RGB565: return 2; case FORMAT_RF: return 4; //float case FORMAT_RGF: return 8; @@ -159,6 +163,8 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_ETC2_RGB8: return 1; case FORMAT_ETC2_RGBA8: return 1; case FORMAT_ETC2_RGB8A1: return 1; + case FORMAT_ETC2_RA_AS_RG: return 1; + case FORMAT_DXT5_RA_AS_RG: return 1; case FORMAT_MAX: { } } @@ -207,7 +213,9 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { case FORMAT_ETC2_RG11S: case FORMAT_ETC2_RGB8: case FORMAT_ETC2_RGBA8: - case FORMAT_ETC2_RGB8A1: { + case FORMAT_ETC2_RGB8A1: + case FORMAT_ETC2_RA_AS_RG: + case FORMAT_DXT5_RA_AS_RG: { r_w = 4; r_h = 4; @@ -268,7 +276,11 @@ int Image::get_format_block_size(Format p_format) { case FORMAT_ETC2_RG11S: case FORMAT_ETC2_RGB8: case FORMAT_ETC2_RGBA8: - case FORMAT_ETC2_RGB8A1: { + case FORMAT_ETC2_RGB8A1: + case FORMAT_ETC2_RA_AS_RG: //used to make basis universal happy + case FORMAT_DXT5_RA_AS_RG: //used to make basis universal happy + + { return 4; } @@ -318,6 +330,17 @@ int Image::get_mipmap_offset(int p_mipmap) const { return ofs; } +int Image::get_mipmap_byte_size(int p_mipmap) const { + + ERR_FAIL_INDEX_V(p_mipmap, get_mipmap_count() + 1, -1); + + int ofs, w, h; + _get_mipmap_offset_and_size(p_mipmap, ofs, w, h); + int ofs2; + _get_mipmap_offset_and_size(p_mipmap + 1, ofs2, w, h); + return ofs2 - ofs; +} + void Image::get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const { int ofs, w, h; @@ -421,8 +444,6 @@ void Image::convert(Format p_new_format) { if (p_new_format == format) return; - ERR_FAIL_COND_MSG(write_lock.ptr(), "Cannot convert image when it is locked."); - if (format > FORMAT_RGBE9995 || p_new_format > FORMAT_RGBE9995) { ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead."); @@ -431,8 +452,6 @@ void Image::convert(Format p_new_format) { //use put/set pixel which is slower but works with non byte formats Image new_img(width, height, 0, p_new_format); - lock(); - new_img.lock(); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { @@ -441,9 +460,6 @@ void Image::convert(Format p_new_format) { } } - unlock(); - new_img.unlock(); - if (has_mipmaps()) { new_img.generate_mipmaps(); } @@ -455,11 +471,8 @@ void Image::convert(Format p_new_format) { Image new_img(width, height, 0, p_new_format); - PoolVector<uint8_t>::Read r = data.read(); - PoolVector<uint8_t>::Write w = new_img.data.write(); - - const uint8_t *rptr = r.ptr(); - uint8_t *wptr = w.ptr(); + const uint8_t *rptr = data.ptr(); + uint8_t *wptr = new_img.data.ptrw(); int conversion_type = format | p_new_format << 8; @@ -497,9 +510,6 @@ void Image::convert(Format p_new_format) { case FORMAT_RGBA8 | (FORMAT_RGB8 << 8): _convert<3, true, 3, false, false, false>(width, height, rptr, wptr); break; } - r.release(); - w.release(); - bool gen_mipmaps = mipmaps; _copy_internals_from(new_img); @@ -883,7 +893,6 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { ERR_FAIL_COND_MSG(data.size() == 0, "Cannot resize image before creating it, use create() or create_from_data() first."); ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats."); - ERR_FAIL_COND_MSG(write_lock.ptr(), "Cannot resize image when it is locked."); bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */; @@ -891,6 +900,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0."); ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + "."); ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + "."); + ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); if (p_width == width && p_height == height) return; @@ -924,11 +934,11 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { } // -- - PoolVector<uint8_t>::Read r = data.read(); - const unsigned char *r_ptr = r.ptr(); + const uint8_t *r = data.ptr(); + const unsigned char *r_ptr = r; - PoolVector<uint8_t>::Write w = dst.data.write(); - unsigned char *w_ptr = w.ptr(); + uint8_t *w = dst.data.ptrw(); + unsigned char *w_ptr = w; switch (p_interpolation) { @@ -993,8 +1003,8 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { _get_mipmap_offset_and_size(mip2, offs, src_width, src_height); src_ptr = r_ptr + offs; // Switch to write to the second destination image - w = dst2.data.write(); - w_ptr = w.ptr(); + w = dst2.data.ptrw(); + w_ptr = w; } } @@ -1024,8 +1034,8 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { if (interpolate_mipmaps) { // Switch to read again from the first scaled mipmap to overlay it over the second - r = dst.data.read(); - _overlay(r.ptr(), w.ptr(), mip1_weight, p_width, p_height, get_format_pixel_size(format)); + r = dst.data.ptr(); + _overlay(r, w, mip1_weight, p_width, p_height, get_format_pixel_size(format)); } } break; @@ -1081,9 +1091,6 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { } break; } - r.release(); - w.release(); - if (interpolate_mipmaps) { dst._copy_internals_from(dst2); } @@ -1118,8 +1125,8 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) { Image dst(p_width, p_height, 0, format); { - PoolVector<uint8_t>::Read r = data.read(); - PoolVector<uint8_t>::Write w = dst.data.write(); + const uint8_t *r = data.ptr(); + uint8_t *w = dst.data.ptrw(); int m_h = p_y + p_height; int m_w = p_x + p_width; @@ -1131,10 +1138,10 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) { for (uint32_t i = 0; i < pixel_size; i++) pdata[i] = 0; } else { - _get_pixelb(x, y, pixel_size, r.ptr(), pdata); + _get_pixelb(x, y, pixel_size, r, pdata); } - dst._put_pixelb(x - p_x, y - p_y, pixel_size, w.ptr(), pdata); + dst._put_pixelb(x - p_x, y - p_y, pixel_size, w, pdata); } } } @@ -1159,7 +1166,7 @@ void Image::flip_y() { } { - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); uint8_t up[16]; uint8_t down[16]; uint32_t pixel_size = get_format_pixel_size(format); @@ -1168,11 +1175,11 @@ void Image::flip_y() { for (int x = 0; x < width; x++) { - _get_pixelb(x, y, pixel_size, w.ptr(), up); - _get_pixelb(x, height - y - 1, pixel_size, w.ptr(), down); + _get_pixelb(x, y, pixel_size, w, up); + _get_pixelb(x, height - y - 1, pixel_size, w, down); - _put_pixelb(x, height - y - 1, pixel_size, w.ptr(), up); - _put_pixelb(x, y, pixel_size, w.ptr(), down); + _put_pixelb(x, height - y - 1, pixel_size, w, up); + _put_pixelb(x, y, pixel_size, w, down); } } } @@ -1192,7 +1199,7 @@ void Image::flip_x() { } { - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); uint8_t up[16]; uint8_t down[16]; uint32_t pixel_size = get_format_pixel_size(format); @@ -1201,11 +1208,11 @@ void Image::flip_x() { for (int x = 0; x < width / 2; x++) { - _get_pixelb(x, y, pixel_size, w.ptr(), up); - _get_pixelb(width - x - 1, y, pixel_size, w.ptr(), down); + _get_pixelb(x, y, pixel_size, w, up); + _get_pixelb(width - x - 1, y, pixel_size, w, down); - _put_pixelb(width - x - 1, y, pixel_size, w.ptr(), up); - _put_pixelb(x, y, pixel_size, w.ptr(), down); + _put_pixelb(width - x - 1, y, pixel_size, w, up); + _put_pixelb(x, y, pixel_size, w, down); } } } @@ -1215,7 +1222,7 @@ void Image::flip_x() { } } -int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps) { +int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps, int *r_mm_width, int *r_mm_height) { int size = 0; int w = p_width; @@ -1242,6 +1249,13 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int & size += s; + if (r_mm_width) { + *r_mm_width = bw; + } + if (r_mm_height) { + *r_mm_height = bh; + } + if (p_mipmaps >= 0 && mm == p_mipmaps) break; @@ -1317,16 +1331,16 @@ void Image::expand_x2_hq2x() { if (current != FORMAT_RGBA8) convert(FORMAT_RGBA8); - PoolVector<uint8_t> dest; + Vector<uint8_t> dest; dest.resize(width * 2 * height * 2 * 4); { - PoolVector<uint8_t>::Read r = data.read(); - PoolVector<uint8_t>::Write w = dest.write(); + const uint8_t *r = data.ptr(); + uint8_t *w = dest.ptrw(); - ERR_FAIL_COND(!r.ptr()); + ERR_FAIL_COND(!r); - hq2x_resize((const uint32_t *)r.ptr(), width, height, (uint32_t *)w.ptr()); + hq2x_resize((const uint32_t *)r, width, height, (uint32_t *)w); } width *= 2; @@ -1350,7 +1364,7 @@ void Image::shrink_x2() { if (mipmaps) { //just use the lower mipmap as base and copy all - PoolVector<uint8_t> new_img; + Vector<uint8_t> new_img; int ofs = get_mipmap_offset(1); @@ -1359,10 +1373,10 @@ void Image::shrink_x2() { ERR_FAIL_COND(new_img.size() == 0); { - PoolVector<uint8_t>::Write w = new_img.write(); - PoolVector<uint8_t>::Read r = data.read(); + uint8_t *w = new_img.ptrw(); + const uint8_t *r = data.ptr(); - copymem(w.ptr(), &r[ofs], new_size); + copymem(w, &r[ofs], new_size); } width = MAX(width / 2, 1); @@ -1371,7 +1385,7 @@ void Image::shrink_x2() { } else { - PoolVector<uint8_t> new_img; + Vector<uint8_t> new_img; ERR_FAIL_COND(!_can_modify(format)); int ps = get_format_pixel_size(format); @@ -1380,29 +1394,29 @@ void Image::shrink_x2() { ERR_FAIL_COND(data.size() == 0); { - PoolVector<uint8_t>::Write w = new_img.write(); - PoolVector<uint8_t>::Read r = data.read(); + uint8_t *w = new_img.ptrw(); + const uint8_t *r = data.ptr(); switch (format) { case FORMAT_L8: - case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break; - case FORMAT_LA8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break; - case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break; - case FORMAT_RGB8: _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break; - case FORMAT_RGBA8: _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break; - - case FORMAT_RF: _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break; - case FORMAT_RGF: _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break; - case FORMAT_RGBF: _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break; - case FORMAT_RGBAF: _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break; - - case FORMAT_RH: _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break; - case FORMAT_RGH: _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break; - case FORMAT_RGBH: _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break; - case FORMAT_RGBAH: _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break; - - case FORMAT_RGBE9995: _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r.ptr()), reinterpret_cast<uint32_t *>(w.ptr()), width, height); break; + case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; + case FORMAT_LA8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; + case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; + case FORMAT_RGB8: _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; + case FORMAT_RGBA8: _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; + + case FORMAT_RF: _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; + case FORMAT_RGF: _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; + case FORMAT_RGBF: _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; + case FORMAT_RGBAF: _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; + + case FORMAT_RH: _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; + case FORMAT_RGH: _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; + case FORMAT_RGBH: _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; + case FORMAT_RGBAH: _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; + + case FORMAT_RGBE9995: _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r), reinterpret_cast<uint32_t *>(w), width, height); break; default: { } } @@ -1421,8 +1435,6 @@ void Image::normalize() { clear_mipmaps(); } - lock(); - for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { @@ -1437,8 +1449,6 @@ void Image::normalize() { } } - unlock(); - if (used_mipmaps) { generate_mipmaps(true); } @@ -1456,7 +1466,7 @@ Error Image::generate_mipmaps(bool p_renormalize) { data.resize(size); - PoolVector<uint8_t>::Write wp = data.write(); + uint8_t *wp = data.ptrw(); int prev_ofs = 0; int prev_h = height; @@ -1547,6 +1557,202 @@ Error Image::generate_mipmaps(bool p_renormalize) { return OK; } +Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref<Image> &p_normal_map) { + + Vector<double> normal_sat_vec; //summed area table + double *normal_sat = nullptr; //summed area table for normalmap + int normal_w = 0, normal_h = 0; + + ERR_FAIL_COND_V_MSG(p_normal_map.is_null() || p_normal_map->empty(), ERR_INVALID_PARAMETER, "Must provide a valid normalmap for roughness mipmaps"); + + Ref<Image> nm = p_normal_map->duplicate(); + if (nm->is_compressed()) { + nm->decompress(); + } + + normal_w = nm->get_width(); + normal_h = nm->get_height(); + + normal_sat_vec.resize(normal_w * normal_h * 3); + + normal_sat = normal_sat_vec.ptrw(); + + //create summed area table + + for (int y = 0; y < normal_h; y++) { + double line_sum[3] = { 0, 0, 0 }; + for (int x = 0; x < normal_w; x++) { + double normal[3]; + Color color = nm->get_pixel(x, y); + normal[0] = color.r * 2.0 - 1.0; + normal[1] = color.g * 2.0 - 1.0; + normal[2] = Math::sqrt(MAX(0.0, 1.0 - (normal[0] * normal[0] + normal[1] * normal[1]))); //reconstruct if missing + + line_sum[0] += normal[0]; + line_sum[1] += normal[1]; + line_sum[2] += normal[2]; + + uint32_t ofs = (y * normal_w + x) * 3; + + normal_sat[ofs + 0] = line_sum[0]; + normal_sat[ofs + 1] = line_sum[1]; + normal_sat[ofs + 2] = line_sum[2]; + + if (y > 0) { + uint32_t prev_ofs = ((y - 1) * normal_w + x) * 3; + normal_sat[ofs + 0] += normal_sat[prev_ofs + 0]; + normal_sat[ofs + 1] += normal_sat[prev_ofs + 1]; + normal_sat[ofs + 2] += normal_sat[prev_ofs + 2]; + } + } + } + +#if 0 + { + Vector3 beg(normal_sat_vec[0], normal_sat_vec[1], normal_sat_vec[2]); + Vector3 end(normal_sat_vec[normal_sat_vec.size() - 3], normal_sat_vec[normal_sat_vec.size() - 2], normal_sat_vec[normal_sat_vec.size() - 1]); + Vector3 avg = (end - beg) / (normal_w * normal_h); + print_line("average: " + avg); + } +#endif + + int mmcount; + + _get_dst_image_size(width, height, format, mmcount); + + uint8_t *base_ptr = data.ptrw(); + + for (int i = 1; i <= mmcount; i++) { + + int ofs, w, h; + _get_mipmap_offset_and_size(i, ofs, w, h); + uint8_t *ptr = &base_ptr[ofs]; + + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int from_x = x * normal_w / w; + int from_y = y * normal_h / h; + int to_x = (x + 1) * normal_w / w; + int to_y = (y + 1) * normal_h / h; + to_x = MIN(to_x - 1, normal_w); + to_y = MIN(to_y - 1, normal_h); + + int size_x = (to_x - from_x) + 1; + int size_y = (to_y - from_y) + 1; + + //summed area table version (much faster) + + double avg[3] = { 0, 0, 0 }; + + if (from_x > 0 && from_y > 0) { + uint32_t tofs = ((from_y - 1) * normal_w + (from_x - 1)) * 3; + avg[0] += normal_sat[tofs + 0]; + avg[1] += normal_sat[tofs + 1]; + avg[2] += normal_sat[tofs + 2]; + } + + if (from_y > 0) { + uint32_t tofs = ((from_y - 1) * normal_w + to_x) * 3; + avg[0] -= normal_sat[tofs + 0]; + avg[1] -= normal_sat[tofs + 1]; + avg[2] -= normal_sat[tofs + 2]; + } + + if (from_x > 0) { + uint32_t tofs = (to_y * normal_w + (from_x - 1)) * 3; + avg[0] -= normal_sat[tofs + 0]; + avg[1] -= normal_sat[tofs + 1]; + avg[2] -= normal_sat[tofs + 2]; + } + + uint32_t tofs = (to_y * normal_w + to_x) * 3; + avg[0] += normal_sat[tofs + 0]; + avg[1] += normal_sat[tofs + 1]; + avg[2] += normal_sat[tofs + 2]; + + double div = double(size_x * size_y); + Vector3 vec(avg[0] / div, avg[1] / div, avg[2] / div); + + float r = vec.length(); + + int pixel_ofs = y * w + x; + Color c = _get_color_at_ofs(ptr, pixel_ofs); + + float roughness; + + switch (p_roughness_channel) { + case ROUGHNESS_CHANNEL_R: { + roughness = c.r; + } break; + case ROUGHNESS_CHANNEL_G: { + roughness = c.g; + } break; + case ROUGHNESS_CHANNEL_B: { + roughness = c.b; + } break; + case ROUGHNESS_CHANNEL_L: { + roughness = c.get_v(); + } break; + case ROUGHNESS_CHANNEL_A: { + roughness = c.a; + } break; + } + + float variance = 0; + if (r < 1.0f) { + float r2 = r * r; + float kappa = (3.0f * r - r * r2) / (1.0f - r2); + variance = 0.25f / kappa; + } + + float threshold = 0.4; + roughness = Math::sqrt(roughness * roughness + MIN(3.0f * variance, threshold * threshold)); + + switch (p_roughness_channel) { + case ROUGHNESS_CHANNEL_R: { + c.r = roughness; + } break; + case ROUGHNESS_CHANNEL_G: { + c.g = roughness; + } break; + case ROUGHNESS_CHANNEL_B: { + c.b = roughness; + } break; + case ROUGHNESS_CHANNEL_L: { + c.r = roughness; + c.g = roughness; + c.b = roughness; + } break; + case ROUGHNESS_CHANNEL_A: { + c.a = roughness; + } break; + } + + _set_color_at_ofs(ptr, pixel_ofs, c); + } + } +#if 0 + { + int size = get_mipmap_byte_size(i); + print_line("size for mimpap " + itos(i) + ": " + itos(size)); + Vector<uint8_t> imgdata; + imgdata.resize(size); + + + uint8_t* wr = imgdata.ptrw(); + copymem(wr.ptr(), ptr, size); + wr = uint8_t*(); + Ref<Image> im; + im.instance(); + im->create(w, h, false, format, imgdata); + im->save_png("res://mipmap_" + itos(i) + ".png"); + } +#endif + } + + return OK; +} + void Image::clear_mipmaps() { if (!mipmaps) @@ -1567,7 +1773,7 @@ bool Image::empty() const { return (data.size() == 0); } -PoolVector<uint8_t> Image::get_data() const { +Vector<uint8_t> Image::get_data() const { return data; } @@ -1576,13 +1782,15 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH); ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT); + ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); int mm = 0; int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); data.resize(size); + { - PoolVector<uint8_t>::Write w = data.write(); - zeromem(w.ptr(), size); + uint8_t *w = data.ptrw(); + zeromem(w, size); } width = p_width; @@ -1591,10 +1799,11 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma format = p_format; } -void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data) { +void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH); ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT); + ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); int mm; int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); @@ -1605,6 +1814,7 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma width = p_width; format = p_format; data = p_data; + mipmaps = p_use_mipmaps; } @@ -1629,7 +1839,7 @@ void Image::create(const char **p_xpm) { HashMap<String, Color> colormap; int colormap_size = 0; uint32_t pixel_size = 0; - PoolVector<uint8_t>::Write w; + uint8_t *w; while (status != DONE) { @@ -1720,7 +1930,7 @@ void Image::create(const char **p_xpm) { status = READING_PIXELS; create(size_width, size_height, 0, has_alpha ? FORMAT_RGBA8 : FORMAT_RGB8); - w = data.write(); + w = data.ptrw(); pixel_size = has_alpha ? 4 : 3; } } break; @@ -1739,7 +1949,7 @@ void Image::create(const char **p_xpm) { for (uint32_t i = 0; i < pixel_size; i++) { pixel[i] = CLAMP((*colorptr)[i] * 255, 0, 255); } - _put_pixelb(x, y, pixel_size, w.ptr(), pixel); + _put_pixelb(x, y, pixel_size, w, pixel); } if (y == (size_height - 1)) @@ -1791,8 +2001,8 @@ bool Image::is_invisible() const { int w, h; _get_mipmap_offset_and_size(1, len, w, h); - PoolVector<uint8_t>::Read r = data.read(); - const unsigned char *data_ptr = r.ptr(); + const uint8_t *r = data.ptr(); + const unsigned char *data_ptr = r; bool detected = false; @@ -1836,8 +2046,8 @@ Image::AlphaMode Image::detect_alpha() const { int w, h; _get_mipmap_offset_and_size(1, len, w, h); - PoolVector<uint8_t>::Read r = data.read(); - const unsigned char *data_ptr = r.ptr(); + const uint8_t *r = data.ptr(); + const unsigned char *data_ptr = r; bool bit = false; bool detected = false; @@ -1879,7 +2089,7 @@ Image::AlphaMode Image::detect_alpha() const { Error Image::load(const String &p_path) { #ifdef DEBUG_ENABLED if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) { - WARN_PRINTS("Loaded resource as image file, this will not work on export: '" + p_path + "'. Instead, import the image file as an Image resource and load it normally as a resource."); + WARN_PRINT("Loaded resource as image file, this will not work on export: '" + p_path + "'. Instead, import the image file as an Image resource and load it normally as a resource."); } #endif return ImageLoader::load_image(p_path, this); @@ -1893,6 +2103,14 @@ Error Image::save_png(const String &p_path) const { return save_png_func(p_path, Ref<Image>((Image *)this)); } +Vector<uint8_t> Image::save_png_to_buffer() const { + if (save_png_buffer_func == NULL) { + return Vector<uint8_t>(); + } + + return save_png_buffer_func(Ref<Image>((Image *)this)); +} + Error Image::save_exr(const String &p_path, bool p_grayscale) const { if (save_exr_func == NULL) @@ -1914,6 +2132,13 @@ int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format return mm; } +Size2i Image::get_image_mipmap_size(int p_width, int p_height, Format p_format, int p_mipmap) { + int mm; + Size2i ret; + _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap, &ret.x, &ret.y); + return ret; +} + int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) { if (p_mipmap <= 0) { @@ -1923,13 +2148,24 @@ int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, i return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1); } +int Image::get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h) { + + if (p_mipmap <= 0) { + r_w = p_width; + r_h = p_height; + return 0; + } + int mm; + return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1, &r_w, &r_h); +} + bool Image::is_compressed() const { return format > FORMAT_RGBE9995; } Error Image::decompress() { - if (format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG && _image_decompress_bc) + if (((format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG) || (format == FORMAT_DXT5_RA_AS_RG)) && _image_decompress_bc) _image_decompress_bc(this); else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc) _image_decompress_bptc(this); @@ -1937,7 +2173,7 @@ Error Image::decompress() { _image_decompress_pvrtc(this); else if (format == FORMAT_ETC && _image_decompress_etc1) _image_decompress_etc1(this); - else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RGB8A1 && _image_decompress_etc2) + else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2) _image_decompress_etc2(this); else return ERR_UNAVAILABLE; @@ -1946,12 +2182,16 @@ Error Image::decompress() { Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) { + return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality); +} +Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality) { + switch (p_mode) { case COMPRESS_S3TC: { ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); - _image_compress_bc_func(this, p_lossy_quality, p_source); + _image_compress_bc_func(this, p_lossy_quality, p_channels); } break; case COMPRESS_PVRTC2: { @@ -1971,12 +2211,12 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_loss case COMPRESS_ETC2: { ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE); - _image_compress_etc2_func(this, p_lossy_quality, p_source); + _image_compress_etc2_func(this, p_lossy_quality, p_channels); } break; case COMPRESS_BPTC: { ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE); - _image_compress_bptc_func(this, p_lossy_quality, p_source); + _image_compress_bptc_func(this, p_lossy_quality, p_channels); } break; } @@ -2003,7 +2243,7 @@ Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { create(p_width, p_height, p_use_mipmaps, p_format); } -Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data) { +Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { width = 0; height = 0; @@ -2015,7 +2255,7 @@ Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const P Rect2 Image::get_used_rect() const { - if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGBA5551) + if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGB565) return Rect2(Point2(), Size2(width, height)); int len = data.size(); @@ -2023,7 +2263,6 @@ Rect2 Image::get_used_rect() const { if (len == 0) return Rect2(); - const_cast<Image *>(this)->lock(); int minx = 0xFFFFFF, miny = 0xFFFFFFF; int maxx = -1, maxy = -1; for (int j = 0; j < height; j++) { @@ -2042,8 +2281,6 @@ Rect2 Image::get_used_rect() const { } } - const_cast<Image *>(this)->unlock(); - if (maxx == -1) return Rect2(); else @@ -2080,11 +2317,11 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); - PoolVector<uint8_t>::Write wp = data.write(); - uint8_t *dst_data_ptr = wp.ptr(); + uint8_t *wp = data.ptrw(); + uint8_t *dst_data_ptr = wp; - PoolVector<uint8_t>::Read rp = p_src->data.read(); - const uint8_t *src_data_ptr = rp.ptr(); + const uint8_t *rp = p_src->data.ptr(); + const uint8_t *src_data_ptr = rp; int pixel_size = get_format_pixel_size(format); @@ -2135,16 +2372,15 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); - PoolVector<uint8_t>::Write wp = data.write(); - uint8_t *dst_data_ptr = wp.ptr(); + uint8_t *wp = data.ptrw(); + uint8_t *dst_data_ptr = wp; - PoolVector<uint8_t>::Read rp = p_src->data.read(); - const uint8_t *src_data_ptr = rp.ptr(); + const uint8_t *rp = p_src->data.ptr(); + const uint8_t *src_data_ptr = rp; int pixel_size = get_format_pixel_size(format); Ref<Image> msk = p_mask; - msk->lock(); for (int i = 0; i < dest_rect.size.y; i++) { @@ -2167,8 +2403,6 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co } } } - - msk->unlock(); } void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) { @@ -2193,9 +2427,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); - lock(); Ref<Image> img = p_src; - img->lock(); for (int i = 0; i < dest_rect.size.y; i++) { @@ -2216,9 +2448,6 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P set_pixel(dst_x, dst_y, dc); } } - - img->unlock(); - unlock(); } void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) { @@ -2248,11 +2477,8 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); - lock(); Ref<Image> img = p_src; Ref<Image> msk = p_mask; - img->lock(); - msk->lock(); for (int i = 0; i < dest_rect.size.y; i++) { @@ -2279,19 +2505,13 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c } } } - - msk->unlock(); - img->unlock(); - unlock(); } void Image::fill(const Color &c) { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill in compressed or custom image formats."); - lock(); - - PoolVector<uint8_t>::Write wp = data.write(); - uint8_t *dst_data_ptr = wp.ptr(); + uint8_t *wp = data.ptrw(); + uint8_t *dst_data_ptr = wp; int pixel_size = get_format_pixel_size(format); @@ -2309,30 +2529,30 @@ void Image::fill(const Color &c) { } } } - - unlock(); } ImageMemLoadFunc Image::_png_mem_loader_func = NULL; ImageMemLoadFunc Image::_jpg_mem_loader_func = NULL; ImageMemLoadFunc Image::_webp_mem_loader_func = NULL; -void (*Image::_image_compress_bc_func)(Image *, float, Image::CompressSource) = NULL; -void (*Image::_image_compress_bptc_func)(Image *, float, Image::CompressSource) = NULL; +void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = NULL; +void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = NULL; void (*Image::_image_compress_pvrtc2_func)(Image *) = NULL; void (*Image::_image_compress_pvrtc4_func)(Image *) = NULL; void (*Image::_image_compress_etc1_func)(Image *, float) = NULL; -void (*Image::_image_compress_etc2_func)(Image *, float, Image::CompressSource) = NULL; +void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = NULL; void (*Image::_image_decompress_pvrtc)(Image *) = NULL; void (*Image::_image_decompress_bc)(Image *) = NULL; void (*Image::_image_decompress_bptc)(Image *) = NULL; void (*Image::_image_decompress_etc1)(Image *) = NULL; void (*Image::_image_decompress_etc2)(Image *) = NULL; -PoolVector<uint8_t> (*Image::lossy_packer)(const Ref<Image> &, float) = NULL; -Ref<Image> (*Image::lossy_unpacker)(const PoolVector<uint8_t> &) = NULL; -PoolVector<uint8_t> (*Image::lossless_packer)(const Ref<Image> &) = NULL; -Ref<Image> (*Image::lossless_unpacker)(const PoolVector<uint8_t> &) = NULL; +Vector<uint8_t> (*Image::lossy_packer)(const Ref<Image> &, float) = NULL; +Ref<Image> (*Image::lossy_unpacker)(const Vector<uint8_t> &) = NULL; +Vector<uint8_t> (*Image::lossless_packer)(const Ref<Image> &) = NULL; +Ref<Image> (*Image::lossless_unpacker)(const Vector<uint8_t> &) = NULL; +Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = NULL; +Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = NULL; void Image::_set_data(const Dictionary &p_data) { @@ -2346,7 +2566,7 @@ void Image::_set_data(const Dictionary &p_data) { int dheight = p_data["height"]; String dformat = p_data["format"]; bool dmipmaps = p_data["mipmaps"]; - PoolVector<uint8_t> ddata = p_data["data"]; + Vector<uint8_t> ddata = p_data["data"]; Format ddformat = FORMAT_MAX; for (int i = 0; i < FORMAT_MAX; i++) { if (dformat == get_format_name(Format(i))) { @@ -2371,33 +2591,11 @@ Dictionary Image::_get_data() const { return d; } -void Image::lock() { - - ERR_FAIL_COND(data.size() == 0); - write_lock = data.write(); -} - -void Image::unlock() { - - write_lock.release(); -} - Color Image::get_pixelv(const Point2 &p_src) const { return get_pixel(p_src.x, p_src.y); } -Color Image::get_pixel(int p_x, int p_y) const { - - uint8_t *ptr = write_lock.ptr(); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V_MSG(!ptr, Color(), "Image must be locked with 'lock()' before using get_pixel()."); - - ERR_FAIL_INDEX_V(p_x, width, Color()); - ERR_FAIL_INDEX_V(p_y, height, Color()); - -#endif - - uint32_t ofs = p_y * width + p_x; +Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const { switch (format) { case FORMAT_L8: { @@ -2441,14 +2639,13 @@ Color Image::get_pixel(int p_x, int p_y) const { float a = (u & 0xF) / 15.0; return Color(r, g, b, a); } - case FORMAT_RGBA5551: { + case FORMAT_RGB565: { uint16_t u = ((uint16_t *)ptr)[ofs]; - float r = ((u >> 11) & 0x1F) / 15.0; - float g = ((u >> 6) & 0x1F) / 15.0; - float b = ((u >> 1) & 0x1F) / 15.0; - float a = (u & 0x1) / 1.0; - return Color(r, g, b, a); + float r = (u & 0x1F) / 31.0; + float g = ((u >> 5) & 0x3F) / 63.0; + float b = ((u >> 11) & 0x1F) / 31.0; + return Color(r, g, b, 1.0); } case FORMAT_RF: { @@ -2511,23 +2708,7 @@ Color Image::get_pixel(int p_x, int p_y) const { } } -void Image::set_pixelv(const Point2 &p_dst, const Color &p_color) { - set_pixel(p_dst.x, p_dst.y, p_color); -} - -void Image::set_pixel(int p_x, int p_y, const Color &p_color) { - - uint8_t *ptr = write_lock.ptr(); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!ptr, "Image must be locked with 'lock()' before using set_pixel()."); - - ERR_FAIL_INDEX(p_x, width); - ERR_FAIL_INDEX(p_y, height); - -#endif - - uint32_t ofs = p_y * width + p_x; - +void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color) { switch (format) { case FORMAT_L8: { ptr[ofs] = uint8_t(CLAMP(p_color.get_v() * 255.0, 0, 255)); @@ -2569,14 +2750,13 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) { ((uint16_t *)ptr)[ofs] = rgba; } break; - case FORMAT_RGBA5551: { + case FORMAT_RGB565: { uint16_t rgba = 0; - rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31)) << 11; - rgba |= uint16_t(CLAMP(p_color.g * 31.0, 0, 31)) << 6; - rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 1; - rgba |= uint16_t(p_color.a > 0.5 ? 1 : 0); + rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31)); + rgba |= uint16_t(CLAMP(p_color.g * 63.0, 0, 33)) << 5; + rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 11; ((uint16_t *)ptr)[ofs] = rgba; @@ -2636,12 +2816,36 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) { } } -Image::DetectChannels Image::get_detected_channels() { +Color Image::get_pixel(int p_x, int p_y) const { +#ifdef DEBUG_ENABLED + ERR_FAIL_INDEX_V(p_x, width, Color()); + ERR_FAIL_INDEX_V(p_y, height, Color()); +#endif + + uint32_t ofs = p_y * width + p_x; + return _get_color_at_ofs(data.ptr(), ofs); +} + +void Image::set_pixelv(const Point2 &p_dst, const Color &p_color) { + set_pixel(p_dst.x, p_dst.y, p_color); +} - ERR_FAIL_COND_V(data.size() == 0, DETECTED_RGBA); - ERR_FAIL_COND_V(is_compressed(), DETECTED_RGBA); +void Image::set_pixel(int p_x, int p_y, const Color &p_color) { +#ifdef DEBUG_ENABLED + ERR_FAIL_INDEX(p_x, width); + ERR_FAIL_INDEX(p_y, height); +#endif + + uint32_t ofs = p_y * width + p_x; + _set_color_at_ofs(data.ptrw(), ofs, p_color); +} + +Image::UsedChannels Image::detect_used_channels(CompressSource p_source) { + + ERR_FAIL_COND_V(data.size() == 0, USED_CHANNELS_RGBA); + ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA); bool r = false, g = false, b = false, a = false, c = false; - lock(); + for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { @@ -2662,33 +2866,42 @@ Image::DetectChannels Image::get_detected_channels() { } } - unlock(); + UsedChannels used_channels; if (!c && !a) - return DETECTED_L; - if (!c && a) - return DETECTED_LA; - - if (r && !g && !b && !a) - return DETECTED_R; + used_channels = USED_CHANNELS_L; + else if (!c && a) + used_channels = USED_CHANNELS_LA; + else if (r && !g && !b && !a) + used_channels = USED_CHANNELS_R; + else if (r && g && !b && !a) + used_channels = USED_CHANNELS_RG; + else if (r && g && b && !a) + used_channels = USED_CHANNELS_RGB; + else + used_channels = USED_CHANNELS_RGBA; - if (r && g && !b && !a) - return DETECTED_RG; + if (p_source == COMPRESS_SOURCE_SRGB && (used_channels == USED_CHANNELS_R || used_channels == USED_CHANNELS_RG)) { + //R and RG do not support SRGB + used_channels = USED_CHANNELS_RGB; + } - if (r && g && b && !a) - return DETECTED_RGB; + if (p_source == COMPRESS_SOURCE_NORMAL) { + //use RG channels only for normal + used_channels = USED_CHANNELS_RG; + } - return DETECTED_RGBA; + return used_channels; } void Image::optimize_channels() { - switch (get_detected_channels()) { - case DETECTED_L: convert(FORMAT_L8); break; - case DETECTED_LA: convert(FORMAT_LA8); break; - case DETECTED_R: convert(FORMAT_R8); break; - case DETECTED_RG: convert(FORMAT_RG8); break; - case DETECTED_RGB: convert(FORMAT_RGB8); break; - case DETECTED_RGBA: convert(FORMAT_RGBA8); break; + switch (detect_used_channels()) { + case USED_CHANNELS_L: convert(FORMAT_L8); break; + case USED_CHANNELS_LA: convert(FORMAT_LA8); break; + case USED_CHANNELS_R: convert(FORMAT_R8); break; + case USED_CHANNELS_RG: convert(FORMAT_RG8); break; + case USED_CHANNELS_RGB: convert(FORMAT_RGB8); break; + case USED_CHANNELS_RGBA: convert(FORMAT_RGBA8); break; } } @@ -2728,7 +2941,9 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("detect_alpha"), &Image::detect_alpha); ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible); - ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality"), &Image::compress); + ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC)); + ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7)); + ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality"), &Image::compress, DEFVAL(0.7)); ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress); ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed); @@ -2753,8 +2968,6 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data", "data"), &Image::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &Image::_get_data); - ClassDB::bind_method(D_METHOD("lock"), &Image::lock); - ClassDB::bind_method(D_METHOD("unlock"), &Image::unlock); ClassDB::bind_method(D_METHOD("get_pixelv", "src"), &Image::get_pixelv); ClassDB::bind_method(D_METHOD("get_pixel", "x", "y"), &Image::get_pixel); ClassDB::bind_method(D_METHOD("set_pixelv", "dst", "color"), &Image::set_pixelv); @@ -2776,7 +2989,7 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(FORMAT_RGB8); BIND_ENUM_CONSTANT(FORMAT_RGBA8); BIND_ENUM_CONSTANT(FORMAT_RGBA4444); - BIND_ENUM_CONSTANT(FORMAT_RGBA5551); + BIND_ENUM_CONSTANT(FORMAT_RGB565); BIND_ENUM_CONSTANT(FORMAT_RF); //float BIND_ENUM_CONSTANT(FORMAT_RGF); BIND_ENUM_CONSTANT(FORMAT_RGBF); @@ -2806,6 +3019,8 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8); BIND_ENUM_CONSTANT(FORMAT_ETC2_RGBA8); BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8A1); + BIND_ENUM_CONSTANT(FORMAT_ETC2_RA_AS_RG); + BIND_ENUM_CONSTANT(FORMAT_DXT5_RA_AS_RG); BIND_ENUM_CONSTANT(FORMAT_MAX); BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST); @@ -2824,17 +3039,24 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(COMPRESS_ETC); BIND_ENUM_CONSTANT(COMPRESS_ETC2); + BIND_ENUM_CONSTANT(USED_CHANNELS_L); + BIND_ENUM_CONSTANT(USED_CHANNELS_LA); + BIND_ENUM_CONSTANT(USED_CHANNELS_R); + BIND_ENUM_CONSTANT(USED_CHANNELS_RG); + BIND_ENUM_CONSTANT(USED_CHANNELS_RGB); + BIND_ENUM_CONSTANT(USED_CHANNELS_RGBA); + BIND_ENUM_CONSTANT(COMPRESS_SOURCE_GENERIC); BIND_ENUM_CONSTANT(COMPRESS_SOURCE_SRGB); BIND_ENUM_CONSTANT(COMPRESS_SOURCE_NORMAL); } -void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, CompressSource)) { +void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)) { _image_compress_bc_func = p_compress_func; } -void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, CompressSource)) { +void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)) { _image_compress_bptc_func = p_compress_func; } @@ -2845,8 +3067,7 @@ void Image::normalmap_to_xy() { { int len = data.size() / 4; - PoolVector<uint8_t>::Write wp = data.write(); - unsigned char *data_ptr = wp.ptr(); + uint8_t *data_ptr = data.ptrw(); for (int i = 0; i < len; i++) { @@ -2870,19 +3091,12 @@ Ref<Image> Image::rgbe_to_srgb() { new_image.instance(); new_image->create(width, height, 0, Image::FORMAT_RGB8); - lock(); - - new_image->lock(); - for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { new_image->set_pixel(col, row, get_pixel(col, row).to_srgb()); } } - unlock(); - new_image->unlock(); - if (has_mipmaps()) { new_image->generate_mipmaps(); } @@ -2890,21 +3104,46 @@ Ref<Image> Image::rgbe_to_srgb() { return new_image; } +Ref<Image> Image::get_image_from_mipmap(int p_mipamp) const { + + int ofs, size, w, h; + get_mipmap_offset_size_and_dimensions(p_mipamp, ofs, size, w, h); + + Vector<uint8_t> new_data; + new_data.resize(size); + + { + uint8_t *wr = new_data.ptrw(); + const uint8_t *rd = data.ptr(); + copymem(wr, rd + ofs, size); + } + + Ref<Image> image; + image.instance(); + image->width = w; + image->height = h; + image->format = format; + image->data = new_data; + + image->mipmaps = false; + return image; +} + void Image::bumpmap_to_normalmap(float bump_scale) { ERR_FAIL_COND(!_can_modify(format)); convert(Image::FORMAT_RF); - PoolVector<uint8_t> result_image; //rgba output + Vector<uint8_t> result_image; //rgba output result_image.resize(width * height * 4); { - PoolVector<uint8_t>::Read rp = data.read(); - PoolVector<uint8_t>::Write wp = result_image.write(); + const uint8_t *rp = data.ptr(); + uint8_t *wp = result_image.ptrw(); - ERR_FAIL_COND(!rp.ptr()); + ERR_FAIL_COND(!rp); - unsigned char *write_ptr = wp.ptr(); - float *read_ptr = (float *)rp.ptr(); + unsigned char *write_ptr = wp; + float *read_ptr = (float *)rp; for (int ty = 0; ty < height; ty++) { int py = ty + 1; @@ -2945,8 +3184,7 @@ void Image::srgb_to_linear() { if (format == FORMAT_RGBA8) { int len = data.size() / 4; - PoolVector<uint8_t>::Write wp = data.write(); - unsigned char *data_ptr = wp.ptr(); + uint8_t *data_ptr = data.ptrw(); for (int i = 0; i < len; i++) { @@ -2958,8 +3196,7 @@ void Image::srgb_to_linear() { } else if (format == FORMAT_RGB8) { int len = data.size() / 3; - PoolVector<uint8_t>::Write wp = data.write(); - unsigned char *data_ptr = wp.ptr(); + uint8_t *data_ptr = data.ptrw(); for (int i = 0; i < len; i++) { @@ -2978,8 +3215,7 @@ void Image::premultiply_alpha() { if (format != FORMAT_RGBA8) return; //not needed - PoolVector<uint8_t>::Write wp = data.write(); - unsigned char *data_ptr = wp.ptr(); + uint8_t *data_ptr = data.ptrw(); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { @@ -3001,12 +3237,10 @@ void Image::fix_alpha_edges() { if (format != FORMAT_RGBA8) return; //not needed - PoolVector<uint8_t> dcopy = data; - PoolVector<uint8_t>::Read rp = dcopy.read(); - const uint8_t *srcptr = rp.ptr(); + Vector<uint8_t> dcopy = data; + const uint8_t *srcptr = dcopy.ptr(); - PoolVector<uint8_t>::Write wp = data.write(); - unsigned char *data_ptr = wp.ptr(); + uint8_t *data_ptr = data.ptrw(); const int max_radius = 4; const int alpha_threshold = 20; @@ -3066,27 +3300,52 @@ String Image::get_format_name(Format p_format) { return format_names[p_format]; } -Error Image::load_png_from_buffer(const PoolVector<uint8_t> &p_array) { +Error Image::load_png_from_buffer(const Vector<uint8_t> &p_array) { return _load_from_buffer(p_array, _png_mem_loader_func); } -Error Image::load_jpg_from_buffer(const PoolVector<uint8_t> &p_array) { +Error Image::load_jpg_from_buffer(const Vector<uint8_t> &p_array) { return _load_from_buffer(p_array, _jpg_mem_loader_func); } -Error Image::load_webp_from_buffer(const PoolVector<uint8_t> &p_array) { +Error Image::load_webp_from_buffer(const Vector<uint8_t> &p_array) { return _load_from_buffer(p_array, _webp_mem_loader_func); } -Error Image::_load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadFunc p_loader) { +void Image::convert_rg_to_ra_rgba8() { + ERR_FAIL_COND(format != FORMAT_RGBA8); + ERR_FAIL_COND(!data.size()); + + int s = data.size(); + uint8_t *w = data.ptrw(); + for (int i = 0; i < s; i += 4) { + w[i + 3] = w[i + 1]; + w[i + 1] = 0; + w[i + 2] = 0; + } +} +void Image::convert_ra_rgba8_to_rg() { + ERR_FAIL_COND(format != FORMAT_RGBA8); + ERR_FAIL_COND(!data.size()); + + int s = data.size(); + uint8_t *w = data.ptrw(); + for (int i = 0; i < s; i += 4) { + w[i + 1] = w[i + 3]; + w[i + 2] = 0; + w[i + 3] = 255; + } +} + +Error Image::_load_from_buffer(const Vector<uint8_t> &p_array, ImageMemLoadFunc p_loader) { int buffer_size = p_array.size(); ERR_FAIL_COND_V(buffer_size == 0, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(!p_loader, ERR_INVALID_PARAMETER); - PoolVector<uint8_t>::Read r = p_array.read(); + const uint8_t *r = p_array.ptr(); - Ref<Image> image = p_loader(r.ptr(), buffer_size); + Ref<Image> image = p_loader(r, buffer_size); ERR_FAIL_COND_V(!image.is_valid(), ERR_PARSE_ERROR); copy_internals_from(image); @@ -3176,8 +3435,4 @@ Image::Image() { } Image::~Image() { - - if (write_lock.ptr()) { - unlock(); - } } diff --git a/core/image.h b/core/image.h index c15cfc9f6f..4dc4bf1328 100644 --- a/core/image.h +++ b/core/image.h @@ -33,7 +33,7 @@ #include "core/color.h" #include "core/math/rect2.h" -#include "core/pool_vector.h" + #include "core/resource.h" /** @@ -47,6 +47,7 @@ class Image; typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img); +typedef Vector<uint8_t> (*SavePNGBufferFunc)(const Ref<Image> &p_img); typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size); typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale); @@ -57,10 +58,12 @@ class Image : public Resource { public: static SavePNGFunc save_png_func; static SaveEXRFunc save_exr_func; + static SavePNGBufferFunc save_png_buffer_func; enum { - MAX_WIDTH = 16384, // force a limit somehow - MAX_HEIGHT = 16384 // force a limit somehow + MAX_WIDTH = (1 << 24), // force a limit somehow + MAX_HEIGHT = (1 << 24), // force a limit somehow + MAX_PIXELS = 268435456 }; enum Format { @@ -72,7 +75,7 @@ public: FORMAT_RGB8, FORMAT_RGBA8, FORMAT_RGBA4444, - FORMAT_RGBA5551, + FORMAT_RGB565, FORMAT_RF, //float FORMAT_RGF, FORMAT_RGBF, @@ -102,6 +105,8 @@ public: FORMAT_ETC2_RGB8, FORMAT_ETC2_RGBA8, FORMAT_ETC2_RGB8A1, + FORMAT_ETC2_RA_AS_RG, //used to make basis universal happy + FORMAT_DXT5_RA_AS_RG, //used to make basis universal happy FORMAT_MAX }; @@ -117,25 +122,27 @@ public: /* INTERPOLATE GAUSS */ }; - enum CompressSource { - COMPRESS_SOURCE_GENERIC, - COMPRESS_SOURCE_SRGB, - COMPRESS_SOURCE_NORMAL, - COMPRESS_SOURCE_LAYERED, + //this is used for compression + enum UsedChannels { + USED_CHANNELS_L, + USED_CHANNELS_LA, + USED_CHANNELS_R, + USED_CHANNELS_RG, + USED_CHANNELS_RGB, + USED_CHANNELS_RGBA, }; - //some functions provided by something else static ImageMemLoadFunc _png_mem_loader_func; static ImageMemLoadFunc _jpg_mem_loader_func; static ImageMemLoadFunc _webp_mem_loader_func; - static void (*_image_compress_bc_func)(Image *, float, CompressSource p_source); - static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, CompressSource p_source); + static void (*_image_compress_bc_func)(Image *, float, UsedChannels p_channels); + static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels); static void (*_image_compress_pvrtc2_func)(Image *); static void (*_image_compress_pvrtc4_func)(Image *); static void (*_image_compress_etc1_func)(Image *, float); - static void (*_image_compress_etc2_func)(Image *, float, CompressSource p_source); + static void (*_image_compress_etc2_func)(Image *, float, UsedChannels p_channels); static void (*_image_decompress_pvrtc)(Image *); static void (*_image_decompress_bc)(Image *); @@ -143,12 +150,15 @@ public: static void (*_image_decompress_etc1)(Image *); static void (*_image_decompress_etc2)(Image *); - static PoolVector<uint8_t> (*lossy_packer)(const Ref<Image> &p_image, float p_quality); - static Ref<Image> (*lossy_unpacker)(const PoolVector<uint8_t> &p_buffer); - static PoolVector<uint8_t> (*lossless_packer)(const Ref<Image> &p_image); - static Ref<Image> (*lossless_unpacker)(const PoolVector<uint8_t> &p_buffer); + static Vector<uint8_t> (*lossy_packer)(const Ref<Image> &p_image, float p_quality); + static Ref<Image> (*lossy_unpacker)(const Vector<uint8_t> &p_buffer); + static Vector<uint8_t> (*lossless_packer)(const Ref<Image> &p_image); + static Ref<Image> (*lossless_unpacker)(const Vector<uint8_t> &p_buffer); + static Vector<uint8_t> (*basis_universal_packer)(const Ref<Image> &p_image, UsedChannels p_channels); + static Ref<Image> (*basis_universal_unpacker)(const Vector<uint8_t> &p_buffer); - PoolVector<uint8_t>::Write write_lock; + _FORCE_INLINE_ Color _get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const; + _FORCE_INLINE_ void _set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color); protected: static void _bind_methods(); @@ -158,12 +168,12 @@ private: create(p_width, p_height, p_use_mipmaps, p_format); } - void _create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data) { + void _create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { create(p_width, p_height, p_use_mipmaps, p_format, p_data); } Format format; - PoolVector<uint8_t> data; + Vector<uint8_t> data; int width, height; bool mipmaps; @@ -177,7 +187,7 @@ private: _FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data - static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1); + static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1, int *r_mm_width = NULL, int *r_mm_height = NULL); bool _can_modify(Format p_format) const; _FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel); @@ -186,7 +196,7 @@ private: void _set_data(const Dictionary &p_data); Dictionary _get_data() const; - Error _load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadFunc p_loader); + Error _load_from_buffer(const Vector<uint8_t> &p_array, ImageMemLoadFunc p_loader); static void average_4_uint8(uint8_t &p_out, const uint8_t &p_a, const uint8_t &p_b, const uint8_t &p_c, const uint8_t &p_d); static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d); @@ -214,6 +224,7 @@ public: */ Format get_format() const; + int get_mipmap_byte_size(int p_mipmap) const; //get where the mipmap begins in data int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data void get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const; //get where the mipmap begins in data void get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int &r_size, int &w, int &h) const; //get where the mipmap begins in data @@ -240,6 +251,16 @@ public: */ Error generate_mipmaps(bool p_renormalize = false); + enum RoughnessChannel { + ROUGHNESS_CHANNEL_R, + ROUGHNESS_CHANNEL_G, + ROUGHNESS_CHANNEL_B, + ROUGHNESS_CHANNEL_A, + ROUGHNESS_CHANNEL_L, + }; + + Error generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref<Image> &p_normal_map); + void clear_mipmaps(); void normalize(); //for normal maps @@ -247,7 +268,7 @@ public: * Create a new image of a given size and format. Current image will be lost */ void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format); - void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data); + void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); void create(const char **p_xpm); /** @@ -255,10 +276,11 @@ public: */ bool empty() const; - PoolVector<uint8_t> get_data() const; + Vector<uint8_t> get_data() const; Error load(const String &p_path); Error save_png(const String &p_path) const; + Vector<uint8_t> save_png_to_buffer() const; Error save_exr(const String &p_path, bool p_grayscale) const; /** @@ -272,7 +294,7 @@ public: /** * import an image of a specific size and format from a pointer */ - Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data); + Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data); enum AlphaMode { ALPHA_NONE, @@ -290,7 +312,9 @@ public: static int get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps = false); static int get_image_required_mipmaps(int p_width, int p_height, Format p_format); + static Size2i get_image_mipmap_size(int p_width, int p_height, Format p_format, int p_mipmap); static int get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap); + static int get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h); enum CompressMode { COMPRESS_S3TC, @@ -300,8 +324,14 @@ public: COMPRESS_ETC2, COMPRESS_BPTC }; + enum CompressSource { + COMPRESS_SOURCE_GENERIC, + COMPRESS_SOURCE_SRGB, + COMPRESS_SOURCE_NORMAL + }; - Error compress(CompressMode p_mode = COMPRESS_S3TC, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7); + Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7); + Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality = 0.7); Error decompress(); bool is_compressed() const; @@ -310,6 +340,7 @@ public: void srgb_to_linear(); void normalmap_to_xy(); Ref<Image> rgbe_to_srgb(); + Ref<Image> get_image_from_mipmap(int p_mipamp) const; void bumpmap_to_normalmap(float bump_scale = 1.0); void blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); @@ -321,33 +352,23 @@ public: Rect2 get_used_rect() const; Ref<Image> get_rect(const Rect2 &p_area) const; - static void set_compress_bc_func(void (*p_compress_func)(Image *, float, CompressSource)); - static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, CompressSource)); + static void set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)); + static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)); static String get_format_name(Format p_format); - Error load_png_from_buffer(const PoolVector<uint8_t> &p_array); - Error load_jpg_from_buffer(const PoolVector<uint8_t> &p_array); - Error load_webp_from_buffer(const PoolVector<uint8_t> &p_array); + Error load_png_from_buffer(const Vector<uint8_t> &p_array); + Error load_jpg_from_buffer(const Vector<uint8_t> &p_array); + Error load_webp_from_buffer(const Vector<uint8_t> &p_array); + + void convert_rg_to_ra_rgba8(); + void convert_ra_rgba8_to_rg(); Image(const uint8_t *p_mem_png_jpg, int p_len = -1); Image(const char **p_xpm); virtual Ref<Resource> duplicate(bool p_subresources = false) const; - void lock(); - void unlock(); - - //this is used for compression - enum DetectChannels { - DETECTED_L, - DETECTED_LA, - DETECTED_R, - DETECTED_RG, - DETECTED_RGB, - DETECTED_RGBA, - }; - - DetectChannels get_detected_channels(); + UsedChannels detect_used_channels(CompressSource p_source = COMPRESS_SOURCE_GENERIC); void optimize_channels(); Color get_pixelv(const Point2 &p_src) const; @@ -371,6 +392,8 @@ VARIANT_ENUM_CAST(Image::Format) VARIANT_ENUM_CAST(Image::Interpolation) VARIANT_ENUM_CAST(Image::CompressMode) VARIANT_ENUM_CAST(Image::CompressSource) +VARIANT_ENUM_CAST(Image::UsedChannels) VARIANT_ENUM_CAST(Image::AlphaMode) +VARIANT_ENUM_CAST(Image::RoughnessChannel) #endif diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 5c25cad770..b44ac16a87 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -34,11 +34,11 @@ #include "core/os/keyboard.h" #include "core/variant_parser.h" -PoolStringArray ConfigFile::_get_sections() const { +PackedStringArray ConfigFile::_get_sections() const { List<String> s; get_sections(&s); - PoolStringArray arr; + PackedStringArray arr; arr.resize(s.size()); int idx = 0; for (const List<String>::Element *E = s.front(); E; E = E->next()) { @@ -49,11 +49,11 @@ PoolStringArray ConfigFile::_get_sections() const { return arr; } -PoolStringArray ConfigFile::_get_section_keys(const String &p_section) const { +PackedStringArray ConfigFile::_get_section_keys(const String &p_section) const { List<String> s; get_section_keys(p_section, &s); - PoolStringArray arr; + PackedStringArray arr; arr.resize(s.size()); int idx = 0; for (const List<String>::Element *E = s.front(); E; E = E->next()) { @@ -86,9 +86,10 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V Variant ConfigFile::get_value(const String &p_section, const String &p_key, Variant p_default) const { if (!values.has(p_section) || !values[p_section].has(p_key)) { - ERR_FAIL_COND_V_MSG(p_default.get_type() == Variant::NIL, p_default, "Couldn't find the given section/key and no default was given."); + ERR_FAIL_COND_V_MSG(p_default.get_type() == Variant::NIL, Variant(), "Couldn't find the given section '" + p_section + "', key '" + p_key + "' and no default was given."); return p_default; } + return values[p_section][p_key]; } @@ -255,6 +256,22 @@ Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) { VariantParser::StreamFile stream; stream.f = f; + Error err = _parse(p_path, &stream); + + memdelete(f); + + return err; +} + +Error ConfigFile::parse(const String &p_data) { + + VariantParser::StreamString stream; + stream.s = p_data; + return _parse("<string>", &stream); +} + +Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream) { + String assign; Variant value; VariantParser::Tag next_tag; @@ -270,13 +287,11 @@ Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) { next_tag.fields.clear(); next_tag.name = String(); - Error err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true); + Error err = VariantParser::parse_tag_assign_eof(p_stream, lines, error_text, next_tag, assign, value, NULL, true); if (err == ERR_FILE_EOF) { - memdelete(f); return OK; } else if (err != OK) { - ERR_PRINTS("ConfgFile::load - " + p_path + ":" + itos(lines) + " error: " + error_text + "."); - memdelete(f); + ERR_PRINT("ConfgFile - " + p_path + ":" + itos(lines) + " error: " + error_text + "."); return err; } @@ -286,6 +301,8 @@ Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) { section = next_tag.name; } } + + return OK; } void ConfigFile::_bind_methods() { @@ -303,6 +320,7 @@ void ConfigFile::_bind_methods() { ClassDB::bind_method(D_METHOD("erase_section_key", "section", "key"), &ConfigFile::erase_section_key); ClassDB::bind_method(D_METHOD("load", "path"), &ConfigFile::load); + ClassDB::bind_method(D_METHOD("parse", "data"), &ConfigFile::parse); ClassDB::bind_method(D_METHOD("save", "path"), &ConfigFile::save); ClassDB::bind_method(D_METHOD("load_encrypted", "path", "key"), &ConfigFile::load_encrypted); diff --git a/core/io/config_file.h b/core/io/config_file.h index 95a581d156..150fd24693 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -34,6 +34,7 @@ #include "core/ordered_hash_map.h" #include "core/os/file_access.h" #include "core/reference.h" +#include "core/variant_parser.h" class ConfigFile : public Reference { @@ -41,11 +42,13 @@ class ConfigFile : public Reference { OrderedHashMap<String, OrderedHashMap<String, Variant> > values; - PoolStringArray _get_sections() const; - PoolStringArray _get_section_keys(const String &p_section) const; + PackedStringArray _get_sections() const; + PackedStringArray _get_section_keys(const String &p_section) const; Error _internal_load(const String &p_path, FileAccess *f); Error _internal_save(FileAccess *file); + Error _parse(const String &p_path, VariantParser::Stream *p_stream); + protected: static void _bind_methods(); @@ -64,6 +67,7 @@ public: Error save(const String &p_path); Error load(const String &p_path); + Error parse(const String &p_data); Error load_encrypted(const String &p_path, const Vector<uint8_t> &p_key); Error load_encrypted_pass(const String &p_path, const String &p_pass); diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp new file mode 100644 index 0000000000..aa302ced8f --- /dev/null +++ b/core/io/dtls_server.cpp @@ -0,0 +1,54 @@ +/*************************************************************************/ +/* dtls_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 "dtls_server.h" +#include "core/os/file_access.h" +#include "core/project_settings.h" + +DTLSServer *(*DTLSServer::_create)() = NULL; +bool DTLSServer::available = false; + +DTLSServer *DTLSServer::create() { + + return _create(); +} + +bool DTLSServer::is_available() { + return available; +} + +void DTLSServer::_bind_methods() { + + ClassDB::bind_method(D_METHOD("setup", "key", "certificate", "chain"), &DTLSServer::setup, DEFVAL(Ref<X509Certificate>())); + ClassDB::bind_method(D_METHOD("take_connection", "udp_peer"), &DTLSServer::take_connection); +} + +DTLSServer::DTLSServer() { +} diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h new file mode 100644 index 0000000000..ebef13da64 --- /dev/null +++ b/core/io/dtls_server.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* dtls_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 DTLS_SERVER_H +#define DTLS_SERVER_H + +#include "core/io/net_socket.h" +#include "core/io/packet_peer_dtls.h" + +class DTLSServer : public Reference { + GDCLASS(DTLSServer, Reference); + +protected: + static DTLSServer *(*_create)(); + static void _bind_methods(); + + static bool available; + +public: + static bool is_available(); + static DTLSServer *create(); + + virtual Error setup(Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>()) = 0; + virtual void stop() = 0; + virtual Ref<PacketPeerDTLS> take_connection(Ref<PacketPeerUDP> p_peer) = 0; + + DTLSServer(); +}; + +#endif // DTLS_SERVER_H diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp index 6ac065a19b..ab0fb3943c 100644 --- a/core/io/file_access_buffered.cpp +++ b/core/io/file_access_buffered.cpp @@ -113,7 +113,7 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { int size = (cache.buffer.size() - (file.offset - cache.offset)); size = size - (size % 4); - //PoolVector<uint8_t>::Read read = cache.buffer.read(); + //const uint8_t* read = cache.buffer.ptr(); //memcpy(p_dest, read.ptr() + (file.offset - cache.offset), size); memcpy(p_dest, cache.buffer.ptr() + (file.offset - cache.offset), size); p_dest += size; @@ -145,7 +145,7 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { } int r = MIN(left, to_read); - //PoolVector<uint8_t>::Read read = cache.buffer.read(); + //const uint8_t* read = cache.buffer.ptr(); //memcpy(p_dest+total_read, &read.ptr()[file.offset - cache.offset], r); memcpy(p_dest + total_read, cache.buffer.ptr() + (file.offset - cache.offset), r); diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h index 5e2939c1a2..a6177c20be 100644 --- a/core/io/file_access_buffered.h +++ b/core/io/file_access_buffered.h @@ -32,7 +32,7 @@ #define FILE_ACCESS_BUFFERED_H #include "core/os/file_access.h" -#include "core/pool_vector.h" + #include "core/ustring.h" class FileAccessBuffered : public FileAccess { diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h index c17652080c..6ec77d503b 100644 --- a/core/io/file_access_buffered_fa.h +++ b/core/io/file_access_buffered_fa.h @@ -54,8 +54,8 @@ class FileAccessBufferedFA : public FileAccessBuffered { cache.offset = p_offset; cache.buffer.resize(p_size); - // on PoolVector - //PoolVector<uint8_t>::Write write = cache.buffer.write(); + // on Vector + //uint8_t* write = cache.buffer.ptrw(); //f.get_buffer(write.ptrw(), p_size); // on vector diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index 87ead37b91..17cc6ce58f 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -63,6 +63,10 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) { f = p_base; cmode = (Compression::Mode)f->get_32(); block_size = f->get_32(); + if (block_size == 0) { + f = NULL; // Let the caller to handle the FileAccess object if failed to open as compressed file. + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted."); + } read_total = f->get_32(); int bc = (read_total / block_size) + 1; int acc_ofs = f->get_position() + bc * 4; @@ -125,13 +129,11 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) { char rmagic[5]; f->get_buffer((uint8_t *)rmagic, 4); rmagic[4] = 0; - if (magic != rmagic) { + if (magic != rmagic || open_after_magic(f) != OK) { memdelete(f); f = NULL; return ERR_FILE_UNRECOGNIZED; } - - open_after_magic(f); } return OK; diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index 1b09ac7208..202eb89dbd 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -231,7 +231,7 @@ FileAccessNetworkClient::FileAccessNetworkClient() { singleton = this; last_id = 0; client.instance(); - sem = Semaphore::create(); + sem = SemaphoreOld::create(); lockcount = 0; } @@ -522,8 +522,8 @@ FileAccessNetwork::FileAccessNetwork() { eof_flag = false; opened = false; pos = 0; - sem = Semaphore::create(); - page_sem = Semaphore::create(); + sem = SemaphoreOld::create(); + page_sem = SemaphoreOld::create(); buffer_mutex = Mutex::create(); FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; nc->lock_mutex(); diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index e2da1d0893..f329abf7c5 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -49,7 +49,7 @@ class FileAccessNetworkClient { List<BlockRequest> block_requests; - Semaphore *sem; + SemaphoreOld *sem; Thread *thread; bool quit; Mutex *mutex; @@ -85,8 +85,8 @@ public: class FileAccessNetwork : public FileAccess { - Semaphore *sem; - Semaphore *page_sem; + SemaphoreOld *sem; + SemaphoreOld *page_sem; Mutex *buffer_mutex; bool opened; size_t total_size; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 541bd3a7c8..ce7025de35 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -110,7 +110,7 @@ Ref<StreamPeer> HTTPClient::get_connection() const { return connection; } -Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) { +Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body) { ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); @@ -152,10 +152,10 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector request += "\r\n"; CharString cs = request.utf8(); - PoolVector<uint8_t> data; + Vector<uint8_t> data; data.resize(cs.length()); { - PoolVector<uint8_t>::Write data_write = data.write(); + uint8_t *data_write = data.ptrw(); for (int i = 0; i < cs.length(); i++) { data_write[i] = cs[i]; } @@ -163,7 +163,7 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector data.append_array(p_body); - PoolVector<uint8_t>::Read r = data.read(); + const uint8_t *r = data.ptr(); Error err = connection->put_data(&r[0], data.size()); if (err) { @@ -517,11 +517,11 @@ int HTTPClient::get_response_body_length() const { return body_size; } -PoolByteArray HTTPClient::read_response_body_chunk() { +PackedByteArray HTTPClient::read_response_body_chunk() { - ERR_FAIL_COND_V(status != STATUS_BODY, PoolByteArray()); + ERR_FAIL_COND_V(status != STATUS_BODY, PackedByteArray()); - PoolByteArray ret; + PackedByteArray ret; Error err = OK; if (chunked) { @@ -622,8 +622,8 @@ PoolByteArray HTTPClient::read_response_body_chunk() { } ret.resize(chunk.size() - 2); - PoolByteArray::Write w = ret.write(); - copymem(w.ptr(), chunk.ptr(), chunk.size() - 2); + uint8_t *w = ret.ptrw(); + copymem(w, chunk.ptr(), chunk.size() - 2); chunk.clear(); } @@ -639,8 +639,8 @@ PoolByteArray HTTPClient::read_response_body_chunk() { while (to_read > 0) { int rec = 0; { - PoolByteArray::Write w = ret.write(); - err = _get_http_data(w.ptr() + _offset, to_read, rec); + uint8_t *w = ret.ptrw(); + err = _get_http_data(w + _offset, to_read, rec); } if (rec <= 0) { // Ended up reading less ret.resize(_offset); @@ -801,11 +801,11 @@ Dictionary HTTPClient::_get_response_headers_as_dictionary() { return ret; } -PoolStringArray HTTPClient::_get_response_headers() { +PackedStringArray HTTPClient::_get_response_headers() { List<String> rh; get_response_headers(&rh); - PoolStringArray ret; + PackedStringArray ret; ret.resize(rh.size()); int idx = 0; for (const List<String>::Element *E = rh.front(); E; E = E->next()) { diff --git a/core/io/http_client.h b/core/io/http_client.h index 3796eb992c..03ba20f8dd 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -191,7 +191,7 @@ private: #include "platform/javascript/http_client.h.inc" #endif - PoolStringArray _get_response_headers(); + PackedStringArray _get_response_headers(); Dictionary _get_response_headers_as_dictionary(); static void _bind_methods(); @@ -202,7 +202,7 @@ public: void set_connection(const Ref<StreamPeer> &p_connection); Ref<StreamPeer> get_connection() const; - Error request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body); + Error request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body); Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body = String()); void close(); @@ -215,7 +215,7 @@ public: Error get_response_headers(List<String> *r_response); int get_response_body_length() const; - PoolByteArray read_response_body_chunk(); // Can't get body as partial text because of most encodings UTF8, gzip, etc. + PackedByteArray read_response_body_chunk(); // Can't get body as partial text because of most encodings UTF8, gzip, etc. void set_blocking_mode(bool p_enable); // Useful mostly if running in a thread bool is_blocking_mode_enabled() const; diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index 05929ee8ed..720f25f91b 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -53,7 +53,7 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c Error err; f = FileAccess::open(p_file, FileAccess::READ, &err); if (!f) { - ERR_PRINTS("Error opening file '" + p_file + "'."); + ERR_PRINT("Error opening file '" + p_file + "'."); return err; } } @@ -66,7 +66,7 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c continue; Error err = loader[i]->load_image(p_image, f, p_force_linear, p_scale); if (err != OK) { - ERR_PRINTS("Error loading image: " + p_file); + ERR_PRINT("Error loading image: " + p_file); } if (err != ERR_FILE_UNRECOGNIZED) { diff --git a/core/io/ip.cpp b/core/io/ip.cpp index ea791fb327..7d18117711 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -71,7 +71,7 @@ struct _IP_ResolverPrivate { } Mutex *mutex; - Semaphore *sem; + SemaphoreOld *sem; Thread *thread; //Semaphore* semaphore; @@ -184,7 +184,7 @@ IP_Address IP::get_resolve_item_address(ResolverID p_id) const { resolver->mutex->lock(); if (resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE) { - ERR_PRINTS("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet."); + ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet."); resolver->mutex->unlock(); return IP_Address(); } @@ -319,7 +319,7 @@ IP::IP() { #ifndef NO_THREADS - resolver->sem = Semaphore::create(); + resolver->sem = SemaphoreOld::create(); if (resolver->sem) { resolver->thread_abort = false; diff --git a/core/io/json.cpp b/core/io/json.cpp index dbf1676e62..08a147032f 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -71,9 +71,9 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_ case Variant::BOOL: return p_var.operator bool() ? "true" : "false"; case Variant::INT: return itos(p_var); case Variant::REAL: return rtos(p_var); - case Variant::POOL_INT_ARRAY: - case Variant::POOL_REAL_ARRAY: - case Variant::POOL_STRING_ARRAY: + case Variant::PACKED_INT_ARRAY: + case Variant::PACKED_REAL_ARRAY: + case Variant::PACKED_STRING_ARRAY: case Variant::ARRAY: { String s = "["; @@ -203,8 +203,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to case 'f': res = 12; break; case 'r': res = 13; break; case 'u': { - //hexnumbarh - oct is deprecated - + // hex number for (int j = 0; j < 4; j++) { CharType c = p_str[index + j + 1]; if (c == 0) { @@ -226,7 +225,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to v = c - 'A'; v += 10; } else { - ERR_PRINT("BUG"); + ERR_PRINT("Bug parsing hex constant."); v = 0; } @@ -236,13 +235,8 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to index += 4; //will add at the end anyway } break; - //case '\"': res='\"'; break; - //case '\\': res='\\'; break; - //case '/': res='/'; break; default: { res = next; - //r_err_str="Invalid escape sequence"; - //return ERR_PARSE_ERROR; } break; } diff --git a/core/io/logger.cpp b/core/io/logger.cpp index c3ea0d024e..4d732332d5 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -58,12 +58,12 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c return; } - const char *err_type = "**ERROR**"; + const char *err_type = "ERROR"; switch (p_type) { - case ERR_ERROR: err_type = "**ERROR**"; break; - case ERR_WARNING: err_type = "**WARNING**"; break; - case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break; - case ERR_SHADER: err_type = "**SHADER ERROR**"; break; + case ERR_ERROR: err_type = "ERROR"; break; + case ERR_WARNING: err_type = "WARNING"; break; + case ERR_SCRIPT: err_type = "SCRIPT ERROR"; break; + case ERR_SHADER: err_type = "SHADER ERROR"; break; default: ERR_PRINT("Unknown error type"); break; } @@ -74,7 +74,7 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c err_details = p_code; logf_error("%s: %s\n", err_type, err_details); - logf_error(" At: %s:%i:%s() - %s\n", p_file, p_line, p_function, p_code); + logf_error(" at: %s (%s:%i) - %s\n", p_function, p_file, p_line, p_code); } void Logger::logf(const char *p_format, ...) { diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index e847a9cf0c..6548faac9f 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -53,8 +53,7 @@ ObjectID EncodedObjectAsID::get_object_id() const { return id; } -EncodedObjectAsID::EncodedObjectAsID() : - id(0) { +EncodedObjectAsID::EncodedObjectAsID() { } #define _S(a) ((int32_t)a) @@ -386,11 +385,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (type & ENCODE_FLAG_OBJECT_AS_ID) { //this _is_ allowed ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); - ObjectID val = decode_uint64(buf); + ObjectID val = ObjectID(decode_uint64(buf)); if (r_len) (*r_len) += 8; - if (val == 0) { + if (val.is_null()) { r_variant = (Object *)NULL; } else { Ref<EncodedObjectAsID> obj_as_id; @@ -536,7 +535,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; // arrays - case Variant::POOL_BYTE_ARRAY: { + case Variant::PACKED_BYTE_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -544,11 +543,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int len -= 4; ERR_FAIL_COND_V(count < 0 || count > len, ERR_INVALID_DATA); - PoolVector<uint8_t> data; + Vector<uint8_t> data; if (count) { data.resize(count); - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { w[i] = buf[i]; @@ -564,7 +563,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } } break; - case Variant::POOL_INT_ARRAY: { + case Variant::PACKED_INT_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -573,12 +572,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA); - PoolVector<int> data; + Vector<int> data; if (count) { //const int*rbuf=(const int*)buf; data.resize(count); - PoolVector<int>::Write w = data.write(); + int *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { w[i] = decode_uint32(&buf[i * 4]); @@ -590,7 +589,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } } break; - case Variant::POOL_REAL_ARRAY: { + case Variant::PACKED_REAL_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -599,12 +598,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA); - PoolVector<float> data; + Vector<float> data; if (count) { //const float*rbuf=(const float*)buf; data.resize(count); - PoolVector<float>::Write w = data.write(); + float *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { w[i] = decode_float(&buf[i * 4]); @@ -617,12 +616,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } } break; - case Variant::POOL_STRING_ARRAY: { + case Variant::PACKED_STRING_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); - PoolVector<String> strings; + Vector<String> strings; buf += 4; len -= 4; @@ -643,7 +642,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = strings; } break; - case Variant::POOL_VECTOR2_ARRAY: { + case Variant::PACKED_VECTOR2_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -652,7 +651,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4 * 2, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 * 2 > len, ERR_INVALID_DATA); - PoolVector<Vector2> varray; + Vector<Vector2> varray; if (r_len) { (*r_len) += 4; @@ -660,7 +659,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (count) { varray.resize(count); - PoolVector<Vector2>::Write w = varray.write(); + Vector2 *w = varray.ptrw(); for (int32_t i = 0; i < count; i++) { @@ -677,7 +676,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = varray; } break; - case Variant::POOL_VECTOR3_ARRAY: { + case Variant::PACKED_VECTOR3_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -687,7 +686,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4 * 3, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 * 3 > len, ERR_INVALID_DATA); - PoolVector<Vector3> varray; + Vector<Vector3> varray; if (r_len) { (*r_len) += 4; @@ -695,7 +694,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (count) { varray.resize(count); - PoolVector<Vector3>::Write w = varray.write(); + Vector3 *w = varray.ptrw(); for (int32_t i = 0; i < count; i++) { @@ -713,7 +712,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = varray; } break; - case Variant::POOL_COLOR_ARRAY: { + case Variant::PACKED_COLOR_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -723,7 +722,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4 * 4, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 * 4 > len, ERR_INVALID_DATA); - PoolVector<Color> carray; + Vector<Color> carray; if (r_len) { (*r_len) += 4; @@ -731,7 +730,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (count) { carray.resize(count); - PoolVector<Color>::Write w = carray.write(); + Color *w = carray.ptrw(); for (int32_t i = 0; i < count; i++) { @@ -803,10 +802,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; case Variant::OBJECT: { -#ifdef DEBUG_ENABLED + // Test for potential wrong values sent by the debugger when it breaks. - Object *obj = p_variant; - if (!obj || !ObjectDB::instance_validate(obj)) { + Object *obj = p_variant.get_validated_object(); + if (!obj) { // Object is invalid, send a NULL instead. if (buf) { encode_uint32(Variant::NIL, buf); @@ -814,7 +813,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4; return OK; } -#endif // DEBUG_ENABLED + if (!p_full_objects) { flags |= ENCODE_FLAG_OBJECT_AS_ID; } @@ -1128,9 +1127,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } else { if (buf) { - Object *obj = p_variant; - ObjectID id = 0; - if (obj && ObjectDB::instance_validate(obj)) { + Object *obj = p_variant.get_validated_object(); + ObjectID id; + if (obj) { id = obj->get_instance_id(); } @@ -1208,16 +1207,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; // arrays - case Variant::POOL_BYTE_ARRAY: { + case Variant::PACKED_BYTE_ARRAY: { - PoolVector<uint8_t> data = p_variant; + Vector<uint8_t> data = p_variant; int datalen = data.size(); int datasize = sizeof(uint8_t); if (buf) { encode_uint32(datalen, buf); buf += 4; - PoolVector<uint8_t>::Read r = data.read(); + const uint8_t *r = data.ptr(); copymem(buf, &r[0], datalen * datasize); buf += datalen * datasize; } @@ -1230,16 +1229,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; - case Variant::POOL_INT_ARRAY: { + case Variant::PACKED_INT_ARRAY: { - PoolVector<int> data = p_variant; + Vector<int> data = p_variant; int datalen = data.size(); int datasize = sizeof(int32_t); if (buf) { encode_uint32(datalen, buf); buf += 4; - PoolVector<int>::Read r = data.read(); + const int *r = data.ptr(); for (int i = 0; i < datalen; i++) encode_uint32(r[i], &buf[i * datasize]); } @@ -1247,16 +1246,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 + datalen * datasize; } break; - case Variant::POOL_REAL_ARRAY: { + case Variant::PACKED_REAL_ARRAY: { - PoolVector<real_t> data = p_variant; + Vector<real_t> data = p_variant; int datalen = data.size(); int datasize = sizeof(real_t); if (buf) { encode_uint32(datalen, buf); buf += 4; - PoolVector<real_t>::Read r = data.read(); + const real_t *r = data.ptr(); for (int i = 0; i < datalen; i++) encode_float(r[i], &buf[i * datasize]); } @@ -1264,9 +1263,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 + datalen * datasize; } break; - case Variant::POOL_STRING_ARRAY: { + case Variant::PACKED_STRING_ARRAY: { - PoolVector<String> data = p_variant; + Vector<String> data = p_variant; int len = data.size(); if (buf) { @@ -1296,9 +1295,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; - case Variant::POOL_VECTOR2_ARRAY: { + case Variant::PACKED_VECTOR2_ARRAY: { - PoolVector<Vector2> data = p_variant; + Vector<Vector2> data = p_variant; int len = data.size(); if (buf) { @@ -1323,9 +1322,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 * 2 * len; } break; - case Variant::POOL_VECTOR3_ARRAY: { + case Variant::PACKED_VECTOR3_ARRAY: { - PoolVector<Vector3> data = p_variant; + Vector<Vector3> data = p_variant; int len = data.size(); if (buf) { @@ -1351,9 +1350,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 * 3 * len; } break; - case Variant::POOL_COLOR_ARRAY: { + case Variant::PACKED_COLOR_ARRAY: { - PoolVector<Color> data = p_variant; + Vector<Color> data = p_variant; int len = data.size(); if (buf) { diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 381ac4c0bb..abe629ecba 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -32,6 +32,7 @@ #include "core/io/marshalls.h" #include "scene/main/node.h" +#include <stdint.h> #ifdef DEBUG_ENABLED #include "core/os/os.h" @@ -180,7 +181,8 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ } #endif - uint8_t packet_type = p_packet[0]; + // Extract the `packet_type` from the LSB three bits: + uint8_t packet_type = p_packet[0] & 7; switch (packet_type) { @@ -197,31 +199,80 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ case NETWORK_COMMAND_REMOTE_CALL: case NETWORK_COMMAND_REMOTE_SET: { - ERR_FAIL_COND_MSG(p_packet_len < 6, "Invalid packet received. Size too small."); - - Node *node = _process_get_node(p_from, p_packet, p_packet_len); + // Extract packet meta + int packet_min_size = 1; + int name_id_offset = 1; + ERR_FAIL_COND_MSG(p_packet_len < packet_min_size, "Invalid packet received. Size too small."); + // Compute the meta size, which depends on the compression level. + int node_id_compression = (p_packet[0] & 24) >> 3; + int name_id_compression = (p_packet[0] & 32) >> 5; + + switch (node_id_compression) { + case NETWORK_NODE_ID_COMPRESSION_8: + packet_min_size += 1; + name_id_offset += 1; + break; + case NETWORK_NODE_ID_COMPRESSION_16: + packet_min_size += 2; + name_id_offset += 2; + break; + case NETWORK_NODE_ID_COMPRESSION_32: + packet_min_size += 4; + name_id_offset += 4; + break; + default: + ERR_FAIL_MSG("Was not possible to extract the node id compression mode."); + } + switch (name_id_compression) { + case NETWORK_NAME_ID_COMPRESSION_8: + packet_min_size += 1; + break; + case NETWORK_NAME_ID_COMPRESSION_16: + packet_min_size += 2; + break; + default: + ERR_FAIL_MSG("Was not possible to extract the name id compression mode."); + } + ERR_FAIL_COND_MSG(p_packet_len < packet_min_size, "Invalid packet received. Size too small."); + uint32_t node_target = 0; + switch (node_id_compression) { + case NETWORK_NODE_ID_COMPRESSION_8: + node_target = p_packet[1]; + break; + case NETWORK_NODE_ID_COMPRESSION_16: + node_target = decode_uint16(p_packet + 1); + break; + case NETWORK_NODE_ID_COMPRESSION_32: + node_target = decode_uint32(p_packet + 1); + break; + default: + // Unreachable, checked before. + CRASH_NOW(); + } + Node *node = _process_get_node(p_from, p_packet, node_target, p_packet_len); ERR_FAIL_COND_MSG(node == NULL, "Invalid packet received. Requested node was not found."); - // Detect cstring end. - int len_end = 5; - for (; len_end < p_packet_len; len_end++) { - if (p_packet[len_end] == 0) { + uint16_t name_id = 0; + switch (name_id_compression) { + case NETWORK_NAME_ID_COMPRESSION_8: + name_id = p_packet[name_id_offset]; break; - } + case NETWORK_NAME_ID_COMPRESSION_16: + name_id = decode_uint16(p_packet + name_id_offset); + break; + default: + // Unreachable, checked before. + CRASH_NOW(); } - ERR_FAIL_COND_MSG(len_end >= p_packet_len, "Invalid packet received. Size too small."); - - StringName name = String::utf8((const char *)&p_packet[5]); - if (packet_type == NETWORK_COMMAND_REMOTE_CALL) { - _process_rpc(node, name, p_from, p_packet, p_packet_len, len_end + 1); + _process_rpc(node, name_id, p_from, p_packet, p_packet_len, packet_min_size); } else { - _process_rset(node, name, p_from, p_packet, p_packet_len, len_end + 1); + _process_rset(node, name_id, p_from, p_packet, p_packet_len, packet_min_size); } } break; @@ -233,15 +284,14 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ } } -Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len) { +Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len) { - uint32_t target = decode_uint32(&p_packet[1]); Node *node = NULL; - if (target & 0x80000000) { + if (p_node_target & 0x80000000) { // Use full path (not cached yet). - int ofs = target & 0x7FFFFFFF; + int ofs = p_node_target & 0x7FFFFFFF; ERR_FAIL_COND_V_MSG(ofs >= p_packet_len, NULL, "Invalid packet received. Size smaller than declared."); @@ -253,10 +303,10 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int node = root_node->get_node(np); if (!node) - ERR_PRINTS("Failed to get path from RPC: " + String(np) + "."); + ERR_PRINT("Failed to get path from RPC: " + String(np) + "."); } else { // Use cached path. - int id = target; + int id = p_node_target; Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from); ERR_FAIL_COND_V_MSG(!E, NULL, "Invalid packet received. Requests invalid peer cache."); @@ -269,26 +319,26 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int node = root_node->get_node(ni->path); if (!node) - ERR_PRINTS("Failed to get cached path from RPC: " + String(ni->path) + "."); + ERR_PRINT("Failed to get cached path from RPC: " + String(ni->path) + "."); } return node; } -void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { +void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); // Check that remote can call the RPC on this node. - RPCMode rpc_mode = RPC_MODE_DISABLED; - const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_name); - if (E) { - rpc_mode = E->get(); - } else if (p_node->get_script_instance()) { - rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_name); + StringName name = p_node->get_node_rpc_method(p_rpc_method_id); + RPCMode rpc_mode = p_node->get_node_rpc_mode_by_id(p_rpc_method_id); + if (name == StringName() && p_node->get_script_instance()) { + name = p_node->get_script_instance()->get_rpc_method(p_rpc_method_id); + rpc_mode = p_node->get_script_instance()->get_rpc_mode_by_id(p_rpc_method_id); } + ERR_FAIL_COND(name == StringName()); bool can_call = _can_call_mode(p_node, rpc_mode, p_from); - ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + "."); + ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + "."); int argc = p_packet[p_offset]; Vector<Variant> args; @@ -311,7 +361,7 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_ ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); int vlen; - Error err = decode_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen, allow_object_decoding || network_peer->is_object_decoding_allowed()); + Error err = _decode_and_decompress_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen); ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RPC argument."); argp.write[i] = &args[i]; @@ -320,29 +370,29 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_ Variant::CallError ce; - p_node->call(p_name, (const Variant **)argp.ptr(), argc, ce); + p_node->call(name, (const Variant **)argp.ptr(), argc, ce); if (ce.error != Variant::CallError::CALL_OK) { - String error = Variant::get_call_error_text(p_node, p_name, (const Variant **)argp.ptr(), argc, ce); + String error = Variant::get_call_error_text(p_node, name, (const Variant **)argp.ptr(), argc, ce); error = "RPC - " + error; - ERR_PRINTS(error); + ERR_PRINT(error); } } -void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { +void MultiplayerAPI::_process_rset(Node *p_node, const uint16_t p_rpc_property_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); // Check that remote can call the RSET on this node. - RPCMode rset_mode = RPC_MODE_DISABLED; - const Map<StringName, RPCMode>::Element *E = p_node->get_node_rset_mode(p_name); - if (E) { - rset_mode = E->get(); - } else if (p_node->get_script_instance()) { - rset_mode = p_node->get_script_instance()->get_rset_mode(p_name); + StringName name = p_node->get_node_rset_property(p_rpc_property_id); + RPCMode rset_mode = p_node->get_node_rset_mode_by_id(p_rpc_property_id); + if (name == StringName() && p_node->get_script_instance()) { + name = p_node->get_script_instance()->get_rset_property(p_rpc_property_id); + rset_mode = p_node->get_script_instance()->get_rset_mode_by_id(p_rpc_property_id); } + ERR_FAIL_COND(name == StringName()); bool can_call = _can_call_mode(p_node, rset_mode, p_from); - ERR_FAIL_COND_MSG(!can_call, "RSET '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + "."); + ERR_FAIL_COND_MSG(!can_call, "RSET '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + "."); #ifdef DEBUG_ENABLED if (profiling) { @@ -353,26 +403,33 @@ void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p #endif Variant value; - Error err = decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset, NULL, allow_object_decoding || network_peer->is_object_decoding_allowed()); + Error err = _decode_and_decompress_variant(value, &p_packet[p_offset], p_packet_len - p_offset, NULL); ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RSET value."); bool valid; - p_node->set(p_name, value, &valid); + p_node->set(name, value, &valid); if (!valid) { - String error = "Error setting remote property '" + String(p_name) + "', not found in object of type " + p_node->get_class() + "."; - ERR_PRINTS(error); + String error = "Error setting remote property '" + String(name) + "', not found in object of type " + p_node->get_class() + "."; + ERR_PRINT(error); } } void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(p_packet_len < 5, "Invalid packet received. Size too small."); - int id = decode_uint32(&p_packet[1]); + ERR_FAIL_COND_MSG(p_packet_len < 38, "Invalid packet received. Size too small."); + int ofs = 1; + + String methods_md5; + methods_md5.parse_utf8((const char *)(p_packet + ofs), 32); + ofs += 33; + + int id = decode_uint32(&p_packet[ofs]); + ofs += 4; String paths; - paths.parse_utf8((const char *)&p_packet[5], p_packet_len - 5); + paths.parse_utf8((const char *)(p_packet + ofs), p_packet_len - ofs); NodePath path = paths; @@ -380,9 +437,15 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, path_get_cache[p_from] = PathGetCache(); } + Node *node = root_node->get_node(path); + ERR_FAIL_COND(node == NULL); + const bool valid_rpc_checksum = node->get_rpc_md5() == methods_md5; + if (valid_rpc_checksum == false) { + ERR_PRINT("The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + path); + } + PathGetCache::NodeInfo ni; ni.path = path; - ni.instance = 0; path_get_cache[p_from].nodes[id] = ni; @@ -392,9 +455,10 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, Vector<uint8_t> packet; - packet.resize(1 + len); + packet.resize(1 + 1 + len); packet.write[0] = NETWORK_COMMAND_CONFIRM_PATH; - encode_cstring(pname.get_data(), &packet.write[1]); + packet.write[1] = valid_rpc_checksum; + encode_cstring(pname.get_data(), &packet.write[2]); network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); network_peer->set_target_peer(p_from); @@ -403,13 +467,19 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small."); + ERR_FAIL_COND_MSG(p_packet_len < 3, "Invalid packet received. Size too small."); + + const bool valid_rpc_checksum = p_packet[1]; String paths; - paths.parse_utf8((const char *)&p_packet[1], p_packet_len - 1); + paths.parse_utf8((const char *)&p_packet[2], p_packet_len - 2); NodePath path = paths; + if (valid_rpc_checksum == false) { + ERR_PRINT("The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + path); + } + PathSentCache *psc = path_send_cache.getptr(path); ERR_FAIL_COND_MSG(!psc, "Invalid packet received. Tries to confirm a path which was not found in cache."); @@ -418,7 +488,7 @@ void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, E->get() = true; } -bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int p_target) { +bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target) { bool has_all_peers = true; List<int> peers_to_add; // If one is missing, take note to add it. @@ -443,31 +513,192 @@ bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int } } - // Those that need to be added, send a message for this. + if (peers_to_add.size() > 0) { - for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) { + // Those that need to be added, send a message for this. // Encode function name. - CharString pname = String(p_path).utf8(); - int len = encode_cstring(pname.get_data(), NULL); + const CharString path = String(p_path).utf8(); + const int path_len = encode_cstring(path.get_data(), NULL); + + // Extract MD5 from rpc methods list. + const String methods_md5 = p_node->get_rpc_md5(); + const int methods_md5_len = 33; // 32 + 1 for the `0` that is added by the encoder. Vector<uint8_t> packet; + packet.resize(1 + 4 + path_len + methods_md5_len); + int ofs = 0; + + packet.write[ofs] = NETWORK_COMMAND_SIMPLIFY_PATH; + ofs += 1; + + ofs += encode_cstring(methods_md5.utf8().get_data(), &packet.write[ofs]); + + ofs += encode_uint32(psc->id, &packet.write[ofs]); + + ofs += encode_cstring(path.get_data(), &packet.write[ofs]); - packet.resize(1 + 4 + len); - packet.write[0] = NETWORK_COMMAND_SIMPLIFY_PATH; - encode_uint32(psc->id, &packet.write[1]); - encode_cstring(pname.get_data(), &packet.write[5]); + for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) { - network_peer->set_target_peer(E->get()); // To all of you. - network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); - network_peer->put_packet(packet.ptr(), packet.size()); + network_peer->set_target_peer(E->get()); // To all of you. + network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); + network_peer->put_packet(packet.ptr(), packet.size()); - psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed. + psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed. + } } return has_all_peers; } +// The variant is compressed and encoded; The first byte contains all the meta +// information and the format is: +// - The first LSB 5 bits are used for the variant type. +// - The next two bits are used to store the encoding mode. +// - The most significant is used to store the boolean value. +#define VARIANT_META_TYPE_MASK 0x1F +#define VARIANT_META_EMODE_MASK 0x60 +#define VARIANT_META_BOOL_MASK 0x80 +#define ENCODE_8 0 << 5 +#define ENCODE_16 1 << 5 +#define ENCODE_32 2 << 5 +#define ENCODE_64 3 << 5 +Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) { + + // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31 + CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK); + + uint8_t *buf = r_buffer; + r_len = 0; + uint8_t encode_mode = 0; + + switch (p_variant.get_type()) { + case Variant::BOOL: { + if (buf) { + // We still have 1 free bit in the meta, so let's use it. + buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0; + buf[0] |= encode_mode | p_variant.get_type(); + } + r_len += 1; + } break; + case Variant::INT: { + if (buf) { + // Reserve the first byte for the meta. + buf += 1; + } + r_len += 1; + int64_t val = p_variant; + if (val <= (int64_t)INT8_MAX && val >= (int64_t)INT8_MIN) { + // Use 8 bit + encode_mode = ENCODE_8; + if (buf) { + buf[0] = val; + } + r_len += 1; + } else if (val <= (int64_t)INT16_MAX && val >= (int64_t)INT16_MIN) { + // Use 16 bit + encode_mode = ENCODE_16; + if (buf) { + encode_uint16(val, buf); + } + r_len += 2; + } else if (val <= (int64_t)INT32_MAX && val >= (int64_t)INT32_MIN) { + // Use 32 bit + encode_mode = ENCODE_32; + if (buf) { + encode_uint32(val, buf); + } + r_len += 4; + } else { + // Use 64 bit + encode_mode = ENCODE_64; + if (buf) { + encode_uint64(val, buf); + } + r_len += 8; + } + // Store the meta + if (buf) { + buf -= 1; + buf[0] = encode_mode | p_variant.get_type(); + } + } break; + default: + // Any other case is not yet compressed. + Error err = encode_variant(p_variant, r_buffer, r_len, allow_object_decoding); + if (err != OK) + return err; + if (r_buffer) { + // The first byte is not used by the marshaling, so store the type + // so we know how to decompress and decode this variant. + r_buffer[0] = p_variant.get_type(); + } + } + + return OK; +} +Error MultiplayerAPI::_decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len) { + + const uint8_t *buf = p_buffer; + int len = p_len; + + ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA); + uint8_t type = buf[0] & VARIANT_META_TYPE_MASK; + uint8_t encode_mode = buf[0] & VARIANT_META_EMODE_MASK; + + ERR_FAIL_COND_V(type >= Variant::VARIANT_MAX, ERR_INVALID_DATA); + + switch (type) { + case Variant::BOOL: { + bool val = (buf[0] & VARIANT_META_BOOL_MASK) > 0; + r_variant = val; + if (r_len) + *r_len = 1; + } break; + case Variant::INT: { + buf += 1; + len -= 1; + if (r_len) + *r_len = 1; + if (encode_mode == ENCODE_8) { + // 8 bits. + ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA); + int8_t val = buf[0]; + r_variant = val; + if (r_len) + (*r_len) += 1; + } else if (encode_mode == ENCODE_16) { + // 16 bits. + ERR_FAIL_COND_V(len < 2, ERR_INVALID_DATA); + int16_t val = decode_uint16(buf); + r_variant = val; + if (r_len) + (*r_len) += 2; + } else if (encode_mode == ENCODE_32) { + // 32 bits. + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int32_t val = decode_uint32(buf); + r_variant = val; + if (r_len) + (*r_len) += 4; + } else { + // 64 bits. + ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); + int64_t val = decode_uint64(buf); + r_variant = val; + if (r_len) + (*r_len) += 8; + } + } break; + default: + Error err = decode_variant(r_variant, p_buffer, p_len, r_len, allow_object_decoding); + if (err != OK) + return err; + } + + return OK; +} + void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) { ERR_FAIL_COND_MSG(network_peer.is_null(), "Attempt to remote call/set when networking is not active in SceneTree."); @@ -496,6 +727,9 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p psc->id = last_send_cache_id++; } + // See if all peers have cached path (if so, call can be fast). + const bool has_all_peers = _send_confirm_path(p_from, from_path, psc, p_to); + // Create base packet, lots of hardcode because it must be tight. int ofs = 0; @@ -503,45 +737,125 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p #define MAKE_ROOM(m_amount) \ if (packet_cache.size() < m_amount) packet_cache.resize(m_amount); - // Encode type. + // Encode meta. + // The meta is composed by a single byte that contains (starting from the least segnificant bit): + // - `NetworkCommands` in the first three bits. + // - `NetworkNodeIdCompression` in the next 2 bits. + // - `NetworkNameIdCompression` in the next 1 bit. + // - So we still have the last two bits free! + uint8_t command_type = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL; + uint8_t node_id_compression = UINT8_MAX; + uint8_t name_id_compression = UINT8_MAX; + MAKE_ROOM(1); - packet_cache.write[0] = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL; + // The meta is composed along the way, so just set 0 for now. + packet_cache.write[0] = 0; ofs += 1; - // Encode ID. - MAKE_ROOM(ofs + 4); - encode_uint32(psc->id, &(packet_cache.write[ofs])); - ofs += 4; - - // Encode function name. - CharString name = String(p_name).utf8(); - int len = encode_cstring(name.get_data(), NULL); - MAKE_ROOM(ofs + len); - encode_cstring(name.get_data(), &(packet_cache.write[ofs])); - ofs += len; + // Encode Node ID. + if (has_all_peers) { + // Compress the node ID only if all the target peers already know it. + if (psc->id >= 0 && psc->id <= 255) { + // We can encode the id in 1 byte + node_id_compression = NETWORK_NODE_ID_COMPRESSION_8; + MAKE_ROOM(ofs + 1); + packet_cache.write[ofs] = static_cast<uint8_t>(psc->id); + ofs += 1; + } else if (psc->id >= 0 && psc->id <= 65535) { + // We can encode the id in 2 bytes + node_id_compression = NETWORK_NODE_ID_COMPRESSION_16; + MAKE_ROOM(ofs + 2); + encode_uint16(static_cast<uint16_t>(psc->id), &(packet_cache.write[ofs])); + ofs += 2; + } else { + // Too big, let's use 4 bytes. + node_id_compression = NETWORK_NODE_ID_COMPRESSION_32; + MAKE_ROOM(ofs + 4); + encode_uint32(psc->id, &(packet_cache.write[ofs])); + ofs += 4; + } + } else { + // The targets doesn't know the node yet, so we need to use 32 bits int. + node_id_compression = NETWORK_NODE_ID_COMPRESSION_32; + MAKE_ROOM(ofs + 4); + encode_uint32(psc->id, &(packet_cache.write[ofs])); + ofs += 4; + } if (p_set) { + + // Take the rpc property ID + uint16_t property_id = p_from->get_node_rset_property_id(p_name); + if (property_id == UINT16_MAX && p_from->get_script_instance()) { + property_id = p_from->get_script_instance()->get_rset_property_id(p_name); + } + ERR_FAIL_COND_MSG(property_id == UINT16_MAX, "Unable to take the `property_id` for the property:" + p_name + ". this can happen only if this property is not marked as `remote`."); + + if (property_id <= UINT8_MAX) { + // The ID fits in 1 byte + name_id_compression = NETWORK_NAME_ID_COMPRESSION_8; + MAKE_ROOM(ofs + 1); + packet_cache.write[ofs] = static_cast<uint8_t>(property_id); + ofs += 1; + } else { + // The ID is larger, let's use 2 bytes + name_id_compression = NETWORK_NAME_ID_COMPRESSION_16; + MAKE_ROOM(ofs + 2); + encode_uint16(property_id, &(packet_cache.write[ofs])); + ofs += 2; + } + // Set argument. - Error err = encode_variant(*p_arg[0], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + int len(0); + Error err = _encode_and_compress_variant(*p_arg[0], NULL, len); ERR_FAIL_COND_MSG(err != OK, "Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!"); MAKE_ROOM(ofs + len); - encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + _encode_and_compress_variant(*p_arg[0], &(packet_cache.write[ofs]), len); ofs += len; } else { + // Take the rpc method ID + uint16_t method_id = p_from->get_node_rpc_method_id(p_name); + if (method_id == UINT16_MAX && p_from->get_script_instance()) { + method_id = p_from->get_script_instance()->get_rpc_method_id(p_name); + } + ERR_FAIL_COND_MSG(method_id == UINT16_MAX, "Unable to take the `method_id` for the function:" + p_name + ". this can happen only if this method is not marked as `remote`."); + + if (method_id <= UINT8_MAX) { + // The ID fits in 1 byte + name_id_compression = NETWORK_NAME_ID_COMPRESSION_8; + MAKE_ROOM(ofs + 1); + packet_cache.write[ofs] = static_cast<uint8_t>(method_id); + ofs += 1; + } else { + // The ID is larger, let's use 2 bytes + name_id_compression = NETWORK_NAME_ID_COMPRESSION_16; + MAKE_ROOM(ofs + 2); + encode_uint16(method_id, &(packet_cache.write[ofs])); + ofs += 2; + } + // Call arguments. MAKE_ROOM(ofs + 1); packet_cache.write[ofs] = p_argcount; ofs += 1; for (int i = 0; i < p_argcount; i++) { - Error err = encode_variant(*p_arg[i], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + int len(0); + Error err = _encode_and_compress_variant(*p_arg[i], NULL, len); ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!"); MAKE_ROOM(ofs + len); - encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed()); + _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len); ofs += len; } } + ERR_FAIL_COND(command_type > 7); + ERR_FAIL_COND(node_id_compression > 3); + ERR_FAIL_COND(name_id_compression > 1); + + // We can now set the meta + packet_cache.write[0] = command_type + (node_id_compression << 3) + (name_id_compression << 5); + #ifdef DEBUG_ENABLED if (profiling) { bandwidth_outgoing_data.write[bandwidth_outgoing_pointer].timestamp = OS::get_singleton()->get_ticks_msec(); @@ -550,9 +864,6 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p } #endif - // See if all peers have cached path (is so, call can be fast). - bool has_all_peers = _send_confirm_path(from_path, psc, p_to); - // Take chance and set transfer mode, since all send methods will use it. network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); @@ -562,6 +873,9 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p network_peer->set_target_peer(p_to); // To all of you. network_peer->put_packet(packet_cache.ptr(), ofs); // A message with love. } else { + // Unreachable because the node ID is never compressed if the peers doesn't know it. + CRASH_COND(node_id_compression != NETWORK_NODE_ID_COMPRESSION_32); + // Not all verified path, so send one by one. // Append path at the end, since we will need it for some packets. @@ -647,16 +961,14 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) { // Check that send mode can use local call. - const Map<StringName, RPCMode>::Element *E = p_node->get_node_rpc_mode(p_method); - if (E) { - call_local_native = _should_call_local(E->get(), is_master, skip_rpc); - } + RPCMode rpc_mode = p_node->get_node_rpc_mode(p_method); + call_local_native = _should_call_local(rpc_mode, is_master, skip_rpc); if (call_local_native) { // Done below. } else if (p_node->get_script_instance()) { // Attempt with script. - RPCMode rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method); + rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method); call_local_script = _should_call_local(rpc_mode, is_master, skip_rpc); } } @@ -683,7 +995,7 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const if (ce.error != Variant::CallError::CALL_OK) { String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce); error = "rpc() aborted in local call: - " + error + "."; - ERR_PRINTS(error); + ERR_PRINT(error); return; } } @@ -698,7 +1010,7 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const if (ce.error != Variant::CallError::CALL_OK) { String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce); error = "rpc() aborted in script local call: - " + error + "."; - ERR_PRINTS(error); + ERR_PRINT(error); return; } } @@ -719,11 +1031,8 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) { // Check that send mode can use local call. - const Map<StringName, RPCMode>::Element *E = p_node->get_node_rset_mode(p_property); - if (E) { - - set_local = _should_call_local(E->get(), is_master, skip_rset); - } + RPCMode rpc_mode = p_node->get_node_rset_mode(p_property); + set_local = _should_call_local(rpc_mode, is_master, skip_rset); if (set_local) { bool valid; @@ -735,12 +1044,12 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const if (!valid) { String error = "rset() aborted in local set, property not found: - " + String(p_property) + "."; - ERR_PRINTS(error); + ERR_PRINT(error); return; } } else if (p_node->get_script_instance()) { // Attempt with script. - RPCMode rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property); + rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property); set_local = _should_call_local(rpc_mode, is_master, skip_rset); @@ -753,7 +1062,7 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const if (!valid) { String error = "rset() aborted in local script set, property not found: - " + String(p_property) + "."; - ERR_PRINTS(error); + ERR_PRINT(error); return; } } @@ -778,14 +1087,14 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const _send_rpc(p_node, p_peer_id, p_unreliable, true, p_property, &vptr, 1); } -Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) { +Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) { ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet."); ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no network peer is active."); ERR_FAIL_COND_V_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a network peer which is not connected."); MAKE_ROOM(p_data.size() + 1); - PoolVector<uint8_t>::Read r = p_data.read(); + const uint8_t *r = p_data.ptr(); packet_cache.write[0] = NETWORK_COMMAND_RAW; memcpy(&packet_cache.write[1], &r[0], p_data.size()); @@ -799,11 +1108,11 @@ void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_pac ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small."); - PoolVector<uint8_t> out; + Vector<uint8_t> out; int len = p_packet_len - 1; out.resize(len); { - PoolVector<uint8_t>::Write w = out.write(); + uint8_t *w = out.ptrw(); memcpy(&w[0], &p_packet[1], len); } emit_signal("network_peer_packet", p_from, out); @@ -975,7 +1284,7 @@ void MultiplayerAPI::_bind_methods() { ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id"))); - ADD_SIGNAL(MethodInfo("network_peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::POOL_BYTE_ARRAY, "packet"))); + ADD_SIGNAL(MethodInfo("network_peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "packet"))); ADD_SIGNAL(MethodInfo("connected_to_server")); ADD_SIGNAL(MethodInfo("connection_failed")); ADD_SIGNAL(MethodInfo("server_disconnected")); @@ -984,9 +1293,7 @@ void MultiplayerAPI::_bind_methods() { BIND_ENUM_CONSTANT(RPC_MODE_REMOTE); BIND_ENUM_CONSTANT(RPC_MODE_MASTER); BIND_ENUM_CONSTANT(RPC_MODE_PUPPET); - BIND_ENUM_CONSTANT(RPC_MODE_SLAVE); // Deprecated. BIND_ENUM_CONSTANT(RPC_MODE_REMOTESYNC); - BIND_ENUM_CONSTANT(RPC_MODE_SYNC); // Deprecated. BIND_ENUM_CONSTANT(RPC_MODE_MASTERSYNC); BIND_ENUM_CONSTANT(RPC_MODE_PUPPETSYNC); } diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h index c9f127b6b2..a706a0e450 100644 --- a/core/io/multiplayer_api.h +++ b/core/io/multiplayer_api.h @@ -98,32 +98,44 @@ protected: void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len); void _process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len); void _process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len); - Node *_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len); - void _process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); - void _process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); + Node *_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len); + void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); + void _process_rset(Node *p_node, const uint16_t p_rpc_property_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len); void _send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount); - bool _send_confirm_path(NodePath p_path, PathSentCache *psc, int p_target); + bool _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target); + + Error _encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len); + Error _decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len); public: enum NetworkCommands { - NETWORK_COMMAND_REMOTE_CALL, + NETWORK_COMMAND_REMOTE_CALL = 0, NETWORK_COMMAND_REMOTE_SET, NETWORK_COMMAND_SIMPLIFY_PATH, NETWORK_COMMAND_CONFIRM_PATH, NETWORK_COMMAND_RAW, }; + enum NetworkNodeIdCompression { + NETWORK_NODE_ID_COMPRESSION_8 = 0, + NETWORK_NODE_ID_COMPRESSION_16, + NETWORK_NODE_ID_COMPRESSION_32, + }; + + enum NetworkNameIdCompression { + NETWORK_NAME_ID_COMPRESSION_8 = 0, + NETWORK_NAME_ID_COMPRESSION_16, + }; + enum RPCMode { RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default) RPC_MODE_REMOTE, // Using rpc() on it will call method / set property in all remote peers RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets - RPC_MODE_SLAVE = RPC_MODE_PUPPET, // Deprecated, same as puppet RPC_MODE_REMOTESYNC, // Using rpc() on it will call method / set property in all remote peers and locally - RPC_MODE_SYNC = RPC_MODE_REMOTESYNC, // Deprecated. Same as RPC_MODE_REMOTESYNC RPC_MODE_MASTERSYNC, // Using rpc() on it will call method / set property in the master peer and locally RPC_MODE_PUPPETSYNC, // Using rpc() on it will call method / set property in all puppets peers and locally }; @@ -133,7 +145,7 @@ public: void set_root_node(Node *p_node); void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer); Ref<NetworkedMultiplayerPeer> get_network_peer() const; - Error send_bytes(PoolVector<uint8_t> p_data, int p_to = NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST, NetworkedMultiplayerPeer::TransferMode p_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); + Error send_bytes(Vector<uint8_t> p_data, int p_to = NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST, NetworkedMultiplayerPeer::TransferMode p_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); // Called by Node.rpc void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount); diff --git a/core/io/net_socket.h b/core/io/net_socket.h index 710df2dd78..376fd87a27 100644 --- a/core/io/net_socket.h +++ b/core/io/net_socket.h @@ -61,7 +61,7 @@ public: virtual Error connect_to_host(IP_Address p_addr, uint16_t p_port) = 0; virtual Error poll(PollType p_type, int timeout) const = 0; virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0; - virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) = 0; + virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port, bool p_peek = false) = 0; virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0; virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0; virtual Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port) = 0; diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index 9e53d773ba..2f5c493c2c 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -37,20 +37,9 @@ PacketPeer::PacketPeer() : last_get_error(OK), - allow_object_decoding(false), encode_buffer_max_size(8 * 1024 * 1024) { } -void PacketPeer::set_allow_object_decoding(bool p_enable) { - - allow_object_decoding = p_enable; -} - -bool PacketPeer::is_object_decoding_allowed() const { - - return allow_object_decoding; -} - void PacketPeer::set_encode_buffer_max_size(int p_max_size) { ERR_FAIL_COND_MSG(p_max_size < 1024, "Max encode buffer must be at least 1024 bytes"); @@ -64,7 +53,7 @@ int PacketPeer::get_encode_buffer_max_size() const { return encode_buffer_max_size; } -Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) { +Error PacketPeer::get_packet_buffer(Vector<uint8_t> &r_buffer) { const uint8_t *buffer; int buffer_size; @@ -76,20 +65,20 @@ Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) { if (buffer_size == 0) return OK; - PoolVector<uint8_t>::Write w = r_buffer.write(); + uint8_t *w = r_buffer.ptrw(); for (int i = 0; i < buffer_size; i++) w[i] = buffer[i]; return OK; } -Error PacketPeer::put_packet_buffer(const PoolVector<uint8_t> &p_buffer) { +Error PacketPeer::put_packet_buffer(const Vector<uint8_t> &p_buffer) { int len = p_buffer.size(); if (len == 0) return OK; - PoolVector<uint8_t>::Read r = p_buffer.read(); + const uint8_t *r = p_buffer.ptr(); return put_packet(&r[0], len); } @@ -101,13 +90,13 @@ Error PacketPeer::get_var(Variant &r_variant, bool p_allow_objects) { if (err) return err; - return decode_variant(r_variant, buffer, buffer_size, NULL, p_allow_objects || allow_object_decoding); + return decode_variant(r_variant, buffer, buffer_size, NULL, p_allow_objects); } Error PacketPeer::put_var(const Variant &p_packet, bool p_full_objects) { int len; - Error err = encode_variant(p_packet, NULL, len, p_full_objects || allow_object_decoding); // compute len first + Error err = encode_variant(p_packet, NULL, len, p_full_objects); // compute len first if (err) return err; @@ -121,11 +110,11 @@ Error PacketPeer::put_var(const Variant &p_packet, bool p_full_objects) { encode_buffer.resize(next_power_of_2(len)); } - PoolVector<uint8_t>::Write w = encode_buffer.write(); - err = encode_variant(p_packet, w.ptr(), len, p_full_objects || allow_object_decoding); + uint8_t *w = encode_buffer.ptrw(); + err = encode_variant(p_packet, w, len, p_full_objects); ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to encode Variant."); - return put_packet(w.ptr(), len); + return put_packet(w, len); } Variant PacketPeer::_bnd_get_var(bool p_allow_objects) { @@ -136,12 +125,12 @@ Variant PacketPeer::_bnd_get_var(bool p_allow_objects) { return var; } -Error PacketPeer::_put_packet(const PoolVector<uint8_t> &p_buffer) { +Error PacketPeer::_put_packet(const Vector<uint8_t> &p_buffer) { return put_packet_buffer(p_buffer); } -PoolVector<uint8_t> PacketPeer::_get_packet() { +Vector<uint8_t> PacketPeer::_get_packet() { - PoolVector<uint8_t> raw; + Vector<uint8_t> raw; last_get_error = get_packet_buffer(raw); return raw; } @@ -160,13 +149,10 @@ void PacketPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_packet_error"), &PacketPeer::_get_packet_error); ClassDB::bind_method(D_METHOD("get_available_packet_count"), &PacketPeer::get_available_packet_count); - ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &PacketPeer::set_allow_object_decoding); - ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &PacketPeer::is_object_decoding_allowed); ClassDB::bind_method(D_METHOD("get_encode_buffer_max_size"), &PacketPeer::get_encode_buffer_max_size); ClassDB::bind_method(D_METHOD("set_encode_buffer_max_size", "max_size"), &PacketPeer::set_encode_buffer_max_size); ADD_PROPERTY(PropertyInfo(Variant::INT, "encode_buffer_max_size"), "set_encode_buffer_max_size", "get_encode_buffer_max_size"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed"); }; /***************/ diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index 2b13f2e952..62144259cc 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -43,16 +43,14 @@ class PacketPeer : public Reference { static void _bind_methods(); - Error _put_packet(const PoolVector<uint8_t> &p_buffer); - PoolVector<uint8_t> _get_packet(); + Error _put_packet(const Vector<uint8_t> &p_buffer); + Vector<uint8_t> _get_packet(); Error _get_packet_error() const; mutable Error last_get_error; - bool allow_object_decoding; - int encode_buffer_max_size; - PoolVector<uint8_t> encode_buffer; + Vector<uint8_t> encode_buffer; public: virtual int get_available_packet_count() const = 0; @@ -63,15 +61,12 @@ public: /* helpers / binders */ - virtual Error get_packet_buffer(PoolVector<uint8_t> &r_buffer); - virtual Error put_packet_buffer(const PoolVector<uint8_t> &p_buffer); + virtual Error get_packet_buffer(Vector<uint8_t> &r_buffer); + virtual Error put_packet_buffer(const Vector<uint8_t> &p_buffer); virtual Error get_var(Variant &r_variant, bool p_allow_objects = false); virtual Error put_var(const Variant &p_packet, bool p_full_objects = false); - void set_allow_object_decoding(bool p_enable); - bool is_object_decoding_allowed() const; - void set_encode_buffer_max_size(int p_max_size); int get_encode_buffer_max_size() const; diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp new file mode 100644 index 0000000000..64007c7e3b --- /dev/null +++ b/core/io/packet_peer_dtls.cpp @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* packet_peer_dtls.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "packet_peer_dtls.h" +#include "core/os/file_access.h" +#include "core/project_settings.h" + +PacketPeerDTLS *(*PacketPeerDTLS::_create)() = NULL; +bool PacketPeerDTLS::available = false; + +PacketPeerDTLS *PacketPeerDTLS::create() { + + return _create(); +} + +bool PacketPeerDTLS::is_available() { + return available; +} + +void PacketPeerDTLS::_bind_methods() { + + ClassDB::bind_method(D_METHOD("poll"), &PacketPeerDTLS::poll); + ClassDB::bind_method(D_METHOD("connect_to_peer", "packet_peer", "validate_certs", "for_hostname", "valid_certificate"), &PacketPeerDTLS::connect_to_peer, DEFVAL(true), DEFVAL(String()), DEFVAL(Ref<X509Certificate>())); + ClassDB::bind_method(D_METHOD("get_status"), &PacketPeerDTLS::get_status); + ClassDB::bind_method(D_METHOD("disconnect_from_peer"), &PacketPeerDTLS::disconnect_from_peer); + + BIND_ENUM_CONSTANT(STATUS_DISCONNECTED); + BIND_ENUM_CONSTANT(STATUS_HANDSHAKING); + BIND_ENUM_CONSTANT(STATUS_CONNECTED); + BIND_ENUM_CONSTANT(STATUS_ERROR); + BIND_ENUM_CONSTANT(STATUS_ERROR_HOSTNAME_MISMATCH); +} + +PacketPeerDTLS::PacketPeerDTLS() { +} diff --git a/core/io/packet_peer_dtls.h b/core/io/packet_peer_dtls.h new file mode 100644 index 0000000000..b7cabb6ae0 --- /dev/null +++ b/core/io/packet_peer_dtls.h @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* packet_peer_dtls.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 PACKET_PEER_DTLS_H +#define PACKET_PEER_DTLS_H + +#include "core/crypto/crypto.h" +#include "core/io/packet_peer_udp.h" + +class PacketPeerDTLS : public PacketPeer { + GDCLASS(PacketPeerDTLS, PacketPeer); + +protected: + static PacketPeerDTLS *(*_create)(); + static void _bind_methods(); + + static bool available; + +public: + enum Status { + STATUS_DISCONNECTED, + STATUS_HANDSHAKING, + STATUS_CONNECTED, + STATUS_ERROR, + STATUS_ERROR_HOSTNAME_MISMATCH + }; + + virtual void poll() = 0; + virtual Error connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_validate_certs = true, const String &p_for_hostname = String(), Ref<X509Certificate> p_ca_certs = Ref<X509Certificate>()) = 0; + virtual void disconnect_from_peer() = 0; + virtual Status get_status() const = 0; + + static PacketPeerDTLS *create(); + static bool is_available(); + + PacketPeerDTLS(); +}; + +VARIANT_ENUM_CAST(PacketPeerDTLS::Status); + +#endif // PACKET_PEER_DTLS_H diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index 5c98c4fcab..f800ffc3db 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -133,7 +133,11 @@ Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) { } do { - err = _sock->sendto(p_buffer, p_buffer_size, sent, peer_addr, peer_port); + if (connected) { + err = _sock->send(p_buffer, p_buffer_size, sent); + } else { + err = _sock->sendto(p_buffer, p_buffer_size, sent, peer_addr, peer_port); + } if (err != OK) { if (err != ERR_BUSY) return FAILED; @@ -184,12 +188,69 @@ Error PacketPeerUDP::listen(int p_port, const IP_Address &p_bind_address, int p_ return OK; } +Error PacketPeerUDP::connect_socket(Ref<NetSocket> p_sock) { + Error err; + int read = 0; + uint16_t r_port; + IP_Address r_ip; + + err = p_sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, r_ip, r_port, true); + ERR_FAIL_COND_V(err != OK, err); + err = p_sock->connect_to_host(r_ip, r_port); + ERR_FAIL_COND_V(err != OK, err); + _sock = p_sock; + peer_addr = r_ip; + peer_port = r_port; + packet_ip = peer_addr; + packet_port = peer_port; + connected = true; + return OK; +} + +Error PacketPeerUDP::connect_to_host(const IP_Address &p_host, int p_port) { + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER); + + Error err; + + if (!_sock->is_open()) { + IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + err = _sock->open(NetSocket::TYPE_UDP, ip_type); + ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN); + _sock->set_blocking_enabled(false); + } + + err = _sock->connect_to_host(p_host, p_port); + + // I see no reason why we should get ERR_BUSY (wouldblock/eagain) here. + // This is UDP, so connect is only used to tell the OS to which socket + // it shuold deliver packets when multiple are bound on the same address/port. + if (err != OK) { + close(); + ERR_FAIL_V_MSG(FAILED, "Unable to connect"); + } + + connected = true; + + peer_addr = p_host; + peer_port = p_port; + + // Flush any packet we might still have in queue. + rb.clear(); + return OK; +} + +bool PacketPeerUDP::is_connected_to_host() const { + return connected; +} + void PacketPeerUDP::close() { if (_sock.is_valid()) _sock->close(); rb.resize(16); queue_count = 0; + connected = false; } Error PacketPeerUDP::wait() { @@ -212,7 +273,13 @@ Error PacketPeerUDP::_poll() { uint16_t port; while (true) { - err = _sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, ip, port); + if (connected) { + err = _sock->recv(recv_buffer, sizeof(recv_buffer), read); + ip = peer_addr; + port = peer_port; + } else { + err = _sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, ip, port); + } if (err != OK) { if (err == ERR_BUSY) @@ -222,7 +289,7 @@ Error PacketPeerUDP::_poll() { if (rb.space_left() < read + 24) { #ifdef TOOLS_ENABLED - WARN_PRINTS("Buffer full, dropping packets!"); + WARN_PRINT("Buffer full, dropping packets!"); #endif continue; } @@ -254,6 +321,7 @@ int PacketPeerUDP::get_packet_port() const { void PacketPeerUDP::set_dest_address(const IP_Address &p_address, int p_port) { + ERR_FAIL_COND_MSG(connected, "Destination address cannot be set for connected sockets"); peer_addr = p_address; peer_port = p_port; } @@ -264,6 +332,8 @@ void PacketPeerUDP::_bind_methods() { ClassDB::bind_method(D_METHOD("close"), &PacketPeerUDP::close); ClassDB::bind_method(D_METHOD("wait"), &PacketPeerUDP::wait); ClassDB::bind_method(D_METHOD("is_listening"), &PacketPeerUDP::is_listening); + ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &PacketPeerUDP::connect_to_host); + ClassDB::bind_method(D_METHOD("is_connected_to_host"), &PacketPeerUDP::is_connected_to_host); ClassDB::bind_method(D_METHOD("get_packet_ip"), &PacketPeerUDP::_get_packet_ip); ClassDB::bind_method(D_METHOD("get_packet_port"), &PacketPeerUDP::get_packet_port); ClassDB::bind_method(D_METHOD("set_dest_address", "host", "port"), &PacketPeerUDP::_set_dest_address); @@ -276,6 +346,7 @@ PacketPeerUDP::PacketPeerUDP() : packet_port(0), queue_count(0), peer_port(0), + connected(false), blocking(true), broadcast(false), _sock(Ref<NetSocket>(NetSocket::create())) { diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 15b4d00c37..b5a9fc9ec3 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -52,6 +52,7 @@ protected: IP_Address peer_addr; int peer_port; + bool connected; bool blocking; bool broadcast; Ref<NetSocket> _sock; @@ -70,6 +71,11 @@ public: void close(); Error wait(); bool is_listening() const; + + Error connect_socket(Ref<NetSocket> p_sock); // Used by UDPServer + Error connect_to_host(const IP_Address &p_host, int p_port); + bool is_connected_to_host() const; + IP_Address get_packet_address() const; int get_packet_port() const; void set_dest_address(const IP_Address &p_address, int p_port); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 272d5c1116..d4c1fd2e9b 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -73,13 +73,6 @@ enum { VARIANT_VECTOR2_ARRAY = 37, VARIANT_INT64 = 40, VARIANT_DOUBLE = 41, -#ifndef DISABLE_DEPRECATED - VARIANT_IMAGE = 21, // - no longer variant type - IMAGE_ENCODING_EMPTY = 0, - IMAGE_ENCODING_RAW = 1, - IMAGE_ENCODING_LOSSLESS = 2, - IMAGE_ENCODING_LOSSY = 3, -#endif OBJECT_EMPTY = 0, OBJECT_EXTERNAL_RESOURCE = 1, OBJECT_INTERNAL_RESOURCE = 2, @@ -405,12 +398,12 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t len = f->get_32(); - PoolVector<uint8_t> array; + Vector<uint8_t> array; array.resize(len); - PoolVector<uint8_t>::Write w = array.write(); - f->get_buffer(w.ptr(), len); + uint8_t *w = array.ptrw(); + f->get_buffer(w, len); _advance_padding(len); - w.release(); + r_v = array; } break; @@ -418,10 +411,10 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t len = f->get_32(); - PoolVector<int> array; + Vector<int> array; array.resize(len); - PoolVector<int>::Write w = array.write(); - f->get_buffer((uint8_t *)w.ptr(), len * 4); + int *w = array.ptrw(); + f->get_buffer((uint8_t *)w, len * 4); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -432,17 +425,17 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } #endif - w.release(); + r_v = array; } break; case VARIANT_REAL_ARRAY: { uint32_t len = f->get_32(); - PoolVector<real_t> array; + Vector<real_t> array; array.resize(len); - PoolVector<real_t>::Write w = array.write(); - f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t)); + real_t *w = array.ptrw(); + f->get_buffer((uint8_t *)w, len * sizeof(real_t)); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -454,18 +447,17 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { #endif - w.release(); r_v = array; } break; case VARIANT_STRING_ARRAY: { uint32_t len = f->get_32(); - PoolVector<String> array; + Vector<String> array; array.resize(len); - PoolVector<String>::Write w = array.write(); + String *w = array.ptrw(); for (uint32_t i = 0; i < len; i++) w[i] = get_unicode_string(); - w.release(); + r_v = array; } break; @@ -473,11 +465,11 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t len = f->get_32(); - PoolVector<Vector2> array; + Vector<Vector2> array; array.resize(len); - PoolVector<Vector2>::Write w = array.write(); + Vector2 *w = array.ptrw(); if (sizeof(Vector2) == 8) { - f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t) * 2); + f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 2); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -492,7 +484,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } else { ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector2 size is NOT 8!"); } - w.release(); + r_v = array; } break; @@ -500,11 +492,11 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t len = f->get_32(); - PoolVector<Vector3> array; + Vector<Vector3> array; array.resize(len); - PoolVector<Vector3>::Write w = array.write(); + Vector3 *w = array.ptrw(); if (sizeof(Vector3) == 12) { - f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t) * 3); + f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 3); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -519,7 +511,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } else { ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector3 size is NOT 12!"); } - w.release(); + r_v = array; } break; @@ -527,11 +519,11 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t len = f->get_32(); - PoolVector<Color> array; + Vector<Color> array; array.resize(len); - PoolVector<Color>::Write w = array.write(); + Color *w = array.ptrw(); if (sizeof(Color) == 16) { - f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t) * 4); + f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 4); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -546,72 +538,9 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } else { ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Color size is NOT 16!"); } - w.release(); - r_v = array; - } break; -#ifndef DISABLE_DEPRECATED - case VARIANT_IMAGE: { - uint32_t encoding = f->get_32(); - if (encoding == IMAGE_ENCODING_EMPTY) { - r_v = Ref<Image>(); - break; - } else if (encoding == IMAGE_ENCODING_RAW) { - uint32_t width = f->get_32(); - uint32_t height = f->get_32(); - uint32_t mipmaps = f->get_32(); - uint32_t format = f->get_32(); - const uint32_t format_version_shift = 24; - const uint32_t format_version_mask = format_version_shift - 1; - - uint32_t format_version = format >> format_version_shift; - - const uint32_t current_version = 0; - if (format_version > current_version) { - - ERR_PRINT("Format version for encoded binary image is too new."); - return ERR_PARSE_ERROR; - } - - Image::Format fmt = Image::Format(format & format_version_mask); //if format changes, we can add a compatibility bit on top - - uint32_t datalen = f->get_32(); - - PoolVector<uint8_t> imgdata; - imgdata.resize(datalen); - PoolVector<uint8_t>::Write w = imgdata.write(); - f->get_buffer(w.ptr(), datalen); - _advance_padding(datalen); - w.release(); - - Ref<Image> image; - image.instance(); - image->create(width, height, mipmaps, fmt, imgdata); - r_v = image; - - } else { - //compressed - PoolVector<uint8_t> data; - data.resize(f->get_32()); - PoolVector<uint8_t>::Write w = data.write(); - f->get_buffer(w.ptr(), data.size()); - w.release(); - - Ref<Image> image; - - if (encoding == IMAGE_ENCODING_LOSSY && Image::lossy_unpacker) { - - image = Image::lossy_unpacker(data); - } else if (encoding == IMAGE_ENCODING_LOSSLESS && Image::lossless_unpacker) { - - image = Image::lossless_unpacker(data); - } - _advance_padding(data.size()); - - r_v = image; - } + r_v = array; } break; -#endif default: { ERR_FAIL_V(ERR_FILE_CORRUPT); } break; @@ -836,15 +765,20 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) { uint8_t header[4]; f->get_buffer(header, 4); if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') { - //compressed + // Compressed. FileAccessCompressed *fac = memnew(FileAccessCompressed); - fac->open_after_magic(f); + error = fac->open_after_magic(f); + if (error != OK) { + memdelete(fac); + f->close(); + ERR_FAIL_MSG("Failed to open binary resource file: " + local_path + "."); + } f = fac; } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') { - //not normal - + // Not normal. error = ERR_FILE_UNRECOGNIZED; + f->close(); ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + "."); } @@ -919,6 +853,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) { if (f->eof_reached()) { error = ERR_FILE_CORRUPT; + f->close(); ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + "."); } } @@ -931,14 +866,20 @@ String ResourceInteractiveLoaderBinary::recognize(FileAccess *p_f) { uint8_t header[4]; f->get_buffer(header, 4); if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') { - //compressed + // Compressed. FileAccessCompressed *fac = memnew(FileAccessCompressed); - fac->open_after_magic(f); + error = fac->open_after_magic(f); + if (error != OK) { + memdelete(fac); + f->close(); + return ""; + } f = fac; } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') { - //not normal + // Not normal. error = ERR_FILE_UNRECOGNIZED; + f->close(); return ""; } @@ -1055,14 +996,19 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons uint8_t header[4]; f->get_buffer(header, 4); if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') { - //compressed + // Compressed. FileAccessCompressed *fac = memnew(FileAccessCompressed); - fac->open_after_magic(f); + Error err = fac->open_after_magic(f); + if (err != OK) { + memdelete(fac); + memdelete(f); + ERR_FAIL_V_MSG(err, "Cannot open file '" + p_path + "'."); + } f = fac; FileAccessCompressed *facw = memnew(FileAccessCompressed); facw->configure("RSCC"); - Error err = facw->_open(p_path + ".depren", FileAccess::WRITE); + err = facw->_open(p_path + ".depren", FileAccess::WRITE); if (err) { memdelete(fac); memdelete(facw); @@ -1072,9 +1018,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons fw = facw; } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') { - //not normal - - //error=ERR_FILE_UNRECOGNIZED; + // Not normal. memdelete(f); ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file '" + local_path + "'."); } else { @@ -1113,7 +1057,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons memdelete(da); //use the old approach - WARN_PRINTS("This file is old, so it can't refactor dependencies, opening and resaving '" + p_path + "'."); + WARN_PRINT("This file is old, so it can't refactor dependencies, opening and resaving '" + p_path + "'."); Error err; f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -1255,7 +1199,7 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const ria->res_path = ria->local_path; //ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); String r = ria->recognize(f); - return r; + return ClassDB::get_compatibility_remapped_class(r); } /////////////////////////////////////////////////////////// @@ -1528,59 +1472,59 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } } break; - case Variant::POOL_BYTE_ARRAY: { + case Variant::PACKED_BYTE_ARRAY: { f->store_32(VARIANT_RAW_ARRAY); - PoolVector<uint8_t> arr = p_property; + Vector<uint8_t> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<uint8_t>::Read r = arr.read(); - f->store_buffer(r.ptr(), len); + const uint8_t *r = arr.ptr(); + f->store_buffer(r, len); _pad_buffer(f, len); } break; - case Variant::POOL_INT_ARRAY: { + case Variant::PACKED_INT_ARRAY: { f->store_32(VARIANT_INT_ARRAY); - PoolVector<int> arr = p_property; + Vector<int> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<int>::Read r = arr.read(); + const int *r = arr.ptr(); for (int i = 0; i < len; i++) f->store_32(r[i]); } break; - case Variant::POOL_REAL_ARRAY: { + case Variant::PACKED_REAL_ARRAY: { f->store_32(VARIANT_REAL_ARRAY); - PoolVector<real_t> arr = p_property; + Vector<real_t> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<real_t>::Read r = arr.read(); + const real_t *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i]); } } break; - case Variant::POOL_STRING_ARRAY: { + case Variant::PACKED_STRING_ARRAY: { f->store_32(VARIANT_STRING_ARRAY); - PoolVector<String> arr = p_property; + Vector<String> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<String>::Read r = arr.read(); + const String *r = arr.ptr(); for (int i = 0; i < len; i++) { save_unicode_string(f, r[i]); } } break; - case Variant::POOL_VECTOR3_ARRAY: { + case Variant::PACKED_VECTOR3_ARRAY: { f->store_32(VARIANT_VECTOR3_ARRAY); - PoolVector<Vector3> arr = p_property; + Vector<Vector3> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<Vector3>::Read r = arr.read(); + const Vector3 *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i].x); f->store_real(r[i].y); @@ -1588,26 +1532,26 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } } break; - case Variant::POOL_VECTOR2_ARRAY: { + case Variant::PACKED_VECTOR2_ARRAY: { f->store_32(VARIANT_VECTOR2_ARRAY); - PoolVector<Vector2> arr = p_property; + Vector<Vector2> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<Vector2>::Read r = arr.read(); + const Vector2 *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i].x); f->store_real(r[i].y); } } break; - case Variant::POOL_COLOR_ARRAY: { + case Variant::PACKED_COLOR_ARRAY: { f->store_32(VARIANT_COLOR_ARRAY); - PoolVector<Color> arr = p_property; + Vector<Color> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<Color>::Read r = arr.read(); + const Color *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i].r); f->store_real(r[i].g); @@ -1628,14 +1572,14 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant switch (p_variant.get_type()) { case Variant::OBJECT: { - RES res = p_variant.operator RefPtr(); + RES res = p_variant; if (res.is_null() || external_resources.has(res)) return; if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) { if (res->get_path() == path) { - ERR_PRINTS("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded."); + ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded."); return; } int idx = external_resources.size(); diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 7737006d10..f02dbaa0c2 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -51,7 +51,6 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader { Vector<char> str_buf; List<RES> resource_cache; - //Map<int,StringName> string_map; Vector<StringName> string_map; StringName _get_string(); diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index c2d90ed204..f147170ff7 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -74,7 +74,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy memdelete(f); return OK; } else if (err != OK) { - ERR_PRINTS("ResourceFormatImporter::load - " + p_path + ".import:" + itos(lines) + " error: " + error_text); + ERR_PRINT("ResourceFormatImporter::load - " + p_path + ".import:" + itos(lines) + " error: " + error_text); memdelete(f); return err; } @@ -279,7 +279,7 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat memdelete(f); return; } else if (err != OK) { - ERR_PRINTS("ResourceFormatImporter::get_internal_resource_path_list - " + p_path + ".import:" + itos(lines) + " error: " + error_text); + ERR_PRINT("ResourceFormatImporter::get_internal_resource_path_list - " + p_path + ".import:" + itos(lines) + " error: " + error_text); memdelete(f); return; } diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 7471ab4241..1d5d8f9280 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -157,10 +157,10 @@ bool ResourceFormatLoader::exists(const String &p_path) const { void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions) const { if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) { - PoolStringArray exts = get_script_instance()->call("get_recognized_extensions"); + PackedStringArray exts = get_script_instance()->call("get_recognized_extensions"); { - PoolStringArray::Read r = exts.read(); + const String *r = exts.ptr(); for (int i = 0; i < exts.size(); ++i) { p_extensions->push_back(r[i]); } @@ -212,10 +212,10 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { if (get_script_instance() && get_script_instance()->has_method("get_dependencies")) { - PoolStringArray deps = get_script_instance()->call("get_dependencies", p_path, p_add_types); + PackedStringArray deps = get_script_instance()->call("get_dependencies", p_path, p_add_types); { - PoolStringArray::Read r = deps.read(); + const String *r = deps.ptr(); for (int i = 0; i < deps.size(); ++i) { p_dependencies->push_back(r[i]); } @@ -247,7 +247,7 @@ void ResourceFormatLoader::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), info); } - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::POOL_STRING_ARRAY, "get_recognized_extensions")); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::PACKED_STRING_ARRAY, "get_recognized_extensions")); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles_type", PropertyInfo(Variant::STRING, "typename"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_resource_type", PropertyInfo(Variant::STRING, "path"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo("get_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "add_types"))); @@ -404,6 +404,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p if (!p_no_cache) { _remove_from_loading_map(local_path); } + print_verbose("Failed loading resource: " + path); return RES(); } if (!p_no_cache) @@ -728,8 +729,9 @@ String ResourceLoader::get_resource_type(const String &p_path) { for (int i = 0; i < loader_count; i++) { String result = loader[i]->get_resource_type(local_path); - if (result != "") + if (result != "") { return result; + } } return ""; @@ -741,7 +743,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem if (translation_remaps.has(p_path)) { // translation_remaps has the following format: - // { "res://path.png": PoolStringArray( "res://path-ru.png:ru", "res://path-de.png:de" ) } + // { "res://path.png": PackedStringArray( "res://path-ru.png:ru", "res://path-de.png:de" ) } // To find the path of the remapped resource, we extract the locale name after // the last ':' to match the project locale. @@ -815,7 +817,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem if (err == ERR_FILE_EOF) { break; } else if (err != OK) { - ERR_PRINTS("Parse error: " + p_path + ".remap:" + itos(lines) + " error: " + error_text + "."); + ERR_PRINT("Parse error: " + p_path + ".remap:" + itos(lines) + " error: " + error_text + "."); break; } @@ -903,10 +905,10 @@ void ResourceLoader::load_path_remaps() { if (!ProjectSettings::get_singleton()->has_setting("path_remap/remapped_paths")) return; - PoolVector<String> remaps = ProjectSettings::get_singleton()->get("path_remap/remapped_paths"); + Vector<String> remaps = ProjectSettings::get_singleton()->get("path_remap/remapped_paths"); int rc = remaps.size(); ERR_FAIL_COND(rc & 1); //must be even - PoolVector<String>::Read r = remaps.read(); + const String *r = remaps.ptr(); for (int i = 0; i < rc; i += 2) { @@ -953,7 +955,7 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) { ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt) + "."); ResourceFormatLoader *crl = Object::cast_to<ResourceFormatLoader>(obj); - crl->set_script(s.get_ref_ptr()); + crl->set_script(s); ResourceLoader::add_resource_format_loader(crl); return true; @@ -1013,7 +1015,7 @@ void ResourceLoader::finalize() { #ifndef NO_THREADS const LoadingMapKey *K = NULL; while ((K = loading_map.next(K))) { - ERR_PRINTS("Exited while resource is being loaded: " + K->path); + ERR_PRINT("Exited while resource is being loaded: " + K->path); } loading_map.clear(); memdelete(loading_map_mutex); diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index b468685e4d..740aaf5cfa 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -61,10 +61,10 @@ bool ResourceFormatSaver::recognize(const RES &p_resource) const { void ResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) { - PoolStringArray exts = get_script_instance()->call("get_recognized_extensions", p_resource); + PackedStringArray exts = get_script_instance()->call("get_recognized_extensions", p_resource); { - PoolStringArray::Read r = exts.read(); + const String *r = exts.ptr(); for (int i = 0; i < exts.size(); ++i) { p_extensions->push_back(r[i]); } @@ -81,7 +81,7 @@ void ResourceFormatSaver::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "save", arg0, arg1, arg2)); } - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::POOL_STRING_ARRAY, "get_recognized_extensions", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::PACKED_STRING_ARRAY, "get_recognized_extensions", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "recognize", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); } @@ -221,7 +221,7 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) { ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt) + "."); ResourceFormatSaver *crl = Object::cast_to<ResourceFormatSaver>(obj); - crl->set_script(s.get_ref_ptr()); + crl->set_script(s); ResourceSaver::add_resource_format_saver(crl); return true; diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index dee82de691..3c695c18fc 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -32,16 +32,16 @@ #include "core/io/marshalls.h" -Error StreamPeer::_put_data(const PoolVector<uint8_t> &p_data) { +Error StreamPeer::_put_data(const Vector<uint8_t> &p_data) { int len = p_data.size(); if (len == 0) return OK; - PoolVector<uint8_t>::Read r = p_data.read(); + const uint8_t *r = p_data.ptr(); return put_data(&r[0], len); } -Array StreamPeer::_put_partial_data(const PoolVector<uint8_t> &p_data) { +Array StreamPeer::_put_partial_data(const Vector<uint8_t> &p_data) { Array ret; @@ -52,7 +52,7 @@ Array StreamPeer::_put_partial_data(const PoolVector<uint8_t> &p_data) { return ret; } - PoolVector<uint8_t>::Read r = p_data.read(); + const uint8_t *r = p_data.ptr(); int sent; Error err = put_partial_data(&r[0], len, sent); @@ -68,18 +68,18 @@ Array StreamPeer::_get_data(int p_bytes) { Array ret; - PoolVector<uint8_t> data; + Vector<uint8_t> data; data.resize(p_bytes); if (data.size() != p_bytes) { ret.push_back(ERR_OUT_OF_MEMORY); - ret.push_back(PoolVector<uint8_t>()); + ret.push_back(Vector<uint8_t>()); return ret; } - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); Error err = get_data(&w[0], p_bytes); - w.release(); + ret.push_back(err); ret.push_back(data); return ret; @@ -89,19 +89,18 @@ Array StreamPeer::_get_partial_data(int p_bytes) { Array ret; - PoolVector<uint8_t> data; + Vector<uint8_t> data; data.resize(p_bytes); if (data.size() != p_bytes) { ret.push_back(ERR_OUT_OF_MEMORY); - ret.push_back(PoolVector<uint8_t>()); + ret.push_back(Vector<uint8_t>()); return ret; } - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); int received; Error err = get_partial_data(&w[0], p_bytes, received); - w.release(); if (err != OK) { data.resize(0); @@ -431,7 +430,7 @@ void StreamPeerBuffer::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &StreamPeerBuffer::clear); ClassDB::bind_method(D_METHOD("duplicate"), &StreamPeerBuffer::duplicate); - ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data_array"), "set_data_array", "get_data_array"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data_array"), "set_data_array", "get_data_array"); } Error StreamPeerBuffer::put_data(const uint8_t *p_data, int p_bytes) { @@ -443,7 +442,7 @@ Error StreamPeerBuffer::put_data(const uint8_t *p_data, int p_bytes) { data.resize(pointer + p_bytes); } - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); copymem(&w[pointer], p_data, p_bytes); pointer += p_bytes; @@ -478,8 +477,8 @@ Error StreamPeerBuffer::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_ r_received = p_bytes; } - PoolVector<uint8_t>::Read r = data.read(); - copymem(p_buffer, r.ptr() + pointer, r_received); + const uint8_t *r = data.ptr(); + copymem(p_buffer, r + pointer, r_received); pointer += r_received; // FIXME: return what? OK or ERR_* @@ -513,13 +512,13 @@ void StreamPeerBuffer::resize(int p_size) { data.resize(p_size); } -void StreamPeerBuffer::set_data_array(const PoolVector<uint8_t> &p_data) { +void StreamPeerBuffer::set_data_array(const Vector<uint8_t> &p_data) { data = p_data; pointer = 0; } -PoolVector<uint8_t> StreamPeerBuffer::get_data_array() const { +Vector<uint8_t> StreamPeerBuffer::get_data_array() const { return data; } diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index d6ce7ddc16..9358a2c07c 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -41,8 +41,8 @@ protected: static void _bind_methods(); //bind helpers - Error _put_data(const PoolVector<uint8_t> &p_data); - Array _put_partial_data(const PoolVector<uint8_t> &p_data); + Error _put_data(const Vector<uint8_t> &p_data); + Array _put_partial_data(const Vector<uint8_t> &p_data); Array _get_data(int p_bytes); Array _get_partial_data(int p_bytes); @@ -96,7 +96,7 @@ class StreamPeerBuffer : public StreamPeer { GDCLASS(StreamPeerBuffer, StreamPeer); - PoolVector<uint8_t> data; + Vector<uint8_t> data; int pointer; protected: @@ -116,8 +116,8 @@ public: int get_position() const; void resize(int p_size); - void set_data_array(const PoolVector<uint8_t> &p_data); - PoolVector<uint8_t> get_data_array() const; + void set_data_array(const Vector<uint8_t> &p_data); + Vector<uint8_t> get_data_array() const; void clear(); diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp new file mode 100644 index 0000000000..f041bf097f --- /dev/null +++ b/core/io/udp_server.cpp @@ -0,0 +1,119 @@ +/*************************************************************************/ +/* udp_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 "udp_server.h" + +void UDPServer::_bind_methods() { + + ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &UDPServer::listen, DEFVAL("*")); + ClassDB::bind_method(D_METHOD("is_connection_available"), &UDPServer::is_connection_available); + ClassDB::bind_method(D_METHOD("is_listening"), &UDPServer::is_listening); + ClassDB::bind_method(D_METHOD("take_connection"), &UDPServer::take_connection); + ClassDB::bind_method(D_METHOD("stop"), &UDPServer::stop); +} + +Error UDPServer::listen(uint16_t p_port, const IP_Address &p_bind_address) { + + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); + + Error err; + IP::Type ip_type = IP::TYPE_ANY; + + if (p_bind_address.is_valid()) + ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + + err = _sock->open(NetSocket::TYPE_UDP, ip_type); + + if (err != OK) + return ERR_CANT_CREATE; + + _sock->set_blocking_enabled(false); + _sock->set_reuse_address_enabled(true); + err = _sock->bind(p_bind_address, p_port); + + if (err != OK) { + stop(); + return err; + } + bind_address = p_bind_address; + bind_port = p_port; + return OK; +} + +bool UDPServer::is_listening() const { + ERR_FAIL_COND_V(!_sock.is_valid(), false); + + return _sock->is_open(); +} + +bool UDPServer::is_connection_available() const { + + ERR_FAIL_COND_V(!_sock.is_valid(), false); + + if (!_sock->is_open()) + return false; + + Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0); + return (err == OK); +} + +Ref<PacketPeerUDP> UDPServer::take_connection() { + + Ref<PacketPeerUDP> conn; + if (!is_connection_available()) { + return conn; + } + + conn = Ref<PacketPeerUDP>(memnew(PacketPeerUDP)); + conn->connect_socket(_sock); + _sock = Ref<NetSocket>(NetSocket::create()); + listen(bind_port, bind_address); + return conn; +} + +void UDPServer::stop() { + + if (_sock.is_valid()) { + _sock->close(); + } + bind_port = 0; + bind_address = IP_Address(); +} + +UDPServer::UDPServer() : + _sock(Ref<NetSocket>(NetSocket::create())) { +} + +UDPServer::~UDPServer() { + + stop(); +} diff --git a/core/io/udp_server.h b/core/io/udp_server.h new file mode 100644 index 0000000000..5182a04246 --- /dev/null +++ b/core/io/udp_server.h @@ -0,0 +1,58 @@ +/*************************************************************************/ +/* udp_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 UDP_SERVER_H +#define UDP_SERVER_H + +#include "core/io/net_socket.h" +#include "core/io/packet_peer_udp.h" + +class UDPServer : public Reference { + GDCLASS(UDPServer, Reference); + +protected: + static void _bind_methods(); + int bind_port; + IP_Address bind_address; + Ref<NetSocket> _sock; + +public: + Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*")); + bool is_listening() const; + bool is_connection_available() const; + Ref<PacketPeerUDP> take_connection(); + + void stop(); + + UDPServer(); + ~UDPServer(); +}; + +#endif // UDP_SERVER_H diff --git a/core/list.h b/core/list.h index 0796410a84..6250cec598 100644 --- a/core/list.h +++ b/core/list.h @@ -456,17 +456,12 @@ public: Element *I = front(); int c = 0; - while (I) { - - if (c == p_index) { - - return I->get(); - } + while (c < p_index) { I = I->next(); c++; } - CRASH_NOW(); // bug!! + return I->get(); } const T &operator[](int p_index) const { @@ -475,17 +470,12 @@ public: const Element *I = front(); int c = 0; - while (I) { - - if (c == p_index) { - - return I->get(); - } + while (c < p_index) { I = I->next(); c++; } - CRASH_NOW(); // bug!! + return I->get(); } void move_to_back(Element *p_I) { diff --git a/core/make_binders.py b/core/make_binders.py index c38db5cef4..11cfbf6e79 100644 --- a/core/make_binders.py +++ b/core/make_binders.py @@ -342,7 +342,7 @@ def make_version(template, nargs, argmax, const, ret): def run(target, source, env): - versions = 13 + versions = 15 versions_ext = 6 text = "" text_ext = "" diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 73f190a330..b26903e45a 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -235,13 +235,13 @@ Array AStar::get_points() { return point_list; } -PoolVector<int> AStar::get_point_connections(int p_id) { +Vector<int> AStar::get_point_connections(int p_id) { Point *p; bool p_exists = points.lookup(p_id, p); - ERR_FAIL_COND_V(!p_exists, PoolVector<int>()); + ERR_FAIL_COND_V(!p_exists, Vector<int>()); - PoolVector<int> point_list; + Vector<int> point_list; for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) { point_list.push_back((*it.key)); @@ -431,18 +431,18 @@ float AStar::_compute_cost(int p_from_id, int p_to_id) { return from_point->pos.distance_to(to_point->pos); } -PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { +Vector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { Point *a; bool from_exists = points.lookup(p_from_id, a); - ERR_FAIL_COND_V(!from_exists, PoolVector<Vector3>()); + ERR_FAIL_COND_V(!from_exists, Vector<Vector3>()); Point *b; bool to_exists = points.lookup(p_to_id, b); - ERR_FAIL_COND_V(!to_exists, PoolVector<Vector3>()); + ERR_FAIL_COND_V(!to_exists, Vector<Vector3>()); if (a == b) { - PoolVector<Vector3> ret; + Vector<Vector3> ret; ret.push_back(a->pos); return ret; } @@ -451,7 +451,7 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return PoolVector<Vector3>(); + if (!found_route) return Vector<Vector3>(); Point *p = end_point; int pc = 1; // Begin point @@ -460,11 +460,11 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { p = p->prev_point; } - PoolVector<Vector3> path; + Vector<Vector3> path; path.resize(pc); { - PoolVector<Vector3>::Write w = path.write(); + Vector3 *w = path.ptrw(); Point *p2 = end_point; int idx = pc - 1; @@ -479,18 +479,18 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { return path; } -PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { +Vector<int> AStar::get_id_path(int p_from_id, int p_to_id) { Point *a; bool from_exists = points.lookup(p_from_id, a); - ERR_FAIL_COND_V(!from_exists, PoolVector<int>()); + ERR_FAIL_COND_V(!from_exists, Vector<int>()); Point *b; bool to_exists = points.lookup(p_to_id, b); - ERR_FAIL_COND_V(!to_exists, PoolVector<int>()); + ERR_FAIL_COND_V(!to_exists, Vector<int>()); if (a == b) { - PoolVector<int> ret; + Vector<int> ret; ret.push_back(a->id); return ret; } @@ -499,7 +499,7 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return PoolVector<int>(); + if (!found_route) return Vector<int>(); Point *p = end_point; int pc = 1; // Begin point @@ -508,11 +508,11 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { p = p->prev_point; } - PoolVector<int> path; + Vector<int> path; path.resize(pc); { - PoolVector<int>::Write w = path.write(); + int *w = path.ptrw(); p = end_point; int idx = pc - 1; @@ -624,7 +624,7 @@ bool AStar2D::has_point(int p_id) const { return astar.has_point(p_id); } -PoolVector<int> AStar2D::get_point_connections(int p_id) { +Vector<int> AStar2D::get_point_connections(int p_id) { return astar.get_point_connections(p_id); } @@ -677,15 +677,15 @@ Vector2 AStar2D::get_closest_position_in_segment(const Vector2 &p_point) const { return Vector2(p.x, p.y); } -PoolVector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) { +Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) { - PoolVector3Array pv = astar.get_point_path(p_from_id, p_to_id); + PackedVector3Array pv = astar.get_point_path(p_from_id, p_to_id); int size = pv.size(); - PoolVector2Array path; + PackedVector2Array path; path.resize(size); { - PoolVector<Vector3>::Read r = pv.read(); - PoolVector<Vector2>::Write w = path.write(); + const Vector3 *r = pv.ptr(); + Vector2 *w = path.ptrw(); for (int i = 0; i < size; i++) { Vector3 p = r[i]; w[i] = Vector2(p.x, p.y); @@ -694,7 +694,7 @@ PoolVector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) { return path; } -PoolVector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) { +Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) { return astar.get_id_path(p_from_id, p_to_id); } diff --git a/core/math/a_star.h b/core/math/a_star.h index 0b10976932..bfcf0c09d3 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -137,7 +137,7 @@ public: void set_point_weight_scale(int p_id, real_t p_weight_scale); void remove_point(int p_id); bool has_point(int p_id) const; - PoolVector<int> get_point_connections(int p_id); + Vector<int> get_point_connections(int p_id); Array get_points(); void set_point_disabled(int p_id, bool p_disabled = true); @@ -155,8 +155,8 @@ public: int get_closest_point(const Vector3 &p_point, bool p_include_disabled = false) const; Vector3 get_closest_position_in_segment(const Vector3 &p_point) const; - PoolVector<Vector3> get_point_path(int p_from_id, int p_to_id); - PoolVector<int> get_id_path(int p_from_id, int p_to_id); + Vector<Vector3> get_point_path(int p_from_id, int p_to_id); + Vector<int> get_id_path(int p_from_id, int p_to_id); AStar(); ~AStar(); @@ -179,7 +179,7 @@ public: void set_point_weight_scale(int p_id, real_t p_weight_scale); void remove_point(int p_id); bool has_point(int p_id) const; - PoolVector<int> get_point_connections(int p_id); + Vector<int> get_point_connections(int p_id); Array get_points(); void set_point_disabled(int p_id, bool p_disabled = true); @@ -197,8 +197,8 @@ public: int get_closest_point(const Vector2 &p_point, bool p_include_disabled = false) const; Vector2 get_closest_position_in_segment(const Vector2 &p_point) const; - PoolVector<Vector2> get_point_path(int p_from_id, int p_to_id); - PoolVector<int> get_id_path(int p_from_id, int p_to_id); + Vector<Vector2> get_point_path(int p_from_id, int p_to_id); + Vector<int> get_id_path(int p_from_id, int p_to_id); AStar2D(); ~AStar2D(); diff --git a/core/math/basis.cpp b/core/math/basis.cpp index ddf5f13d55..14079f811d 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -244,6 +244,18 @@ void Basis::scale_local(const Vector3 &p_scale) { *this = scaled_local(p_scale); } +float Basis::get_uniform_scale() const { + return (elements[0].length() + elements[1].length() + elements[2].length()) / 3.0; +} + +void Basis::make_scale_uniform() { + float l = (elements[0].length() + elements[1].length() + elements[2].length()) / 3.0; + for (int i = 0; i < 3; i++) { + elements[i].normalize(); + elements[i] *= l; + } +} + Basis Basis::scaled_local(const Vector3 &p_scale) const { Basis b; b.set_diagonal(p_scale); diff --git a/core/math/basis.h b/core/math/basis.h index 6c3a939d70..0261cf67c6 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -108,6 +108,9 @@ public: void scale_local(const Vector3 &p_scale); Basis scaled_local(const Vector3 &p_scale) const; + void make_scale_uniform(); + float get_uniform_scale() const; + Vector3 get_scale() const; Vector3 get_scale_abs() const; Vector3 get_scale_local() const; diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp deleted file mode 100644 index f155d626d7..0000000000 --- a/core/math/bsp_tree.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/*************************************************************************/ -/* bsp_tree.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 "bsp_tree.h" - -#include "core/error_macros.h" -#include "core/print_string.h" - -void BSP_Tree::from_aabb(const AABB &p_aabb) { - - planes.clear(); - - for (int i = 0; i < 3; i++) { - - Vector3 n; - n[i] = 1; - planes.push_back(Plane(n, p_aabb.position[i] + p_aabb.size[i])); - planes.push_back(Plane(-n, -p_aabb.position[i])); - } - - nodes.clear(); - - for (int i = 0; i < 6; i++) { - - Node n; - n.plane = i; - n.under = (i == 0) ? UNDER_LEAF : i - 1; - n.over = OVER_LEAF; - nodes.push_back(n); - } - - aabb = p_aabb; - error_radius = 0; -} - -Vector<BSP_Tree::Node> BSP_Tree::get_nodes() const { - - return nodes; -} -Vector<Plane> BSP_Tree::get_planes() const { - - return planes; -} - -AABB BSP_Tree::get_aabb() const { - - return aabb; -} - -int BSP_Tree::_get_points_inside(int p_node, const Vector3 *p_points, int *p_indices, const Vector3 &p_center, const Vector3 &p_half_extents, int p_indices_count) const { - - const Node *node = &nodes[p_node]; - const Plane &p = planes[node->plane]; - - Vector3 min( - (p.normal.x > 0) ? -p_half_extents.x : p_half_extents.x, - (p.normal.y > 0) ? -p_half_extents.y : p_half_extents.y, - (p.normal.z > 0) ? -p_half_extents.z : p_half_extents.z); - Vector3 max = -min; - max += p_center; - min += p_center; - - real_t dist_min = p.distance_to(min); - real_t dist_max = p.distance_to(max); - - if ((dist_min * dist_max) < CMP_EPSILON) { //intersection, test point by point - - int under_count = 0; - - //sort points, so the are under first, over last - for (int i = 0; i < p_indices_count; i++) { - - int index = p_indices[i]; - - if (p.is_point_over(p_points[index])) { - - // kind of slow (but cache friendly), should try something else, - // but this is a corner case most of the time - - for (int j = index; j < p_indices_count - 1; j++) - p_indices[j] = p_indices[j + 1]; - - p_indices[p_indices_count - 1] = index; - - } else { - under_count++; - } - } - - int total = 0; - - if (under_count > 0) { - if (node->under == UNDER_LEAF) { - total += under_count; - } else { - total += _get_points_inside(node->under, p_points, p_indices, p_center, p_half_extents, under_count); - } - } - - if (under_count != p_indices_count) { - if (node->over == OVER_LEAF) { - //total+=0 //if they are over an OVER_LEAF, they are outside the model - } else { - total += _get_points_inside(node->over, p_points, &p_indices[under_count], p_center, p_half_extents, p_indices_count - under_count); - } - } - - return total; - - } else if (dist_min > 0) { //all points over plane - - if (node->over == OVER_LEAF) { - - return 0; // all these points are not visible - } - - return _get_points_inside(node->over, p_points, p_indices, p_center, p_half_extents, p_indices_count); - } else { //all points behind plane - - if (node->under == UNDER_LEAF) { - - return p_indices_count; // all these points are visible - } - return _get_points_inside(node->under, p_points, p_indices, p_center, p_half_extents, p_indices_count); - } -} - -int BSP_Tree::get_points_inside(const Vector3 *p_points, int p_point_count) const { - - if (nodes.size() == 0) - return 0; - -#if 1 - //this version is easier to debug, and and MUCH faster in real world cases - - int pass_count = 0; - const Node *nodesptr = &nodes[0]; - const Plane *planesptr = &planes[0]; - int node_count = nodes.size(); - - if (node_count == 0) // no nodes! - return 0; - - for (int i = 0; i < p_point_count; i++) { - - const Vector3 &point = p_points[i]; - if (!aabb.has_point(point)) { - continue; - } - - int idx = node_count - 1; - - bool pass = false; - - while (true) { - - if (idx == OVER_LEAF) { - pass = false; - break; - } else if (idx == UNDER_LEAF) { - pass = true; - break; - } - -#ifdef DEBUG_ENABLED - int plane_count = planes.size(); - uint16_t plane = nodesptr[idx].plane; - ERR_FAIL_UNSIGNED_INDEX_V(plane, plane_count, 0); -#endif - - idx = planesptr[nodesptr[idx].plane].is_point_over(point) ? nodes[idx].over : nodes[idx].under; - -#ifdef DEBUG_ENABLED - - ERR_FAIL_COND_V(idx < MAX_NODES && idx >= node_count, 0); -#endif - } - - if (pass) - pass_count++; - } - - return pass_count; - -#else - //this version scales better but it's slower for real world cases - - int *indices = (int *)alloca(p_point_count * sizeof(int)); - AABB bounds; - - for (int i = 0; i < p_point_count; i++) { - - indices[i] = i; - if (i == 0) - bounds.pos = p_points[i]; - else - bounds.expand_to(p_points[i]); - } - - Vector3 half_extents = bounds.size / 2.0; - return _get_points_inside(nodes.size() + 1, p_points, indices, bounds.pos + half_extents, half_extents, p_point_count); -#endif -} - -bool BSP_Tree::point_is_inside(const Vector3 &p_point) const { - - if (!aabb.has_point(p_point)) { - return false; - } - - int node_count = nodes.size(); - - if (node_count == 0) // no nodes! - return false; - - const Node *nodesptr = &nodes[0]; - const Plane *planesptr = &planes[0]; - - int idx = node_count - 1; - - while (true) { - - if (idx == OVER_LEAF) { - return false; - } - if (idx == UNDER_LEAF) { - - return true; - } - -#ifdef DEBUG_ENABLED - int plane_count = planes.size(); - uint16_t plane = nodesptr[idx].plane; - ERR_FAIL_UNSIGNED_INDEX_V(plane, plane_count, false); -#endif - - bool over = planesptr[nodesptr[idx].plane].is_point_over(p_point); - - idx = over ? nodes[idx].over : nodes[idx].under; - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(idx < MAX_NODES && idx >= node_count, false); -#endif - } -} - -static int _bsp_find_best_half_plane(const Face3 *p_faces, const Vector<int> &p_indices, real_t p_tolerance) { - - int ic = p_indices.size(); - const int *indices = p_indices.ptr(); - - int best_plane = -1; - real_t best_plane_cost = 1e20; - - // Loop to find the polygon that best divides the set. - - for (int i = 0; i < ic; i++) { - - const Face3 &f = p_faces[indices[i]]; - Plane p = f.get_plane(); - - int num_over = 0, num_under = 0, num_spanning = 0; - - for (int j = 0; j < ic; j++) { - - if (i == j) - continue; - - const Face3 &g = p_faces[indices[j]]; - int over = 0, under = 0; - - for (int k = 0; k < 3; k++) { - - real_t d = p.distance_to(g.vertex[j]); - - if (Math::abs(d) > p_tolerance) { - - if (d > 0) - over++; - else - under++; - } - } - - if (over && under) - num_spanning++; - else if (over) - num_over++; - else - num_under++; - } - - //real_t split_cost = num_spanning / (real_t) face_count; - real_t relation = Math::abs(num_over - num_under) / (real_t)ic; - - // being honest, i never found a way to add split cost to the mix in a meaninguful way - // in this engine, also, will likely be ignored anyway - - real_t plane_cost = /*split_cost +*/ relation; - - //printf("plane %i, %i over, %i under, %i spanning, cost is %g\n",i,num_over,num_under,num_spanning,plane_cost); - if (plane_cost < best_plane_cost) { - - best_plane = i; - best_plane_cost = plane_cost; - } - } - - return best_plane; -} - -static int _bsp_create_node(const Face3 *p_faces, const Vector<int> &p_indices, Vector<Plane> &p_planes, Vector<BSP_Tree::Node> &p_nodes, real_t p_tolerance) { - - ERR_FAIL_COND_V(p_nodes.size() == BSP_Tree::MAX_NODES, -1); - - // should not reach here - ERR_FAIL_COND_V(p_indices.size() == 0, -1) - - int ic = p_indices.size(); - const int *indices = p_indices.ptr(); - - int divisor_idx = _bsp_find_best_half_plane(p_faces, p_indices, p_tolerance); - - // returned error - ERR_FAIL_COND_V(divisor_idx < 0, -1); - - Vector<int> faces_over; - Vector<int> faces_under; - - Plane divisor_plane = p_faces[indices[divisor_idx]].get_plane(); - - for (int i = 0; i < ic; i++) { - - if (i == divisor_idx) - continue; - - const Face3 &f = p_faces[indices[i]]; - - /* - if (f.get_plane().is_equal_approx(divisor_plane)) - continue; - */ - - int over_count = 0; - int under_count = 0; - - for (int j = 0; j < 3; j++) { - - real_t d = divisor_plane.distance_to(f.vertex[j]); - if (Math::abs(d) > p_tolerance) { - - if (d > 0) - over_count++; - else - under_count++; - } - } - - if (over_count) - faces_over.push_back(indices[i]); - if (under_count) - faces_under.push_back(indices[i]); - } - - uint16_t over_idx = BSP_Tree::OVER_LEAF, under_idx = BSP_Tree::UNDER_LEAF; - - if (faces_over.size() > 0) { //have facess above? - - int idx = _bsp_create_node(p_faces, faces_over, p_planes, p_nodes, p_tolerance); - if (idx >= 0) - over_idx = idx; - } - - if (faces_under.size() > 0) { //have facess above? - - int idx = _bsp_create_node(p_faces, faces_under, p_planes, p_nodes, p_tolerance); - if (idx >= 0) - under_idx = idx; - } - - /* Create the node */ - - // find existing divisor plane - int divisor_plane_idx = -1; - - for (int i = 0; i < p_planes.size(); i++) { - - if (p_planes[i].is_equal_approx(divisor_plane)) { - divisor_plane_idx = i; - break; - } - } - - if (divisor_plane_idx == -1) { - - ERR_FAIL_COND_V(p_planes.size() == BSP_Tree::MAX_PLANES, -1); - divisor_plane_idx = p_planes.size(); - p_planes.push_back(divisor_plane); - } - - BSP_Tree::Node node; - node.plane = divisor_plane_idx; - node.under = under_idx; - node.over = over_idx; - - p_nodes.push_back(node); - - return p_nodes.size() - 1; -} - -BSP_Tree::operator Variant() const { - - Dictionary d; - d["error_radius"] = error_radius; - - Vector<real_t> plane_values; - plane_values.resize(planes.size() * 4); - - for (int i = 0; i < planes.size(); i++) { - - plane_values.write[i * 4 + 0] = planes[i].normal.x; - plane_values.write[i * 4 + 1] = planes[i].normal.y; - plane_values.write[i * 4 + 2] = planes[i].normal.z; - plane_values.write[i * 4 + 3] = planes[i].d; - } - - d["planes"] = plane_values; - - PoolVector<int> dst_nodes; - dst_nodes.resize(nodes.size() * 3); - - for (int i = 0; i < nodes.size(); i++) { - - dst_nodes.set(i * 3 + 0, nodes[i].over); - dst_nodes.set(i * 3 + 1, nodes[i].under); - dst_nodes.set(i * 3 + 2, nodes[i].plane); - } - - d["nodes"] = dst_nodes; - d["aabb"] = aabb; - - return Variant(d); -} - -BSP_Tree::BSP_Tree() { -} - -BSP_Tree::BSP_Tree(const Variant &p_variant) { - - Dictionary d = p_variant; - ERR_FAIL_COND(!d.has("nodes")); - ERR_FAIL_COND(!d.has("planes")); - ERR_FAIL_COND(!d.has("aabb")); - ERR_FAIL_COND(!d.has("error_radius")); - - PoolVector<int> src_nodes = d["nodes"]; - ERR_FAIL_COND(src_nodes.size() % 3); - - if (d["planes"].get_type() == Variant::POOL_REAL_ARRAY) { - - PoolVector<real_t> src_planes = d["planes"]; - int plane_count = src_planes.size(); - ERR_FAIL_COND(plane_count % 4); - planes.resize(plane_count / 4); - - if (plane_count) { - PoolVector<real_t>::Read r = src_planes.read(); - for (int i = 0; i < plane_count / 4; i++) { - - planes.write[i].normal.x = r[i * 4 + 0]; - planes.write[i].normal.y = r[i * 4 + 1]; - planes.write[i].normal.z = r[i * 4 + 2]; - planes.write[i].d = r[i * 4 + 3]; - } - } - - } else { - - planes = d["planes"]; - } - - error_radius = d["error"]; - aabb = d["aabb"]; - - //int node_count = src_nodes.size(); - nodes.resize(src_nodes.size() / 3); - - PoolVector<int>::Read r = src_nodes.read(); - - for (int i = 0; i < nodes.size(); i++) { - - nodes.write[i].over = r[i * 3 + 0]; - nodes.write[i].under = r[i * 3 + 1]; - nodes.write[i].plane = r[i * 3 + 2]; - } -} - -BSP_Tree::BSP_Tree(const PoolVector<Face3> &p_faces, real_t p_error_radius) { - - // compute aabb - - int face_count = p_faces.size(); - PoolVector<Face3>::Read faces_r = p_faces.read(); - const Face3 *facesptr = faces_r.ptr(); - - bool first = true; - - Vector<int> indices; - - for (int i = 0; i < face_count; i++) { - - const Face3 &f = facesptr[i]; - - if (f.is_degenerate()) - continue; - - for (int j = 0; j < 3; j++) { - - if (first) { - - aabb.position = f.vertex[0]; - first = false; - } else { - - aabb.expand_to(f.vertex[j]); - } - } - - indices.push_back(i); - } - - ERR_FAIL_COND(aabb.has_no_area()); - - int top = _bsp_create_node(faces_r.ptr(), indices, planes, nodes, aabb.get_longest_axis_size() * 0.0001); - - if (top < 0) { - - nodes.clear(); - planes.clear(); - ERR_FAIL_COND(top < 0); - } - - error_radius = p_error_radius; -} - -BSP_Tree::BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const AABB &p_aabb, real_t p_error_radius) : - nodes(p_nodes), - planes(p_planes), - aabb(p_aabb), - error_radius(p_error_radius) { -} - -BSP_Tree::~BSP_Tree() { -} diff --git a/core/math/bsp_tree.h b/core/math/bsp_tree.h deleted file mode 100644 index 1c8ea380ff..0000000000 --- a/core/math/bsp_tree.h +++ /dev/null @@ -1,159 +0,0 @@ -/*************************************************************************/ -/* bsp_tree.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 BSP_TREE_H -#define BSP_TREE_H - -#include "core/math/aabb.h" -#include "core/math/face3.h" -#include "core/math/plane.h" -#include "core/method_ptrcall.h" -#include "core/pool_vector.h" -#include "core/variant.h" -#include "core/vector.h" - -class BSP_Tree { -public: - enum { - - UNDER_LEAF = 0xFFFF, - OVER_LEAF = 0xFFFE, - MAX_NODES = 0xFFFE, - MAX_PLANES = (1 << 16) - }; - - struct Node { - - uint16_t plane; - uint16_t under; - uint16_t over; - }; - -private: - // thanks to the properties of Vector, - // this class can be assigned and passed around between threads - // with no cost. - - Vector<Node> nodes; - Vector<Plane> planes; - AABB aabb; - real_t error_radius; - - int _get_points_inside(int p_node, const Vector3 *p_points, int *p_indices, const Vector3 &p_center, const Vector3 &p_half_extents, int p_indices_count) const; - - template <class T> - bool _test_convex(const Node *p_nodes, const Plane *p_planes, int p_current, const T &p_convex) const; - -public: - bool is_empty() const { return nodes.size() == 0; } - Vector<Node> get_nodes() const; - Vector<Plane> get_planes() const; - AABB get_aabb() const; - - bool point_is_inside(const Vector3 &p_point) const; - int get_points_inside(const Vector3 *p_points, int p_point_count) const; - template <class T> - bool convex_is_inside(const T &p_convex) const; - - operator Variant() const; - - void from_aabb(const AABB &p_aabb); - - BSP_Tree(); - BSP_Tree(const Variant &p_variant); - BSP_Tree(const PoolVector<Face3> &p_faces, real_t p_error_radius = 0); - BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const AABB &p_aabb, real_t p_error_radius = 0); - ~BSP_Tree(); -}; - -template <class T> -bool BSP_Tree::_test_convex(const Node *p_nodes, const Plane *p_planes, int p_current, const T &p_convex) const { - - if (p_current == UNDER_LEAF) - return true; - else if (p_current == OVER_LEAF) - return false; - - bool collided = false; - const Node &n = p_nodes[p_current]; - - const Plane &p = p_planes[n.plane]; - - real_t min, max; - p_convex.project_range(p.normal, min, max); - - bool go_under = min < p.d; - bool go_over = max >= p.d; - - if (go_under && _test_convex(p_nodes, p_planes, n.under, p_convex)) - collided = true; - if (go_over && _test_convex(p_nodes, p_planes, n.over, p_convex)) - collided = true; - - return collided; -} - -template <class T> -bool BSP_Tree::convex_is_inside(const T &p_convex) const { - - int node_count = nodes.size(); - if (node_count == 0) - return false; - const Node *nodes = &this->nodes[0]; - const Plane *planes = &this->planes[0]; - - return _test_convex(nodes, planes, node_count - 1, p_convex); -} - -#ifdef PTRCALL_ENABLED - -template <> -struct PtrToArg<BSP_Tree> { - _FORCE_INLINE_ static BSP_Tree convert(const void *p_ptr) { - BSP_Tree s(Variant(*reinterpret_cast<const Dictionary *>(p_ptr))); - return s; - } - _FORCE_INLINE_ static void encode(BSP_Tree p_val, void *p_ptr) { - Dictionary *d = reinterpret_cast<Dictionary *>(p_ptr); - *d = Variant(p_val); - } -}; - -template <> -struct PtrToArg<const BSP_Tree &> { - _FORCE_INLINE_ static BSP_Tree convert(const void *p_ptr) { - BSP_Tree s(Variant(*reinterpret_cast<const Dictionary *>(p_ptr))); - return s; - } -}; - -#endif - -#endif diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index 380bae871a..c4981b954b 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -276,6 +276,36 @@ Vector2 CameraMatrix::get_viewport_half_extents() const { return Vector2(res.x, res.y); } +void CameraMatrix::get_far_plane_size(real_t &r_width, real_t &r_height) const { + + const real_t *matrix = (const real_t *)this->matrix; + ///////--- Far Plane ---/////// + Plane far_plane = Plane(matrix[3] - matrix[2], + matrix[7] - matrix[6], + matrix[11] - matrix[10], + -matrix[15] + matrix[14]); + far_plane.normalize(); + + ///////--- Right Plane ---/////// + Plane right_plane = Plane(matrix[3] - matrix[0], + matrix[7] - matrix[4], + matrix[11] - matrix[8], + -matrix[15] + matrix[12]); + right_plane.normalize(); + + Plane top_plane = Plane(matrix[3] - matrix[1], + matrix[7] - matrix[5], + matrix[11] - matrix[9], + -matrix[15] + matrix[13]); + top_plane.normalize(); + + Vector3 res; + far_plane.intersect_3(right_plane, top_plane, &res); + + r_width = res.x; + r_height = res.y; +} + bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const { Vector<Plane> planes = get_projection_planes(Transform()); @@ -485,6 +515,12 @@ void CameraMatrix::invert() { } } +void CameraMatrix::flip_y() { + for (int i = 0; i < 4; i++) { + matrix[1][i] = -matrix[1][i]; + } +} + CameraMatrix::CameraMatrix() { set_identity(); @@ -506,6 +542,28 @@ CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const { return new_matrix; } +void CameraMatrix::set_depth_correction(bool p_flip_y) { + + real_t *m = &matrix[0][0]; + + m[0] = 1; + m[1] = 0.0; + m[2] = 0.0; + m[3] = 0.0; + m[4] = 0.0; + m[5] = p_flip_y ? -1 : 1; + m[6] = 0.0; + m[7] = 0.0; + m[8] = 0.0; + m[9] = 0.0; + m[10] = 0.5; + m[11] = 0.0; + m[12] = 0.0; + m[13] = 0.0; + m[14] = 0.5; + m[15] = 1.0; +} + void CameraMatrix::set_light_bias() { real_t *m = &matrix[0][0]; diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index 2eed6d25d6..60f7d15974 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -50,6 +50,7 @@ struct CameraMatrix { void set_identity(); void set_zero(); void set_light_bias(); + void set_depth_correction(bool p_flip_y = true); void set_light_atlas_rect(const Rect2 &p_rect); void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false); void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist); @@ -74,6 +75,7 @@ struct CameraMatrix { bool get_endpoints(const Transform &p_transform, Vector3 *p_8points) const; Vector2 get_viewport_half_extents() const; + void get_far_plane_size(real_t &r_width, real_t &r_height) const; void invert(); CameraMatrix inverse() const; @@ -90,6 +92,23 @@ struct CameraMatrix { int get_pixels_per_meter(int p_for_pixel_width) const; operator Transform() const; + void flip_y(); + + bool operator==(const CameraMatrix &p_cam) const { + for (uint32_t i = 0; i < 4; i++) { + for (uint32_t j = 0; j < 4; j++) { + if (matrix[i][j] != p_cam.matrix[i][j]) { + return false; + } + } + } + return true; + } + + bool operator!=(const CameraMatrix &p_cam) const { + return !(*this == p_cam); + } + CameraMatrix(); CameraMatrix(const Transform &p_transform); ~CameraMatrix(); diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 655098376c..c7229ef688 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -64,7 +64,6 @@ const char *Expression::func_name[Expression::FUNC_MAX] = { "is_nan", "is_inf", "ease", - "decimals", "step_decimals", "stepify", "lerp", @@ -153,7 +152,6 @@ int Expression::get_func_argument_count(BuiltinFunc p_func) { case MATH_EXP: case MATH_ISNAN: case MATH_ISINF: - case MATH_DECIMALS: case MATH_STEP_DECIMALS: case MATH_SEED: case MATH_RANDSEED: @@ -376,11 +374,6 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant VALIDATE_ARG_NUM(1); *r_return = Math::ease((double)*p_inputs[0], (double)*p_inputs[1]); } break; - case MATH_DECIMALS: { - - VALIDATE_ARG_NUM(0); - *r_return = Math::step_decimals((double)*p_inputs[0]); - } break; case MATH_STEP_DECIMALS: { VALIDATE_ARG_NUM(0); @@ -764,7 +757,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } break; case VAR_TO_BYTES: { - PoolByteArray barr; + PackedByteArray barr; bool full_objects = *p_inputs[1]; int len; Error err = encode_variant(*p_inputs[0], NULL, len, full_objects); @@ -778,32 +771,32 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant barr.resize(len); { - PoolByteArray::Write w = barr.write(); - encode_variant(*p_inputs[0], w.ptr(), len, full_objects); + uint8_t *w = barr.ptrw(); + encode_variant(*p_inputs[0], w, len, full_objects); } *r_return = barr; } break; case BYTES_TO_VAR: { - if (p_inputs[0]->get_type() != Variant::POOL_BYTE_ARRAY) { + if (p_inputs[0]->get_type() != Variant::PACKED_BYTE_ARRAY) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; - r_error.expected = Variant::POOL_BYTE_ARRAY; + r_error.expected = Variant::PACKED_BYTE_ARRAY; return; } - PoolByteArray varr = *p_inputs[0]; + PackedByteArray varr = *p_inputs[0]; bool allow_objects = *p_inputs[1]; Variant ret; { - PoolByteArray::Read r = varr.read(); - Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects); + const uint8_t *r = varr.ptr(); + Error err = decode_variant(ret, r, varr.size(), NULL, allow_objects); if (err != OK) { r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format."); r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; - r_error.expected = Variant::POOL_BYTE_ARRAY; + r_error.expected = Variant::PACKED_BYTE_ARRAY; return; } } @@ -1036,8 +1029,7 @@ Error Expression::_get_token(Token &r_token) { case 'f': res = 12; break; case 'r': res = 13; break; case 'u': { - //hexnumbarh - oct is deprecated - + // hex number for (int j = 0; j < 4; j++) { CharType c = GET_CHAR(); @@ -1062,7 +1054,7 @@ Error Expression::_get_token(Token &r_token) { v = c - 'A'; v += 10; } else { - ERR_PRINT("BUG"); + ERR_PRINT("Bug parsing hex constant."); v = 0; } @@ -1071,13 +1063,8 @@ Error Expression::_get_token(Token &r_token) { } } break; - //case '\"': res='\"'; break; - //case '\\': res='\\'; break; - //case '/': res='/'; break; default: { res = next; - //r_err_str="Invalid escape sequence"; - //return ERR_PARSE_ERROR; } break; } diff --git a/core/math/expression.h b/core/math/expression.h index c5b9d79a16..1cd1415dcf 100644 --- a/core/math/expression.h +++ b/core/math/expression.h @@ -63,7 +63,6 @@ public: MATH_ISNAN, MATH_ISINF, MATH_EASE, - MATH_DECIMALS, MATH_STEP_DECIMALS, MATH_STEPIFY, MATH_LERP, diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index 7eb48290a8..69c7abfd30 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -214,23 +214,19 @@ static bool _group_face(_FaceClassify *p_faces, int len, int p_index, int p_grou return true; } -PoolVector<PoolVector<Face3> > Geometry::separate_objects(PoolVector<Face3> p_array) { +Vector<Vector<Face3> > Geometry::separate_objects(Vector<Face3> p_array) { - PoolVector<PoolVector<Face3> > objects; + Vector<Vector<Face3> > objects; int len = p_array.size(); - PoolVector<Face3>::Read r = p_array.read(); + const Face3 *arrayptr = p_array.ptr(); - const Face3 *arrayptr = r.ptr(); - - PoolVector<_FaceClassify> fc; + Vector<_FaceClassify> fc; fc.resize(len); - PoolVector<_FaceClassify>::Write fcw = fc.write(); - - _FaceClassify *_fcptr = fcw.ptr(); + _FaceClassify *_fcptr = fc.ptrw(); for (int i = 0; i < len; i++) { @@ -239,7 +235,7 @@ PoolVector<PoolVector<Face3> > Geometry::separate_objects(PoolVector<Face3> p_ar bool error = _connect_faces(_fcptr, len, -1); - ERR_FAIL_COND_V_MSG(error, PoolVector<PoolVector<Face3> >(), "Invalid geometry."); + ERR_FAIL_COND_V_MSG(error, Vector<Vector<Face3> >(), "Invalid geometry."); // Group connected faces in separate objects. @@ -263,8 +259,7 @@ PoolVector<PoolVector<Face3> > Geometry::separate_objects(PoolVector<Face3> p_ar if (group >= 0) { objects.resize(group); - PoolVector<PoolVector<Face3> >::Write obw = objects.write(); - PoolVector<Face3> *group_faces = obw.ptr(); + Vector<Face3> *group_faces = objects.ptrw(); for (int i = 0; i < len; i++) { if (!_fcptr[i].valid) @@ -470,7 +465,7 @@ static inline void _mark_outside(uint8_t ***p_cell_status, int x, int y, int z, } } -static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z, PoolVector<Face3> &p_faces) { +static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z, Vector<Face3> &p_faces) { ERR_FAIL_INDEX(x, len_x); ERR_FAIL_INDEX(y, len_y); @@ -530,14 +525,13 @@ static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, i } } -PoolVector<Face3> Geometry::wrap_geometry(PoolVector<Face3> p_array, real_t *p_error) { +Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { #define _MIN_SIZE 1.0 #define _MAX_LENGTH 20 int face_count = p_array.size(); - PoolVector<Face3>::Read facesr = p_array.read(); - const Face3 *faces = facesr.ptr(); + const Face3 *faces = p_array.ptr(); AABB global_aabb; @@ -638,7 +632,7 @@ PoolVector<Face3> Geometry::wrap_geometry(PoolVector<Face3> p_array, real_t *p_e // Build faces for the inside-outside cell divisors. - PoolVector<Face3> wrapped_faces; + Vector<Face3> wrapped_faces; for (int i = 0; i < div_x; i++) { @@ -654,8 +648,7 @@ PoolVector<Face3> Geometry::wrap_geometry(PoolVector<Face3> p_array, real_t *p_e // Transform face vertices to global coords. int wrapped_faces_count = wrapped_faces.size(); - PoolVector<Face3>::Write wrapped_facesw = wrapped_faces.write(); - Face3 *wrapped_faces_ptr = wrapped_facesw.ptr(); + Face3 *wrapped_faces_ptr = wrapped_faces.ptrw(); for (int i = 0; i < wrapped_faces_count; i++) { @@ -720,7 +713,7 @@ Vector<Vector<Vector2> > Geometry::decompose_polygon_in_convex(Vector<Point2> po return decomp; } -Geometry::MeshData Geometry::build_convex_mesh(const PoolVector<Plane> &p_planes) { +Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) { MeshData mesh; @@ -859,9 +852,9 @@ Geometry::MeshData Geometry::build_convex_mesh(const PoolVector<Plane> &p_planes return mesh; } -PoolVector<Plane> Geometry::build_box_planes(const Vector3 &p_extents) { +Vector<Plane> Geometry::build_box_planes(const Vector3 &p_extents) { - PoolVector<Plane> planes; + Vector<Plane> planes; planes.push_back(Plane(Vector3(1, 0, 0), p_extents.x)); planes.push_back(Plane(Vector3(-1, 0, 0), p_extents.x)); @@ -873,9 +866,9 @@ PoolVector<Plane> Geometry::build_box_planes(const Vector3 &p_extents) { return planes; } -PoolVector<Plane> Geometry::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) { +Vector<Plane> Geometry::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) { - PoolVector<Plane> planes; + Vector<Plane> planes; for (int i = 0; i < p_sides; i++) { @@ -895,9 +888,9 @@ PoolVector<Plane> Geometry::build_cylinder_planes(real_t p_radius, real_t p_heig return planes; } -PoolVector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis) { +Vector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis) { - PoolVector<Plane> planes; + Vector<Plane> planes; Vector3 axis; axis[p_axis] = 1.0; @@ -928,9 +921,9 @@ PoolVector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats, int return planes; } -PoolVector<Plane> Geometry::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { +Vector<Plane> Geometry::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { - PoolVector<Plane> planes; + Vector<Plane> planes; Vector3 axis; axis[p_axis] = 1.0; diff --git a/core/math/geometry.h b/core/math/geometry.h index b9193242bc..a94d00bf77 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -37,7 +37,7 @@ #include "core/math/triangulate.h" #include "core/math/vector3.h" #include "core/object.h" -#include "core/pool_vector.h" + #include "core/print_string.h" #include "core/vector.h" @@ -899,10 +899,10 @@ public: return (intersections & 1); } - static PoolVector<PoolVector<Face3> > separate_objects(PoolVector<Face3> p_array); + static Vector<Vector<Face3> > separate_objects(Vector<Face3> p_array); // Create a "wrap" that encloses the given geometry. - static PoolVector<Face3> wrap_geometry(PoolVector<Face3> p_array, real_t *p_error = NULL); + static Vector<Face3> wrap_geometry(Vector<Face3> p_array, real_t *p_error = NULL); struct MeshData { @@ -1006,11 +1006,11 @@ public: } static Vector<Vector<Vector2> > decompose_polygon_in_convex(Vector<Point2> polygon); - static MeshData build_convex_mesh(const PoolVector<Plane> &p_planes); - static PoolVector<Plane> build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis = Vector3::AXIS_Z); - static PoolVector<Plane> build_box_planes(const Vector3 &p_extents); - static PoolVector<Plane> build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z); - static PoolVector<Plane> build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z); + static MeshData build_convex_mesh(const Vector<Plane> &p_planes); + static Vector<Plane> build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis = Vector3::AXIS_Z); + static Vector<Plane> build_box_planes(const Vector3 &p_extents); + static Vector<Plane> build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z); + static Vector<Plane> build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z); static void make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size); diff --git a/core/math/rect2.h b/core/math/rect2.h index 9017377770..0d2e7eb6e5 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -60,6 +60,19 @@ struct Rect2 { return true; } + inline bool intersects_touch(const Rect2 &p_rect) const { + if (position.x > (p_rect.position.x + p_rect.size.width)) + return false; + if ((position.x + size.width) < p_rect.position.x) + return false; + if (position.y > (p_rect.position.y + p_rect.size.height)) + return false; + if ((position.y + size.height) < p_rect.position.y) + return false; + + return true; + } + inline real_t distance_to(const Vector2 &p_point) const { real_t dist = 0.0; diff --git a/core/math/transform.h b/core/math/transform.h index ad397d9c09..c6e3be4c70 100644 --- a/core/math/transform.h +++ b/core/math/transform.h @@ -34,7 +34,6 @@ #include "core/math/aabb.h" #include "core/math/basis.h" #include "core/math/plane.h" -#include "core/pool_vector.h" class Transform { public: @@ -84,8 +83,8 @@ public: _FORCE_INLINE_ AABB xform(const AABB &p_aabb) const; _FORCE_INLINE_ AABB xform_inv(const AABB &p_aabb) const; - _FORCE_INLINE_ PoolVector<Vector3> xform(const PoolVector<Vector3> &p_array) const; - _FORCE_INLINE_ PoolVector<Vector3> xform_inv(const PoolVector<Vector3> &p_array) const; + _FORCE_INLINE_ Vector<Vector3> xform(const Vector<Vector3> &p_array) const; + _FORCE_INLINE_ Vector<Vector3> xform_inv(const Vector<Vector3> &p_array) const; void operator*=(const Transform &p_transform); Transform operator*(const Transform &p_transform) const; @@ -210,13 +209,13 @@ _FORCE_INLINE_ AABB Transform::xform_inv(const AABB &p_aabb) const { return ret; } -PoolVector<Vector3> Transform::xform(const PoolVector<Vector3> &p_array) const { +Vector<Vector3> Transform::xform(const Vector<Vector3> &p_array) const { - PoolVector<Vector3> array; + Vector<Vector3> array; array.resize(p_array.size()); - PoolVector<Vector3>::Read r = p_array.read(); - PoolVector<Vector3>::Write w = array.write(); + const Vector3 *r = p_array.ptr(); + Vector3 *w = array.ptrw(); for (int i = 0; i < p_array.size(); ++i) { w[i] = xform(r[i]); @@ -224,13 +223,13 @@ PoolVector<Vector3> Transform::xform(const PoolVector<Vector3> &p_array) const { return array; } -PoolVector<Vector3> Transform::xform_inv(const PoolVector<Vector3> &p_array) const { +Vector<Vector3> Transform::xform_inv(const Vector<Vector3> &p_array) const { - PoolVector<Vector3> array; + Vector<Vector3> array; array.resize(p_array.size()); - PoolVector<Vector3>::Read r = p_array.read(); - PoolVector<Vector3>::Write w = array.write(); + const Vector3 *r = p_array.ptr(); + Vector3 *w = array.ptrw(); for (int i = 0; i < p_array.size(); ++i) { w[i] = xform_inv(r[i]); diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index 367f697ccf..fa43762aa4 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -32,7 +32,6 @@ #define TRANSFORM_2D_H #include "core/math/rect2.h" // also includes vector2, math_funcs, and ustring -#include "core/pool_vector.h" struct Transform2D { // Warning #1: basis of Transform2D is stored differently from Basis. In terms of elements array, the basis matrix looks like "on paper": @@ -112,8 +111,8 @@ struct Transform2D { _FORCE_INLINE_ Vector2 xform_inv(const Vector2 &p_vec) const; _FORCE_INLINE_ Rect2 xform(const Rect2 &p_rect) const; _FORCE_INLINE_ Rect2 xform_inv(const Rect2 &p_rect) const; - _FORCE_INLINE_ PoolVector<Vector2> xform(const PoolVector<Vector2> &p_array) const; - _FORCE_INLINE_ PoolVector<Vector2> xform_inv(const PoolVector<Vector2> &p_array) const; + _FORCE_INLINE_ Vector<Vector2> xform(const Vector<Vector2> &p_array) const; + _FORCE_INLINE_ Vector<Vector2> xform_inv(const Vector<Vector2> &p_array) const; operator String() const; @@ -203,13 +202,13 @@ Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const { return new_rect; } -PoolVector<Vector2> Transform2D::xform(const PoolVector<Vector2> &p_array) const { +Vector<Vector2> Transform2D::xform(const Vector<Vector2> &p_array) const { - PoolVector<Vector2> array; + Vector<Vector2> array; array.resize(p_array.size()); - PoolVector<Vector2>::Read r = p_array.read(); - PoolVector<Vector2>::Write w = array.write(); + const Vector2 *r = p_array.ptr(); + Vector2 *w = array.ptrw(); for (int i = 0; i < p_array.size(); ++i) { w[i] = xform(r[i]); @@ -217,13 +216,13 @@ PoolVector<Vector2> Transform2D::xform(const PoolVector<Vector2> &p_array) const return array; } -PoolVector<Vector2> Transform2D::xform_inv(const PoolVector<Vector2> &p_array) const { +Vector<Vector2> Transform2D::xform_inv(const Vector<Vector2> &p_array) const { - PoolVector<Vector2> array; + Vector<Vector2> array; array.resize(p_array.size()); - PoolVector<Vector2>::Read r = p_array.read(); - PoolVector<Vector2>::Write w = array.write(); + const Vector2 *r = p_array.ptr(); + Vector2 *w = array.ptrw(); for (int i = 0; i < p_array.size(); ++i) { w[i] = xform_inv(r[i]); diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index 53d4ea0a96..01d38cf24e 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -89,7 +89,7 @@ int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, in return index; } -void TriangleMesh::get_indices(PoolVector<int> *r_triangles_indices) const { +void TriangleMesh::get_indices(Vector<int> *r_triangles_indices) const { if (!valid) return; @@ -97,10 +97,10 @@ void TriangleMesh::get_indices(PoolVector<int> *r_triangles_indices) const { const int triangles_num = triangles.size(); // Parse vertices indices - PoolVector<Triangle>::Read triangles_read = triangles.read(); + const Triangle *triangles_read = triangles.ptr(); r_triangles_indices->resize(triangles_num * 3); - PoolVector<int>::Write r_indices_write = r_triangles_indices->write(); + int *r_indices_write = r_triangles_indices->ptrw(); for (int i = 0; i < triangles_num; ++i) { r_indices_write[3 * i + 0] = triangles_read[i].indices[0]; @@ -109,7 +109,7 @@ void TriangleMesh::get_indices(PoolVector<int> *r_triangles_indices) const { } } -void TriangleMesh::create(const PoolVector<Vector3> &p_faces) { +void TriangleMesh::create(const Vector<Vector3> &p_faces) { valid = false; @@ -119,7 +119,7 @@ void TriangleMesh::create(const PoolVector<Vector3> &p_faces) { triangles.resize(fc); bvh.resize(fc * 3); //will never be larger than this (todo make better) - PoolVector<BVH>::Write bw = bvh.write(); + BVH *bw = bvh.ptrw(); { @@ -127,8 +127,8 @@ void TriangleMesh::create(const PoolVector<Vector3> &p_faces) { //except for the Set for repeated triangles, everything //goes in-place. - PoolVector<Vector3>::Read r = p_faces.read(); - PoolVector<Triangle>::Write w = triangles.write(); + const Vector3 *r = p_faces.ptr(); + Triangle *w = triangles.ptrw(); Map<Vector3, int> db; for (int i = 0; i < fc; i++) { @@ -164,15 +164,15 @@ void TriangleMesh::create(const PoolVector<Vector3> &p_faces) { } vertices.resize(db.size()); - PoolVector<Vector3>::Write vw = vertices.write(); + Vector3 *vw = vertices.ptrw(); for (Map<Vector3, int>::Element *E = db.front(); E; E = E->next()) { vw[E->get()] = E->key(); } } - PoolVector<BVH *> bwptrs; + Vector<BVH *> bwptrs; bwptrs.resize(fc); - PoolVector<BVH *>::Write bwp = bwptrs.write(); + BVH **bwp = bwptrs.ptrw(); for (int i = 0; i < fc; i++) { bwp[i] = &bw[i]; @@ -180,9 +180,8 @@ void TriangleMesh::create(const PoolVector<Vector3> &p_faces) { max_depth = 0; int max_alloc = fc; - _create_bvh(bw.ptr(), bwp.ptr(), 0, fc, 1, max_depth, max_alloc); + _create_bvh(bw, bwp, 0, fc, 1, max_depth, max_alloc); - bw.release(); //clearup bvh.resize(max_alloc); //resize back valid = true; @@ -208,13 +207,11 @@ Vector3 TriangleMesh::get_area_normal(const AABB &p_aabb) const { int level = 0; - PoolVector<Triangle>::Read trianglesr = triangles.read(); - PoolVector<Vector3>::Read verticesr = vertices.read(); - PoolVector<BVH>::Read bvhr = bvh.read(); + const Triangle *triangleptr = triangles.ptr(); + // const Vector3 *verticesr = vertices.ptr(); + const BVH *bvhptr = bvh.ptr(); - const Triangle *triangleptr = trianglesr.ptr(); int pos = bvh.size() - 1; - const BVH *bvhptr = bvhr.ptr(); stack[0] = pos; while (true) { @@ -304,14 +301,11 @@ bool TriangleMesh::intersect_segment(const Vector3 &p_begin, const Vector3 &p_en int level = 0; - PoolVector<Triangle>::Read trianglesr = triangles.read(); - PoolVector<Vector3>::Read verticesr = vertices.read(); - PoolVector<BVH>::Read bvhr = bvh.read(); + const Triangle *triangleptr = triangles.ptr(); + const Vector3 *vertexptr = vertices.ptr(); + const BVH *bvhptr = bvh.ptr(); - const Triangle *triangleptr = trianglesr.ptr(); - const Vector3 *vertexptr = verticesr.ptr(); int pos = bvh.size() - 1; - const BVH *bvhptr = bvhr.ptr(); stack[0] = pos; while (true) { @@ -419,14 +413,11 @@ bool TriangleMesh::intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, V int level = 0; - PoolVector<Triangle>::Read trianglesr = triangles.read(); - PoolVector<Vector3>::Read verticesr = vertices.read(); - PoolVector<BVH>::Read bvhr = bvh.read(); + const Triangle *triangleptr = triangles.ptr(); + const Vector3 *vertexptr = vertices.ptr(); + const BVH *bvhptr = bvh.ptr(); - const Triangle *triangleptr = trianglesr.ptr(); - const Vector3 *vertexptr = verticesr.ptr(); int pos = bvh.size() - 1; - const BVH *bvhptr = bvhr.ptr(); stack[0] = pos; while (true) { @@ -529,14 +520,11 @@ bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_cou int level = 0; - PoolVector<Triangle>::Read trianglesr = triangles.read(); - PoolVector<Vector3>::Read verticesr = vertices.read(); - PoolVector<BVH>::Read bvhr = bvh.read(); + const Triangle *triangleptr = triangles.ptr(); + const Vector3 *vertexptr = vertices.ptr(); + const BVH *bvhptr = bvh.ptr(); - const Triangle *triangleptr = trianglesr.ptr(); - const Vector3 *vertexptr = verticesr.ptr(); int pos = bvh.size() - 1; - const BVH *bvhptr = bvhr.ptr(); stack[0] = pos; while (true) { @@ -645,16 +633,13 @@ bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count, int level = 0; - PoolVector<Triangle>::Read trianglesr = triangles.read(); - PoolVector<Vector3>::Read verticesr = vertices.read(); - PoolVector<BVH>::Read bvhr = bvh.read(); + const Triangle *triangleptr = triangles.ptr(); + const Vector3 *vertexptr = vertices.ptr(); + const BVH *bvhptr = bvh.ptr(); Transform scale(Basis().scaled(p_scale)); - const Triangle *triangleptr = trianglesr.ptr(); - const Vector3 *vertexptr = verticesr.ptr(); int pos = bvh.size() - 1; - const BVH *bvhptr = bvhr.ptr(); stack[0] = pos; while (true) { @@ -732,18 +717,18 @@ bool TriangleMesh::is_valid() const { return valid; } -PoolVector<Face3> TriangleMesh::get_faces() const { +Vector<Face3> TriangleMesh::get_faces() const { if (!valid) - return PoolVector<Face3>(); + return Vector<Face3>(); - PoolVector<Face3> faces; + Vector<Face3> faces; int ts = triangles.size(); faces.resize(triangles.size()); - PoolVector<Face3>::Write w = faces.write(); - PoolVector<Triangle>::Read r = triangles.read(); - PoolVector<Vector3>::Read rv = vertices.read(); + Face3 *w = faces.ptrw(); + const Triangle *r = triangles.ptr(); + const Vector3 *rv = vertices.ptr(); for (int i = 0; i < ts; i++) { for (int j = 0; j < 3; j++) { @@ -751,7 +736,6 @@ PoolVector<Face3> TriangleMesh::get_faces() const { } } - w.release(); return faces; } diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h index 575a78b0b5..fdbfb90465 100644 --- a/core/math/triangle_mesh.h +++ b/core/math/triangle_mesh.h @@ -44,8 +44,8 @@ class TriangleMesh : public Reference { int indices[3]; }; - PoolVector<Triangle> triangles; - PoolVector<Vector3> vertices; + Vector<Triangle> triangles; + Vector<Vector3> vertices; struct BVH { @@ -82,7 +82,7 @@ class TriangleMesh : public Reference { int _create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, int p_depth, int &max_depth, int &max_alloc); - PoolVector<BVH> bvh; + Vector<BVH> bvh; int max_depth; bool valid; @@ -93,13 +93,13 @@ public: bool intersect_convex_shape(const Plane *p_planes, int p_plane_count) const; bool inside_convex_shape(const Plane *p_planes, int p_plane_count, Vector3 p_scale = Vector3(1, 1, 1)) const; Vector3 get_area_normal(const AABB &p_aabb) const; - PoolVector<Face3> get_faces() const; + Vector<Face3> get_faces() const; - PoolVector<Triangle> get_triangles() const { return triangles; } - PoolVector<Vector3> get_vertices() const { return vertices; } - void get_indices(PoolVector<int> *r_triangles_indices) const; + Vector<Triangle> get_triangles() const { return triangles; } + Vector<Vector3> get_vertices() const { return vertices; } + void get_indices(Vector<int> *r_triangles_indices) const; - void create(const PoolVector<Vector3> &p_faces); + void create(const Vector<Vector3> &p_faces); TriangleMesh(); }; diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 71ff79c0fc..353b2acd16 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -103,7 +103,7 @@ Vector3 Vector3::cubic_interpolaten(const Vector3 &p_b, const Vector3 &p_pre_a, Vector3 out; out = 0.5 * ((p1 * 2.0) + (-p0 + p2) * t + - (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 + + (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 + (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3); return out; } @@ -122,7 +122,7 @@ Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, c Vector3 out; out = 0.5 * ((p1 * 2.0) + (-p0 + p2) * t + - (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 + + (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 + (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3); return out; } diff --git a/core/math/vector3.h b/core/math/vector3.h index 4ad3017109..3bf8644af9 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -32,6 +32,7 @@ #define VECTOR3_H #include "core/math/math_funcs.h" +#include "core/math/vector3i.h" #include "core/ustring.h" class Basis; @@ -147,6 +148,15 @@ struct Vector3 { _FORCE_INLINE_ bool operator>=(const Vector3 &p_v) const; operator String() const; + _FORCE_INLINE_ operator Vector3i() const { + return Vector3i(x, y, z); + } + + _FORCE_INLINE_ Vector3(const Vector3i &p_ivec) { + x = p_ivec.x; + y = p_ivec.y; + z = p_ivec.z; + } _FORCE_INLINE_ Vector3(real_t p_x, real_t p_y, real_t p_z) { x = p_x; diff --git a/core/pool_vector.cpp b/core/math/vector3i.cpp index d8d53f07e9..8a4ddf03b9 100644 --- a/core/pool_vector.cpp +++ b/core/math/vector3i.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* pool_vector.cpp */ +/* vector3i.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,43 +28,28 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "pool_vector.h" +#include "vector3i.h" -Mutex *pool_vector_lock = NULL; - -PoolAllocator *MemoryPool::memory_pool = NULL; -uint8_t *MemoryPool::pool_memory = NULL; -size_t *MemoryPool::pool_size = NULL; - -MemoryPool::Alloc *MemoryPool::allocs = NULL; -MemoryPool::Alloc *MemoryPool::free_list = NULL; -uint32_t MemoryPool::alloc_count = 0; -uint32_t MemoryPool::allocs_used = 0; -Mutex *MemoryPool::alloc_mutex = NULL; - -size_t MemoryPool::total_memory = 0; -size_t MemoryPool::max_memory = 0; - -void MemoryPool::setup(uint32_t p_max_allocs) { - - allocs = memnew_arr(Alloc, p_max_allocs); - alloc_count = p_max_allocs; - allocs_used = 0; - - for (uint32_t i = 0; i < alloc_count - 1; i++) { +void Vector3i::set_axis(int p_axis, int32_t p_value) { + ERR_FAIL_INDEX(p_axis, 3); + coord[p_axis] = p_value; +} +int32_t Vector3i::get_axis(int p_axis) const { - allocs[i].free_list = &allocs[i + 1]; - } + ERR_FAIL_INDEX_V(p_axis, 3, 0); + return operator[](p_axis); +} - free_list = &allocs[0]; +int Vector3i::min_axis() const { - alloc_mutex = Mutex::create(); + return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2); } +int Vector3i::max_axis() const { -void MemoryPool::cleanup() { + return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0); +} - memdelete_arr(allocs); - memdelete(alloc_mutex); +Vector3i::operator String() const { - ERR_FAIL_COND_MSG(allocs_used > 0, "There are still MemoryPool allocs in use at exit!"); + return (itos(x) + ", " + itos(y) + ", " + itos(z)); } diff --git a/core/math/vector3i.h b/core/math/vector3i.h new file mode 100644 index 0000000000..6f9754d3b9 --- /dev/null +++ b/core/math/vector3i.h @@ -0,0 +1,272 @@ +/*************************************************************************/ +/* vector3i.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 VECTOR3I_H +#define VECTOR3I_H + +#include "core/typedefs.h" +#include "core/ustring.h" + +struct Vector3i { + + enum Axis { + AXIS_X, + AXIS_Y, + AXIS_Z, + }; + + union { + struct { + int32_t x; + int32_t y; + int32_t z; + }; + + int32_t coord[3]; + }; + + _FORCE_INLINE_ const int32_t &operator[](int p_axis) const { + + return coord[p_axis]; + } + + _FORCE_INLINE_ int32_t &operator[](int p_axis) { + + return coord[p_axis]; + } + + void set_axis(int p_axis, int32_t p_value); + int32_t get_axis(int p_axis) const; + + int min_axis() const; + int max_axis() const; + + _FORCE_INLINE_ void zero(); + + _FORCE_INLINE_ Vector3i abs() const; + _FORCE_INLINE_ Vector3i sign() const; + + /* Operators */ + + _FORCE_INLINE_ Vector3i &operator+=(const Vector3i &p_v); + _FORCE_INLINE_ Vector3i operator+(const Vector3i &p_v) const; + _FORCE_INLINE_ Vector3i &operator-=(const Vector3i &p_v); + _FORCE_INLINE_ Vector3i operator-(const Vector3i &p_v) const; + _FORCE_INLINE_ Vector3i &operator*=(const Vector3i &p_v); + _FORCE_INLINE_ Vector3i operator*(const Vector3i &p_v) const; + _FORCE_INLINE_ Vector3i &operator/=(const Vector3i &p_v); + _FORCE_INLINE_ Vector3i operator/(const Vector3i &p_v) const; + + _FORCE_INLINE_ Vector3i &operator*=(int32_t p_scalar); + _FORCE_INLINE_ Vector3i operator*(int32_t p_scalar) const; + _FORCE_INLINE_ Vector3i &operator/=(int32_t p_scalar); + _FORCE_INLINE_ Vector3i operator/(int32_t p_scalar) const; + + _FORCE_INLINE_ Vector3i operator-() const; + + _FORCE_INLINE_ bool operator==(const Vector3i &p_v) const; + _FORCE_INLINE_ bool operator!=(const Vector3i &p_v) const; + _FORCE_INLINE_ bool operator<(const Vector3i &p_v) const; + _FORCE_INLINE_ bool operator<=(const Vector3i &p_v) const; + _FORCE_INLINE_ bool operator>(const Vector3i &p_v) const; + _FORCE_INLINE_ bool operator>=(const Vector3i &p_v) const; + + operator String() const; + + _FORCE_INLINE_ Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) { + x = p_x; + y = p_y; + z = p_z; + } + _FORCE_INLINE_ Vector3i() { x = y = z = 0; } +}; + +Vector3i Vector3i::abs() const { + + return Vector3i(ABS(x), ABS(y), ABS(z)); +} + +Vector3i Vector3i::sign() const { + + return Vector3i(SGN(x), SGN(y), SGN(z)); +} + +/* Operators */ + +Vector3i &Vector3i::operator+=(const Vector3i &p_v) { + + x += p_v.x; + y += p_v.y; + z += p_v.z; + return *this; +} + +Vector3i Vector3i::operator+(const Vector3i &p_v) const { + + return Vector3i(x + p_v.x, y + p_v.y, z + p_v.z); +} + +Vector3i &Vector3i::operator-=(const Vector3i &p_v) { + + x -= p_v.x; + y -= p_v.y; + z -= p_v.z; + return *this; +} +Vector3i Vector3i::operator-(const Vector3i &p_v) const { + + return Vector3i(x - p_v.x, y - p_v.y, z - p_v.z); +} + +Vector3i &Vector3i::operator*=(const Vector3i &p_v) { + + x *= p_v.x; + y *= p_v.y; + z *= p_v.z; + return *this; +} +Vector3i Vector3i::operator*(const Vector3i &p_v) const { + + return Vector3i(x * p_v.x, y * p_v.y, z * p_v.z); +} + +Vector3i &Vector3i::operator/=(const Vector3i &p_v) { + + x /= p_v.x; + y /= p_v.y; + z /= p_v.z; + return *this; +} + +Vector3i Vector3i::operator/(const Vector3i &p_v) const { + + return Vector3i(x / p_v.x, y / p_v.y, z / p_v.z); +} + +Vector3i &Vector3i::operator*=(int32_t p_scalar) { + + x *= p_scalar; + y *= p_scalar; + z *= p_scalar; + return *this; +} + +_FORCE_INLINE_ Vector3i operator*(int32_t p_scalar, const Vector3i &p_vec) { + + return p_vec * p_scalar; +} + +Vector3i Vector3i::operator*(int32_t p_scalar) const { + + return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar); +} + +Vector3i &Vector3i::operator/=(int32_t p_scalar) { + + x /= p_scalar; + y /= p_scalar; + z /= p_scalar; + return *this; +} + +Vector3i Vector3i::operator/(int32_t p_scalar) const { + + return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar); +} + +Vector3i Vector3i::operator-() const { + + return Vector3i(-x, -y, -z); +} + +bool Vector3i::operator==(const Vector3i &p_v) const { + + return (x == p_v.x && y == p_v.y && z == p_v.z); +} + +bool Vector3i::operator!=(const Vector3i &p_v) const { + + return (x != p_v.x || y != p_v.y || z != p_v.z); +} + +bool Vector3i::operator<(const Vector3i &p_v) const { + + if (x == p_v.x) { + if (y == p_v.y) + return z < p_v.z; + else + return y < p_v.y; + } else { + return x < p_v.x; + } +} + +bool Vector3i::operator>(const Vector3i &p_v) const { + + if (x == p_v.x) { + if (y == p_v.y) + return z > p_v.z; + else + return y > p_v.y; + } else { + return x > p_v.x; + } +} + +bool Vector3i::operator<=(const Vector3i &p_v) const { + + if (x == p_v.x) { + if (y == p_v.y) + return z <= p_v.z; + else + return y < p_v.y; + } else { + return x < p_v.x; + } +} + +bool Vector3i::operator>=(const Vector3i &p_v) const { + + if (x == p_v.x) { + if (y == p_v.y) + return z >= p_v.z; + else + return y > p_v.y; + } else { + return x > p_v.x; + } +} + +void Vector3i::zero() { + + x = y = z = 0; +} + +#endif // VECTOR3I_H diff --git a/core/message_queue.cpp b/core/message_queue.cpp index 64ceec5ee4..42390935d4 100644 --- a/core/message_queue.cpp +++ b/core/message_queue.cpp @@ -250,7 +250,7 @@ void MessageQueue::_call_function(Object *p_target, const StringName &p_func, co p_target->call(p_func, argptrs, p_argcount, ce); if (p_show_error && ce.error != Variant::CallError::CALL_OK) { - ERR_PRINTS("Error calling deferred method: " + Variant::get_call_error_text(p_target, p_func, argptrs, p_argcount, ce) + "."); + ERR_PRINT("Error calling deferred method: " + Variant::get_call_error_text(p_target, p_func, argptrs, p_argcount, ce) + "."); } } diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h index 0f2458d982..6ccf41229f 100644 --- a/core/method_ptrcall.h +++ b/core/method_ptrcall.h @@ -32,6 +32,7 @@ #define METHOD_PTRCALL_H #include "core/math/transform_2d.h" +#include "core/object_id.h" #include "core/typedefs.h" #include "core/variant.h" @@ -128,13 +129,13 @@ MAKE_PTRARG(NodePath); MAKE_PTRARG(RID); MAKE_PTRARG(Dictionary); MAKE_PTRARG(Array); -MAKE_PTRARG(PoolByteArray); -MAKE_PTRARG(PoolIntArray); -MAKE_PTRARG(PoolRealArray); -MAKE_PTRARG(PoolStringArray); -MAKE_PTRARG(PoolVector2Array); -MAKE_PTRARG(PoolVector3Array); -MAKE_PTRARG(PoolColorArray); +MAKE_PTRARG(PackedByteArray); +MAKE_PTRARG(PackedIntArray); +MAKE_PTRARG(PackedRealArray); +MAKE_PTRARG(PackedStringArray); +MAKE_PTRARG(PackedVector2Array); +MAKE_PTRARG(PackedVector3Array); +MAKE_PTRARG(PackedColorArray); MAKE_PTRARG_BY_REFERENCE(Variant); //this is for Object @@ -167,97 +168,113 @@ struct PtrToArg<const T *> { } }; +//this is for ObjectID + +template <> +struct PtrToArg<ObjectID> { + _FORCE_INLINE_ static const ObjectID convert(const void *p_ptr) { + + return ObjectID(*reinterpret_cast<const uint64_t *>(p_ptr)); + } + + _FORCE_INLINE_ static void encode(const ObjectID &p_val, void *p_ptr) { + + *((uint64_t *)p_ptr) = p_val; + } +}; + //this is for the special cases used by Variant -#define MAKE_VECARG(m_type) \ - template <> \ - struct PtrToArg<Vector<m_type> > { \ - _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \ - const PoolVector<m_type> *dvs = reinterpret_cast<const PoolVector<m_type> *>(p_ptr); \ - Vector<m_type> ret; \ - int len = dvs->size(); \ - ret.resize(len); \ - { \ - PoolVector<m_type>::Read r = dvs->read(); \ - for (int i = 0; i < len; i++) { \ - ret.write[i] = r[i]; \ - } \ - } \ - return ret; \ - } \ - _FORCE_INLINE_ static void encode(Vector<m_type> p_vec, void *p_ptr) { \ - PoolVector<m_type> *dv = reinterpret_cast<PoolVector<m_type> *>(p_ptr); \ - int len = p_vec.size(); \ - dv->resize(len); \ - { \ - PoolVector<m_type>::Write w = dv->write(); \ - for (int i = 0; i < len; i++) { \ - w[i] = p_vec[i]; \ - } \ - } \ - } \ - }; \ - template <> \ - struct PtrToArg<const Vector<m_type> &> { \ - _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \ - const PoolVector<m_type> *dvs = reinterpret_cast<const PoolVector<m_type> *>(p_ptr); \ - Vector<m_type> ret; \ - int len = dvs->size(); \ - ret.resize(len); \ - { \ - PoolVector<m_type>::Read r = dvs->read(); \ - for (int i = 0; i < len; i++) { \ - ret.write[i] = r[i]; \ - } \ - } \ - return ret; \ - } \ +#define MAKE_VECARG(m_type) \ + template <> \ + struct PtrToArg<Vector<m_type> > { \ + _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \ + const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \ + Vector<m_type> ret; \ + int len = dvs->size(); \ + ret.resize(len); \ + { \ + const m_type *r = dvs->ptr(); \ + for (int i = 0; i < len; i++) { \ + ret.write[i] = r[i]; \ + } \ + } \ + return ret; \ + } \ + _FORCE_INLINE_ static void encode(Vector<m_type> p_vec, void *p_ptr) { \ + Vector<m_type> *dv = reinterpret_cast<Vector<m_type> *>(p_ptr); \ + int len = p_vec.size(); \ + dv->resize(len); \ + { \ + m_type *w = dv->ptrw(); \ + for (int i = 0; i < len; i++) { \ + w[i] = p_vec[i]; \ + } \ + } \ + } \ + }; \ + template <> \ + struct PtrToArg<const Vector<m_type> &> { \ + _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \ + const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \ + Vector<m_type> ret; \ + int len = dvs->size(); \ + ret.resize(len); \ + { \ + const m_type *r = dvs->ptr(); \ + for (int i = 0; i < len; i++) { \ + ret.write[i] = r[i]; \ + } \ + } \ + return ret; \ + } \ } -#define MAKE_VECARG_ALT(m_type, m_type_alt) \ - template <> \ - struct PtrToArg<Vector<m_type_alt> > { \ - _FORCE_INLINE_ static Vector<m_type_alt> convert(const void *p_ptr) { \ - const PoolVector<m_type> *dvs = reinterpret_cast<const PoolVector<m_type> *>(p_ptr); \ - Vector<m_type_alt> ret; \ - int len = dvs->size(); \ - ret.resize(len); \ - { \ - PoolVector<m_type>::Read r = dvs->read(); \ - for (int i = 0; i < len; i++) { \ - ret.write[i] = r[i]; \ - } \ - } \ - return ret; \ - } \ - _FORCE_INLINE_ static void encode(Vector<m_type_alt> p_vec, void *p_ptr) { \ - PoolVector<m_type> *dv = reinterpret_cast<PoolVector<m_type> *>(p_ptr); \ - int len = p_vec.size(); \ - dv->resize(len); \ - { \ - PoolVector<m_type>::Write w = dv->write(); \ - for (int i = 0; i < len; i++) { \ - w[i] = p_vec[i]; \ - } \ - } \ - } \ - }; \ - template <> \ - struct PtrToArg<const Vector<m_type_alt> &> { \ - _FORCE_INLINE_ static Vector<m_type_alt> convert(const void *p_ptr) { \ - const PoolVector<m_type> *dvs = reinterpret_cast<const PoolVector<m_type> *>(p_ptr); \ - Vector<m_type_alt> ret; \ - int len = dvs->size(); \ - ret.resize(len); \ - { \ - PoolVector<m_type>::Read r = dvs->read(); \ - for (int i = 0; i < len; i++) { \ - ret.write[i] = r[i]; \ - } \ - } \ - return ret; \ - } \ +#define MAKE_VECARG_ALT(m_type, m_type_alt) \ + template <> \ + struct PtrToArg<Vector<m_type_alt> > { \ + _FORCE_INLINE_ static Vector<m_type_alt> convert(const void *p_ptr) { \ + const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \ + Vector<m_type_alt> ret; \ + int len = dvs->size(); \ + ret.resize(len); \ + { \ + const m_type *r = dvs->ptr(); \ + for (int i = 0; i < len; i++) { \ + ret.write[i] = r[i]; \ + } \ + } \ + return ret; \ + } \ + _FORCE_INLINE_ static void encode(Vector<m_type_alt> p_vec, void *p_ptr) { \ + Vector<m_type> *dv = reinterpret_cast<Vector<m_type> *>(p_ptr); \ + int len = p_vec.size(); \ + dv->resize(len); \ + { \ + m_type *w = dv->ptrw(); \ + for (int i = 0; i < len; i++) { \ + w[i] = p_vec[i]; \ + } \ + } \ + } \ + }; \ + template <> \ + struct PtrToArg<const Vector<m_type_alt> &> { \ + _FORCE_INLINE_ static Vector<m_type_alt> convert(const void *p_ptr) { \ + const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \ + Vector<m_type_alt> ret; \ + int len = dvs->size(); \ + ret.resize(len); \ + { \ + const m_type *r = dvs->ptr(); \ + for (int i = 0; i < len; i++) { \ + ret.write[i] = r[i]; \ + } \ + } \ + return ret; \ + } \ } +/* MAKE_VECARG(String); MAKE_VECARG(uint8_t); MAKE_VECARG(int); @@ -265,6 +282,7 @@ MAKE_VECARG(float); MAKE_VECARG(Vector2); MAKE_VECARG(Vector3); MAKE_VECARG(Color); +*/ MAKE_VECARG_ALT(String, StringName); //for stuff that gets converted to Array vectors @@ -308,52 +326,52 @@ MAKE_VECARR(Variant); MAKE_VECARR(RID); MAKE_VECARR(Plane); -#define MAKE_DVECARR(m_type) \ - template <> \ - struct PtrToArg<PoolVector<m_type> > { \ - _FORCE_INLINE_ static PoolVector<m_type> convert(const void *p_ptr) { \ - const Array *arr = reinterpret_cast<const Array *>(p_ptr); \ - PoolVector<m_type> ret; \ - int len = arr->size(); \ - ret.resize(len); \ - { \ - PoolVector<m_type>::Write w = ret.write(); \ - for (int i = 0; i < len; i++) { \ - w[i] = (*arr)[i]; \ - } \ - } \ - return ret; \ - } \ - _FORCE_INLINE_ static void encode(PoolVector<m_type> p_vec, void *p_ptr) { \ - Array *arr = reinterpret_cast<Array *>(p_ptr); \ - int len = p_vec.size(); \ - arr->resize(len); \ - { \ - PoolVector<m_type>::Read r = p_vec.read(); \ - for (int i = 0; i < len; i++) { \ - (*arr)[i] = r[i]; \ - } \ - } \ - } \ - }; \ - template <> \ - struct PtrToArg<const PoolVector<m_type> &> { \ - _FORCE_INLINE_ static PoolVector<m_type> convert(const void *p_ptr) { \ - const Array *arr = reinterpret_cast<const Array *>(p_ptr); \ - PoolVector<m_type> ret; \ - int len = arr->size(); \ - ret.resize(len); \ - { \ - PoolVector<m_type>::Write w = ret.write(); \ - for (int i = 0; i < len; i++) { \ - w[i] = (*arr)[i]; \ - } \ - } \ - return ret; \ - } \ +#define MAKE_DVECARR(m_type) \ + template <> \ + struct PtrToArg<Vector<m_type> > { \ + _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \ + const Array *arr = reinterpret_cast<const Array *>(p_ptr); \ + Vector<m_type> ret; \ + int len = arr->size(); \ + ret.resize(len); \ + { \ + m_type *w = ret.ptrw(); \ + for (int i = 0; i < len; i++) { \ + w[i] = (*arr)[i]; \ + } \ + } \ + return ret; \ + } \ + _FORCE_INLINE_ static void encode(Vector<m_type> p_vec, void *p_ptr) { \ + Array *arr = reinterpret_cast<Array *>(p_ptr); \ + int len = p_vec.size(); \ + arr->resize(len); \ + { \ + const m_type *r = p_vec.ptr(); \ + for (int i = 0; i < len; i++) { \ + (*arr)[i] = r[i]; \ + } \ + } \ + } \ + }; \ + template <> \ + struct PtrToArg<const Vector<m_type> &> { \ + _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \ + const Array *arr = reinterpret_cast<const Array *>(p_ptr); \ + Vector<m_type> ret; \ + int len = arr->size(); \ + ret.resize(len); \ + { \ + m_type *w = ret.ptrw(); \ + for (int i = 0; i < len; i++) { \ + w[i] = (*arr)[i]; \ + } \ + } \ + return ret; \ + } \ } -MAKE_DVECARR(Plane); +//MAKE_DVECARR(Plane); //for special case StringName #define MAKE_STRINGCONV(m_type) \ @@ -402,15 +420,15 @@ MAKE_STRINGCONV(StringName); MAKE_STRINGCONV_BY_REFERENCE(IP_Address); template <> -struct PtrToArg<PoolVector<Face3> > { - _FORCE_INLINE_ static PoolVector<Face3> convert(const void *p_ptr) { - const PoolVector<Vector3> *dvs = reinterpret_cast<const PoolVector<Vector3> *>(p_ptr); - PoolVector<Face3> ret; +struct PtrToArg<Vector<Face3> > { + _FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) { + const Vector<Vector3> *dvs = reinterpret_cast<const Vector<Vector3> *>(p_ptr); + Vector<Face3> ret; int len = dvs->size() / 3; ret.resize(len); { - PoolVector<Vector3>::Read r = dvs->read(); - PoolVector<Face3>::Write w = ret.write(); + const Vector3 *r = dvs->ptr(); + Face3 *w = ret.ptrw(); for (int i = 0; i < len; i++) { w[i].vertex[0] = r[i * 3 + 0]; w[i].vertex[1] = r[i * 3 + 1]; @@ -419,13 +437,13 @@ struct PtrToArg<PoolVector<Face3> > { } return ret; } - _FORCE_INLINE_ static void encode(PoolVector<Face3> p_vec, void *p_ptr) { - PoolVector<Vector3> *arr = reinterpret_cast<PoolVector<Vector3> *>(p_ptr); + _FORCE_INLINE_ static void encode(Vector<Face3> p_vec, void *p_ptr) { + Vector<Vector3> *arr = reinterpret_cast<Vector<Vector3> *>(p_ptr); int len = p_vec.size(); arr->resize(len * 3); { - PoolVector<Face3>::Read r = p_vec.read(); - PoolVector<Vector3>::Write w = arr->write(); + const Face3 *r = p_vec.ptr(); + Vector3 *w = arr->ptrw(); for (int i = 0; i < len; i++) { w[i * 3 + 0] = r[i].vertex[0]; w[i * 3 + 1] = r[i].vertex[1]; @@ -435,15 +453,15 @@ struct PtrToArg<PoolVector<Face3> > { } }; template <> -struct PtrToArg<const PoolVector<Face3> &> { - _FORCE_INLINE_ static PoolVector<Face3> convert(const void *p_ptr) { - const PoolVector<Vector3> *dvs = reinterpret_cast<const PoolVector<Vector3> *>(p_ptr); - PoolVector<Face3> ret; +struct PtrToArg<const Vector<Face3> &> { + _FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) { + const Vector<Vector3> *dvs = reinterpret_cast<const Vector<Vector3> *>(p_ptr); + Vector<Face3> ret; int len = dvs->size() / 3; ret.resize(len); { - PoolVector<Vector3>::Read r = dvs->read(); - PoolVector<Face3>::Write w = ret.write(); + const Vector3 *r = dvs->ptr(); + Face3 *w = ret.ptrw(); for (int i = 0; i < len; i++) { w[i].vertex[0] = r[i * 3 + 0]; w[i].vertex[1] = r[i * 3 + 1]; diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h index 7407c52816..182ed8b116 100644 --- a/core/oa_hash_map.h +++ b/core/oa_hash_map.h @@ -240,6 +240,22 @@ public: return false; } + /** + * returns true if the value was found, false otherwise. + * + * if r_data is not NULL then the value will be written to the object + * it points to. + */ + TValue *lookup_ptr(const TKey &p_key) const { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); + + if (exists) { + return &values[pos]; + } + return NULL; + } + _FORCE_INLINE_ bool has(const TKey &p_key) const { uint32_t _pos = 0; return _lookup_pos(p_key, _pos); diff --git a/core/object.cpp b/core/object.cpp index 21a3b2cc6c..0a7a46a7d2 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -968,7 +968,7 @@ void Object::cancel_delete() { _predelete_ok = true; } -void Object::set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_instance) { +void Object::set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance) { //this function is not meant to be used in any of these ways ERR_FAIL_COND(p_script.is_null()); @@ -979,7 +979,7 @@ void Object::set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_i script_instance = p_instance; } -void Object::set_script(const RefPtr &p_script) { +void Object::set_script(const Variant &p_script) { if (script == p_script) return; @@ -990,7 +990,7 @@ void Object::set_script(const RefPtr &p_script) { } script = p_script; - Ref<Script> s(script); + Ref<Script> s = script; if (!s.is_null()) { if (s->can_instance()) { @@ -1017,12 +1017,12 @@ void Object::set_script_instance(ScriptInstance *p_instance) { script_instance = p_instance; if (p_instance) - script = p_instance->get_script().get_ref_ptr(); + script = p_instance->get_script(); else - script = RefPtr(); + script = Variant(); } -RefPtr Object::get_script() const { +Variant Object::get_script() const { return script; } @@ -1075,9 +1075,9 @@ Array Object::_get_method_list_bind() const { return ret; } -PoolVector<String> Object::_get_meta_list_bind() const { +Vector<String> Object::_get_meta_list_bind() const { - PoolVector<String> _metaret; + Vector<String> _metaret; List<Variant> keys; metadata.get_key_list(&keys); @@ -1225,7 +1225,7 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int if (ce.error == Variant::CallError::CALL_ERROR_INVALID_METHOD && !ClassDB::class_exists(target->get_class_name())) { //most likely object is not initialized yet, do not throw error. } else { - ERR_PRINTS("Error calling method from signal '" + String(p_name) + "': " + Variant::get_call_error_text(target, c.method, args, argc, ce) + "."); + ERR_PRINT("Error calling method from signal '" + String(p_name) + "': " + Variant::get_call_error_text(target, c.method, args, argc, ce) + "."); err = ERR_METHOD_NOT_FOUND; } } @@ -1911,12 +1911,11 @@ void Object::set_script_instance_binding(int p_script_language_index, void *p_da _script_instance_bindings[p_script_language_index] = p_data; } -Object::Object() { - +void Object::_construct_object(bool p_reference) { + type_is_reference = p_reference; _class_ptr = NULL; _block_signals = false; _predelete_ok = 0; - _instance_id = 0; _instance_id = ObjectDB::add_instance(this); _can_translate = true; _is_queued_for_deletion = false; @@ -1934,6 +1933,14 @@ Object::Object() { _lock_index.init(1); #endif } +Object::Object(bool p_reference) { + _construct_object(p_reference); +} + +Object::Object() { + + _construct_object(false); +} Object::~Object() { @@ -1945,7 +1952,7 @@ Object::~Object() { if (_emitting) { //@todo this may need to actually reach the debugger prioritarily somehow because it may crash before - ERR_PRINTS("Object " + to_string() + " was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes."); + ERR_PRINT("Object " + to_string() + " was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes."); } while ((S = signal_map.next(NULL))) { @@ -1972,7 +1979,7 @@ Object::~Object() { } ObjectDB::remove_instance(this); - _instance_id = 0; + _instance_id = ObjectID(); _predelete_ok = 2; if (!ScriptServer::are_languages_finished()) { @@ -1994,96 +2001,139 @@ void postinitialize_handler(Object *p_object) { p_object->_postinitialize(); } -HashMap<ObjectID, Object *> ObjectDB::instances; -ObjectID ObjectDB::instance_counter = 1; -HashMap<Object *, ObjectID, ObjectDB::ObjectPtrHash> ObjectDB::instance_checks; -ObjectID ObjectDB::add_instance(Object *p_object) { - - ERR_FAIL_COND_V(p_object->get_instance_id() != 0, 0); - - rw_lock->write_lock(); - ObjectID instance_id = ++instance_counter; - instances[instance_id] = p_object; - instance_checks[p_object] = instance_id; - - rw_lock->write_unlock(); +void ObjectDB::debug_objects(DebugFunc p_func) { - return instance_id; + spin_lock.lock(); + for (uint32_t i = 0; i < slot_count; i++) { + uint32_t slot = object_slots[i].next_free; + p_func(object_slots[slot].object); + } + spin_lock.unlock(); } -void ObjectDB::remove_instance(Object *p_object) { +void Object::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { +} - rw_lock->write_lock(); +SpinLock ObjectDB::spin_lock; +uint32_t ObjectDB::slot_count = 0; +uint32_t ObjectDB::slot_max = 0; +ObjectDB::ObjectSlot *ObjectDB::object_slots = nullptr; +uint64_t ObjectDB::validator_counter = 0; - instances.erase(p_object->get_instance_id()); - instance_checks.erase(p_object); +int ObjectDB::get_object_count() { - rw_lock->write_unlock(); + return slot_count; } -Object *ObjectDB::get_instance(ObjectID p_instance_id) { - rw_lock->read_lock(); - Object **obj = instances.getptr(p_instance_id); - rw_lock->read_unlock(); +ObjectID ObjectDB::add_instance(Object *p_object) { - if (!obj) - return NULL; - return *obj; -} + spin_lock.lock(); + if (unlikely(slot_count == slot_max)) { -void ObjectDB::debug_objects(DebugFunc p_func) { + CRASH_COND(slot_count == (1 << OBJECTDB_SLOT_MAX_COUNT_BITS)); + + uint32_t new_slot_max = slot_max > 0 ? slot_max * 2 : 1; + object_slots = (ObjectSlot *)memrealloc(object_slots, sizeof(ObjectSlot) * new_slot_max); + for (uint32_t i = slot_max; i < new_slot_max; i++) { + object_slots[i].object = nullptr; + object_slots[i].is_reference = false; + object_slots[i].next_free = i; + object_slots[i].validator = 0; + } + slot_max = new_slot_max; + } - rw_lock->read_lock(); + uint32_t slot = object_slots[slot_count].next_free; + if (object_slots[slot].object != nullptr) { + spin_lock.unlock(); + ERR_FAIL_COND_V(object_slots[slot].object != nullptr, ObjectID()); + } + object_slots[slot].object = p_object; + object_slots[slot].is_reference = p_object->is_reference(); + validator_counter = (validator_counter + 1) & OBJECTDB_VALIDATOR_MASK; + if (unlikely(validator_counter == 0)) { + validator_counter = 1; + } + object_slots[slot].validator = validator_counter; - const ObjectID *K = NULL; - while ((K = instances.next(K))) { + uint64_t id = validator_counter; + id <<= OBJECTDB_SLOT_MAX_COUNT_BITS; + id |= uint64_t(slot); - p_func(instances[*K]); + if (p_object->is_reference()) { + id |= OBJECTDB_REFERENCE_BIT; } - rw_lock->read_unlock(); -} + slot_count++; -void Object::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + spin_lock.unlock(); + + return ObjectID(id); } -int ObjectDB::get_object_count() { +void ObjectDB::remove_instance(Object *p_object) { + uint64_t t = p_object->get_instance_id(); + uint32_t slot = t & OBJECTDB_SLOT_MAX_COUNT_MASK; //slot is always valid on valid object - rw_lock->read_lock(); - int count = instances.size(); - rw_lock->read_unlock(); + spin_lock.lock(); - return count; -} +#ifdef DEBUG_ENABLED -RWLock *ObjectDB::rw_lock = NULL; + if (object_slots[slot].object != p_object) { + spin_lock.unlock(); + ERR_FAIL_COND(object_slots[slot].object != p_object); + } + { + uint64_t validator = (t >> OBJECTDB_SLOT_MAX_COUNT_BITS) & OBJECTDB_VALIDATOR_MASK; + if (object_slots[slot].validator != validator) { + spin_lock.unlock(); + ERR_FAIL_COND(object_slots[slot].validator != validator); + } + } + +#endif + //decrease slot count + slot_count--; + //set the free slot properly + object_slots[slot_count].next_free = slot; + //invalidate, so checks against it fail + object_slots[slot].validator = 0; + object_slots[slot].is_reference = false; + object_slots[slot].object = nullptr; + + spin_lock.unlock(); +} void ObjectDB::setup() { - rw_lock = RWLock::create(); + //nothing to do now } void ObjectDB::cleanup() { - rw_lock->write_lock(); - if (instances.size()) { + if (slot_count > 0) { + spin_lock.lock(); WARN_PRINT("ObjectDB Instances still exist!"); if (OS::get_singleton()->is_stdout_verbose()) { - const ObjectID *K = NULL; - while ((K = instances.next(K))) { + for (uint32_t i = 0; i < slot_count; i++) { + uint32_t slot = object_slots[i].next_free; + Object *obj = object_slots[slot].object; String node_name; - if (instances[*K]->is_class("Node")) - node_name = " - Node name: " + String(instances[*K]->call("get_name")); - if (instances[*K]->is_class("Resource")) - node_name = " - Resource name: " + String(instances[*K]->call("get_name")) + " Path: " + String(instances[*K]->call("get_path")); - print_line("Leaked instance: " + String(instances[*K]->get_class()) + ":" + itos(*K) + node_name); + if (obj->is_class("Node")) + node_name = " - Node name: " + String(obj->call("get_name")); + if (obj->is_class("Resource")) + node_name = " - Resource name: " + String(obj->call("get_name")) + " Path: " + String(obj->call("get_path")); + + uint64_t id = uint64_t(slot) | (uint64_t(object_slots[slot].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[slot].is_reference ? OBJECTDB_REFERENCE_BIT : 0); + print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + node_name); } } + spin_lock.unlock(); + } + + if (object_slots) { + memfree(object_slots); } - instances.clear(); - instance_checks.clear(); - rw_lock->write_unlock(); - memdelete(rw_lock); } diff --git a/core/object.h b/core/object.h index 865c155764..afbdbda814 100644 --- a/core/object.h +++ b/core/object.h @@ -34,8 +34,10 @@ #include "core/hash_map.h" #include "core/list.h" #include "core/map.h" +#include "core/object_id.h" #include "core/os/rw_lock.h" #include "core/set.h" +#include "core/spin_lock.h" #include "core/variant.h" #include "core/vmap.h" @@ -89,6 +91,7 @@ enum PropertyHint { PROPERTY_HINT_OBJECT_TOO_BIG, ///< object is too big to send PROPERTY_HINT_NODE_PATH_VALID_TYPES, PROPERTY_HINT_SAVE_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog + PROPERTY_HINT_INT_IS_OBJECTID, PROPERTY_HINT_MAX, // When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit }; @@ -397,7 +400,6 @@ public: \ private: class ScriptInstance; -typedef uint64_t ObjectID; class Object { public: @@ -452,7 +454,7 @@ private: _id(p_id), method(p_method) { } - Target() { _id = 0; } + Target() { _id = ObjectID(); } }; struct Slot { @@ -487,7 +489,7 @@ private: Set<String> editor_section_folding; #endif ScriptInstance *script_instance; - RefPtr script; + Variant script; //reference does not yet exist, store it in a Dictionary metadata; mutable StringName _class_name; mutable const StringName *_class_ptr; @@ -505,9 +507,13 @@ private: void property_list_changed_notify(); + _FORCE_INLINE_ void _construct_object(bool p_reference); + friend class Reference; + bool type_is_reference = false; uint32_t instance_binding_count; void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS]; + Object(bool p_reference); protected: virtual void _initialize_classv() { initialize_class(); } @@ -557,7 +563,7 @@ protected: return &_class_name; } - PoolVector<String> _get_meta_list_bind() const; + Vector<String> _get_meta_list_bind() const; Array _get_property_list_bind() const; Array _get_method_list_bind() const; @@ -679,8 +685,8 @@ public: /* SCRIPT */ - void set_script(const RefPtr &p_script); - RefPtr get_script() const; + void set_script(const Variant &p_script); + Variant get_script() const; /* SCRIPT */ @@ -699,7 +705,7 @@ public: void set_script_instance(ScriptInstance *p_instance); _FORCE_INLINE_ ScriptInstance *get_script_instance() const { return script_instance; } - void set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_instance); //some script languages can't control instance creation, so this function eases the process + void set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance); //some script languages can't control instance creation, so this function eases the process void add_user_signal(const MethodInfo &p_signal); Error emit_signal(const StringName &p_name, VARIANT_ARG_LIST); @@ -750,6 +756,7 @@ public: void clear_internal_resource_paths(); + _ALWAYS_INLINE_ bool is_reference() const { return type_is_reference; } Object(); virtual ~Object(); }; @@ -759,49 +766,63 @@ void postinitialize_handler(Object *p_object); class ObjectDB { - struct ObjectPtrHash { - - static _FORCE_INLINE_ uint32_t hash(const Object *p_obj) { - - union { - const Object *p; - unsigned long i; - } u; - u.p = p_obj; - return HashMapHasherDefault::hash((uint64_t)u.i); - } +//this needs to add up to 63, 1 bit is for reference +#define OBJECTDB_VALIDATOR_BITS 39 +#define OBJECTDB_VALIDATOR_MASK ((uint64_t(1) << OBJECTDB_VALIDATOR_BITS) - 1) +#define OBJECTDB_SLOT_MAX_COUNT_BITS 24 +#define OBJECTDB_SLOT_MAX_COUNT_MASK ((uint64_t(1) << OBJECTDB_SLOT_MAX_COUNT_BITS) - 1) +#define OBJECTDB_REFERENCE_BIT (uint64_t(1) << (OBJECTDB_SLOT_MAX_COUNT_BITS + OBJECTDB_VALIDATOR_BITS)) + + struct ObjectSlot { //128 bits per slot + uint64_t validator : OBJECTDB_VALIDATOR_BITS; + uint64_t next_free : OBJECTDB_SLOT_MAX_COUNT_BITS; + uint64_t is_reference : 1; + Object *object; }; - static HashMap<ObjectID, Object *> instances; - static HashMap<Object *, ObjectID, ObjectPtrHash> instance_checks; + static SpinLock spin_lock; + static uint32_t slot_count; + static uint32_t slot_max; + static ObjectSlot *object_slots; + static uint64_t validator_counter; - static ObjectID instance_counter; friend class Object; friend void unregister_core_types(); - - static RWLock *rw_lock; static void cleanup(); + static ObjectID add_instance(Object *p_object); static void remove_instance(Object *p_object); + friend void register_core_types(); static void setup(); public: typedef void (*DebugFunc)(Object *p_obj); - static Object *get_instance(ObjectID p_instance_id); - static void debug_objects(DebugFunc p_func); - static int get_object_count(); + _ALWAYS_INLINE_ static Object *get_instance(ObjectID p_instance_id) { + + uint64_t id = p_instance_id; + uint32_t slot = id & OBJECTDB_SLOT_MAX_COUNT_MASK; + + ERR_FAIL_COND_V(slot >= slot_max, nullptr); //this should never happen unless RID is corrupted + + spin_lock.lock(); - _FORCE_INLINE_ static bool instance_validate(Object *p_ptr) { - rw_lock->read_lock(); + uint64_t validator = (id >> OBJECTDB_SLOT_MAX_COUNT_BITS) & OBJECTDB_VALIDATOR_MASK; - bool exists = instance_checks.has(p_ptr); + if (unlikely(object_slots[slot].validator != validator)) { + spin_lock.unlock(); + return nullptr; + } + + Object *object = object_slots[slot].object; - rw_lock->read_unlock(); + spin_lock.unlock(); - return exists; + return object; } + static void debug_objects(DebugFunc p_func); + static int get_object_count(); }; //needed by macros diff --git a/core/object_id.h b/core/object_id.h new file mode 100644 index 0000000000..6ab1a3031a --- /dev/null +++ b/core/object_id.h @@ -0,0 +1,33 @@ +#ifndef OBJECT_ID_H +#define OBJECT_ID_H + +#include "core/typedefs.h" + +// Class to store an object ID (int64) +// needs to be compatile with int64 because this is what Variant uses +// Also, need to be explicitly only castable to 64 bits integer types +// to avoid bugs due to loss of precision + +class ObjectID { + uint64_t id = 0; + +public: + _ALWAYS_INLINE_ bool is_reference() const { return (id & (uint64_t(1) << 63)) != 0; } + _ALWAYS_INLINE_ bool is_valid() const { return id != 0; } + _ALWAYS_INLINE_ bool is_null() const { return id == 0; } + _ALWAYS_INLINE_ operator uint64_t() const { return id; } + _ALWAYS_INLINE_ operator int64_t() const { return id; } + + _ALWAYS_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; } + _ALWAYS_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; } + _ALWAYS_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; } + + _ALWAYS_INLINE_ void operator=(int64_t p_int64) { id = p_int64; } + _ALWAYS_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; } + + _ALWAYS_INLINE_ ObjectID() {} + _ALWAYS_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; } + _ALWAYS_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; } +}; + +#endif // OBJECT_ID_H diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index 0477db82be..f65fc00077 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -285,7 +285,7 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err); if (err) { - ERR_PRINTS("Failed to open " + p_from); + ERR_PRINT("Failed to open " + p_from); return err; } @@ -294,7 +294,7 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { fsrc->close(); memdelete(fsrc); - ERR_PRINTS("Failed to open " + p_to); + ERR_PRINT("Failed to open " + p_to); return err; } diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 2917351a2f..30cfaa7617 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -408,17 +408,17 @@ int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const { } String FileAccess::get_as_utf8_string() const { - PoolVector<uint8_t> sourcef; + Vector<uint8_t> sourcef; int len = get_len(); sourcef.resize(len + 1); - PoolVector<uint8_t>::Write w = sourcef.write(); - int r = get_buffer(w.ptr(), len); + uint8_t *w = sourcef.ptrw(); + int r = get_buffer(w, len); ERR_FAIL_COND_V(r != len, String()); w[len] = 0; String s; - if (s.parse_utf8((const char *)w.ptr())) { + if (s.parse_utf8((const char *)w)) { return String(); } return s; diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index 5ecdd74a4b..61bcb7dd32 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -46,7 +46,7 @@ void MainLoop::_bind_methods() { BIND_VMETHOD(MethodInfo("_initialize")); BIND_VMETHOD(MethodInfo(Variant::BOOL, "_iteration", PropertyInfo(Variant::REAL, "delta"))); BIND_VMETHOD(MethodInfo(Variant::BOOL, "_idle", PropertyInfo(Variant::REAL, "delta"))); - BIND_VMETHOD(MethodInfo("_drop_files", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "from_screen"))); + BIND_VMETHOD(MethodInfo("_drop_files", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "from_screen"))); BIND_VMETHOD(MethodInfo("_finalize")); BIND_VMETHOD(MethodInfo("_global_menu_action", PropertyInfo(Variant::NIL, "id"), PropertyInfo(Variant::NIL, "meta"))); @@ -95,7 +95,7 @@ void MainLoop::input_event(const Ref<InputEvent> &p_event) { void MainLoop::init() { if (init_script.is_valid()) - set_script(init_script.get_ref_ptr()); + set_script(init_script); if (get_script_instance()) get_script_instance()->call("_initialize"); @@ -131,6 +131,6 @@ void MainLoop::finish() { if (get_script_instance()) { get_script_instance()->call("_finalize"); - set_script(RefPtr()); //clear script + set_script(Variant()); //clear script } } diff --git a/core/os/memory.h b/core/os/memory.h index e45f97e0c8..207149b57e 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -143,7 +143,7 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") { if (p_elements == 0) return 0; /** overloading operator new[] cannot be done , because it may not return the real allocated address (it may pad the 'element count' before the actual array). Because of that, it must be done by hand. This is the - same strategy used by std::vector, and the PoolVector class, so it should be safe.*/ + same strategy used by std::vector, and the Vector class, so it should be safe.*/ size_t len = sizeof(T) * p_elements; uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true); diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp index 3e020a1585..6ebec50ff0 100644 --- a/core/os/midi_driver.cpp +++ b/core/os/midi_driver.cpp @@ -121,9 +121,9 @@ void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_ id->parse_input_event(event); } -PoolStringArray MIDIDriver::get_connected_inputs() { +PackedStringArray MIDIDriver::get_connected_inputs() { - PoolStringArray list; + PackedStringArray list; return list; } diff --git a/core/os/midi_driver.h b/core/os/midi_driver.h index 26dbdce151..4f53feb43e 100644 --- a/core/os/midi_driver.h +++ b/core/os/midi_driver.h @@ -50,7 +50,7 @@ public: virtual Error open() = 0; virtual void close() = 0; - virtual PoolStringArray get_connected_inputs(); + virtual PackedStringArray get_connected_inputs(); static void receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_t length); diff --git a/core/os/os.cpp b/core/os/os.cpp index 1ed9484208..9a65d537ac 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -188,7 +188,7 @@ int OS::get_process_id() const { void OS::vibrate_handheld(int p_duration_ms) { - WARN_PRINTS("vibrate_handheld() only works with Android and iOS"); + WARN_PRINT("vibrate_handheld() only works with Android and iOS"); } bool OS::is_stdout_verbose() const { @@ -416,10 +416,6 @@ uint64_t OS::get_static_memory_usage() const { return Memory::get_mem_usage(); } -uint64_t OS::get_dynamic_memory_usage() const { - - return MemoryPool::total_memory; -} uint64_t OS::get_static_memory_peak_usage() const { @@ -586,16 +582,6 @@ bool OS::is_vsync_via_compositor_enabled() const { return _vsync_via_compositor; } -OS::PowerState OS::get_power_state() { - return POWERSTATE_UNKNOWN; -} -int OS::get_power_seconds_left() { - return -1; -} -int OS::get_power_percent_left() { - return -1; -} - void OS::set_has_server_feature_callback(HasServerFeatureCallback p_callback) { has_server_feature_callback = p_callback; @@ -691,9 +677,9 @@ const char *OS::get_video_driver_name(int p_driver) const { switch (p_driver) { case VIDEO_DRIVER_GLES2: return "GLES2"; - case VIDEO_DRIVER_GLES3: + case VIDEO_DRIVER_VULKAN: default: - return "GLES3"; + return "Vulkan"; } } @@ -722,12 +708,12 @@ List<String> OS::get_restart_on_exit_arguments() const { return restart_commandline; } -PoolStringArray OS::get_connected_midi_inputs() { +PackedStringArray OS::get_connected_midi_inputs() { if (MIDIDriver::get_singleton()) return MIDIDriver::get_singleton()->get_connected_inputs(); - PoolStringArray list; + PackedStringArray list; return list; } diff --git a/core/os/os.h b/core/os/os.h index 89b3414b3e..77391c3a8b 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -78,14 +78,6 @@ public: typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection); typedef bool (*HasServerFeatureCallback)(const String &p_feature); - enum PowerState { - POWERSTATE_UNKNOWN, /**< cannot determine power status */ - POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */ - POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */ - POWERSTATE_CHARGING, /**< Plugged in, charging battery */ - POWERSTATE_CHARGED /**< Plugged in, battery charged */ - }; - enum RenderThreadMode { RENDER_THREAD_UNSAFE, @@ -181,7 +173,7 @@ public: virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const = 0; enum VideoDriver { - VIDEO_DRIVER_GLES3, + VIDEO_DRIVER_VULKAN, VIDEO_DRIVER_GLES2, VIDEO_DRIVER_MAX, }; @@ -193,7 +185,7 @@ public: virtual int get_audio_driver_count() const; virtual const char *get_audio_driver_name(int p_driver) const; - virtual PoolStringArray get_connected_midi_inputs(); + virtual PackedStringArray get_connected_midi_inputs(); virtual void open_midi_inputs(); virtual void close_midi_inputs(); @@ -398,7 +390,6 @@ public: virtual uint64_t get_static_memory_usage() const; virtual uint64_t get_static_memory_peak_usage() const; - virtual uint64_t get_dynamic_memory_usage() const; virtual uint64_t get_free_static_memory() const; RenderThreadMode get_render_thread_mode() const { return _render_thread_mode; } @@ -517,10 +508,6 @@ public: void set_vsync_via_compositor(bool p_enable); bool is_vsync_via_compositor_enabled() const; - virtual OS::PowerState get_power_state(); - virtual int get_power_seconds_left(); - virtual int get_power_percent_left(); - virtual void force_process_input(){}; bool has_feature(const String &p_feature); @@ -542,6 +529,4 @@ public: virtual ~OS(); }; -VARIANT_ENUM_CAST(OS::PowerState); - #endif diff --git a/core/os/semaphore.cpp b/core/os/semaphore.cpp index b2ba9716f0..2c20f234d0 100644 --- a/core/os/semaphore.cpp +++ b/core/os/semaphore.cpp @@ -32,14 +32,14 @@ #include "core/error_macros.h" -Semaphore *(*Semaphore::create_func)() = 0; +SemaphoreOld *(*SemaphoreOld::create_func)() = 0; -Semaphore *Semaphore::create() { +SemaphoreOld *SemaphoreOld::create() { ERR_FAIL_COND_V(!create_func, 0); return create_func(); } -Semaphore::~Semaphore() { +SemaphoreOld::~SemaphoreOld() { } diff --git a/core/os/semaphore.h b/core/os/semaphore.h index 9f3c0f549c..f16a15a6db 100644 --- a/core/os/semaphore.h +++ b/core/os/semaphore.h @@ -32,19 +32,53 @@ #define SEMAPHORE_H #include "core/error_list.h" +#include "core/typedefs.h" + +#include <condition_variable> +#include <mutex> class Semaphore { +private: + std::mutex mutex_; + std::condition_variable condition_; + unsigned long count_ = 0; // Initialized as locked. + +public: + _ALWAYS_INLINE_ void post() { + std::lock_guard<decltype(mutex_)> lock(mutex_); + ++count_; + condition_.notify_one(); + } + + _ALWAYS_INLINE_ void wait() { + std::unique_lock<decltype(mutex_)> lock(mutex_); + while (!count_) // Handle spurious wake-ups. + condition_.wait(lock); + --count_; + } + + _ALWAYS_INLINE_ bool try_wait() { + std::lock_guard<decltype(mutex_)> lock(mutex_); + if (count_) { + --count_; + return true; + } + return false; + } +}; + +class SemaphoreOld { protected: - static Semaphore *(*create_func)(); + static SemaphoreOld *(*create_func)(); public: virtual Error wait() = 0; ///< wait until semaphore has positive value, then decrement and pass virtual Error post() = 0; ///< unlock the semaphore, incrementing the value virtual int get() const = 0; ///< get semaphore value - static Semaphore *create(); ///< Create a mutex + static SemaphoreOld *create(); ///< Create a mutex - virtual ~Semaphore(); + virtual ~SemaphoreOld(); }; #endif diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp index d4f65b0312..916aeeda30 100644 --- a/core/os/thread_dummy.cpp +++ b/core/os/thread_dummy.cpp @@ -48,12 +48,12 @@ void MutexDummy::make_default() { Mutex::create_func = &MutexDummy::create; }; -Semaphore *SemaphoreDummy::create() { +SemaphoreOld *SemaphoreDummy::create() { return memnew(SemaphoreDummy); }; void SemaphoreDummy::make_default() { - Semaphore::create_func = &SemaphoreDummy::create; + SemaphoreOld::create_func = &SemaphoreDummy::create; }; RWLock *RWLockDummy::create() { diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h index c8b52ae4dd..9329cdaa32 100644 --- a/core/os/thread_dummy.h +++ b/core/os/thread_dummy.h @@ -58,9 +58,9 @@ public: static void make_default(); }; -class SemaphoreDummy : public Semaphore { +class SemaphoreDummy : public SemaphoreOld { - static Semaphore *create(); + static SemaphoreOld *create(); public: virtual Error wait() { return OK; }; diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp index f8f51c4c75..ae5f89e870 100644 --- a/core/packed_data_container.cpp +++ b/core/packed_data_container.cpp @@ -80,20 +80,20 @@ Variant PackedDataContainer::_iter_get_ofs(const Variant &p_iter, uint32_t p_off if (pos < 0 || pos >= size) return Variant(); - PoolVector<uint8_t>::Read rd = data.read(); + const uint8_t *rd = data.ptr(); const uint8_t *r = &rd[p_offset]; uint32_t type = decode_uint32(r); bool err = false; if (type == TYPE_ARRAY) { - uint32_t vpos = decode_uint32(rd.ptr() + p_offset + 8 + pos * 4); - return _get_at_ofs(vpos, rd.ptr(), err); + uint32_t vpos = decode_uint32(rd + p_offset + 8 + pos * 4); + return _get_at_ofs(vpos, rd, err); } else if (type == TYPE_DICT) { - uint32_t vpos = decode_uint32(rd.ptr() + p_offset + 8 + pos * 12 + 4); - return _get_at_ofs(vpos, rd.ptr(), err); + uint32_t vpos = decode_uint32(rd + p_offset + 8 + pos * 12 + 4); + return _get_at_ofs(vpos, rd, err); } else { ERR_FAIL_V(Variant()); } @@ -127,7 +127,7 @@ Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, b uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const { - PoolVector<uint8_t>::Read rd = data.read(); + const uint8_t *rd = data.ptr(); const uint8_t *r = &rd[p_ofs]; uint32_t type = decode_uint32(r); @@ -136,8 +136,8 @@ uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const { int PackedDataContainer::_size(uint32_t p_ofs) const { - PoolVector<uint8_t>::Read rd = data.read(); - ERR_FAIL_COND_V(!rd.ptr(), 0); + const uint8_t *rd = data.ptr(); + ERR_FAIL_COND_V(!rd, 0); const uint8_t *r = &rd[p_ofs]; uint32_t type = decode_uint32(r); @@ -157,7 +157,7 @@ int PackedDataContainer::_size(uint32_t p_ofs) const { Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, bool &err) const { - PoolVector<uint8_t>::Read rd = data.read(); + const uint8_t *rd = data.ptr(); const uint8_t *r = &rd[p_ofs]; uint32_t type = decode_uint32(r); @@ -172,7 +172,7 @@ Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, b return Variant(); } uint32_t ofs = decode_uint32(r + 8 + 4 * idx); - return _get_at_ofs(ofs, rd.ptr(), err); + return _get_at_ofs(ofs, rd, err); } else { err = true; @@ -188,12 +188,12 @@ Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, b for (uint32_t i = 0; i < len; i++) { uint32_t khash = decode_uint32(r + 8 + i * 12 + 0); if (khash == hash) { - Variant key = _get_at_ofs(decode_uint32(r + 8 + i * 12 + 4), rd.ptr(), err); + Variant key = _get_at_ofs(decode_uint32(r + 8 + i * 12 + 4), rd, err); if (err) return Variant(); if (key == p_key) { //key matches, return value - return _get_at_ofs(decode_uint32(r + 8 + i * 12 + 8), rd.ptr(), err); + return _get_at_ofs(decode_uint32(r + 8 + i * 12 + 8), rd, err); } found = true; } else { @@ -240,13 +240,13 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd case Variant::AABB: case Variant::BASIS: case Variant::TRANSFORM: - case Variant::POOL_BYTE_ARRAY: - case Variant::POOL_INT_ARRAY: - case Variant::POOL_REAL_ARRAY: - case Variant::POOL_STRING_ARRAY: - case Variant::POOL_VECTOR2_ARRAY: - case Variant::POOL_VECTOR3_ARRAY: - case Variant::POOL_COLOR_ARRAY: + case Variant::PACKED_BYTE_ARRAY: + case Variant::PACKED_INT_ARRAY: + case Variant::PACKED_REAL_ARRAY: + case Variant::PACKED_STRING_ARRAY: + case Variant::PACKED_VECTOR2_ARRAY: + case Variant::PACKED_VECTOR3_ARRAY: + case Variant::PACKED_COLOR_ARRAY: case Variant::NODE_PATH: { uint32_t pos = tmpdata.size(); @@ -335,19 +335,19 @@ Error PackedDataContainer::pack(const Variant &p_data) { _pack(p_data, tmpdata, string_cache); datalen = tmpdata.size(); data.resize(tmpdata.size()); - PoolVector<uint8_t>::Write w = data.write(); - copymem(w.ptr(), tmpdata.ptr(), tmpdata.size()); + uint8_t *w = data.ptrw(); + copymem(w, tmpdata.ptr(), tmpdata.size()); return OK; } -void PackedDataContainer::_set_data(const PoolVector<uint8_t> &p_data) { +void PackedDataContainer::_set_data(const Vector<uint8_t> &p_data) { data = p_data; datalen = data.size(); } -PoolVector<uint8_t> PackedDataContainer::_get_data() const { +Vector<uint8_t> PackedDataContainer::_get_data() const { return data; } @@ -375,7 +375,7 @@ void PackedDataContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("pack", "value"), &PackedDataContainer::pack); ClassDB::bind_method(D_METHOD("size"), &PackedDataContainer::size); - ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "__data__"), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "__data__"), "_set_data", "_get_data"); } PackedDataContainer::PackedDataContainer() { diff --git a/core/packed_data_container.h b/core/packed_data_container.h index b534169077..852fdcd0d3 100644 --- a/core/packed_data_container.h +++ b/core/packed_data_container.h @@ -48,7 +48,7 @@ class PackedDataContainer : public Resource { bool operator<(const DictKey &p_key) const { return hash < p_key.hash; } }; - PoolVector<uint8_t> data; + Vector<uint8_t> data; int datalen; uint32_t _pack(const Variant &p_data, Vector<uint8_t> &tmpdata, Map<String, uint32_t> &string_cache); @@ -68,8 +68,8 @@ class PackedDataContainer : public Resource { int _size(uint32_t p_ofs) const; protected: - void _set_data(const PoolVector<uint8_t> &p_data); - PoolVector<uint8_t> _get_data() const; + void _set_data(const Vector<uint8_t> &p_data); + Vector<uint8_t> _get_data() const; static void _bind_methods(); public: diff --git a/core/pool_vector.h b/core/pool_vector.h deleted file mode 100644 index 01c40a237d..0000000000 --- a/core/pool_vector.h +++ /dev/null @@ -1,648 +0,0 @@ -/*************************************************************************/ -/* pool_vector.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 POOL_VECTOR_H -#define POOL_VECTOR_H - -#include "core/os/copymem.h" -#include "core/os/memory.h" -#include "core/os/rw_lock.h" -#include "core/pool_allocator.h" -#include "core/safe_refcount.h" -#include "core/ustring.h" - -struct MemoryPool { - - //avoid accessing these directly, must be public for template access - - static PoolAllocator *memory_pool; - static uint8_t *pool_memory; - static size_t *pool_size; - - struct Alloc { - - SafeRefCount refcount; - uint32_t lock; - void *mem; - PoolAllocator::ID pool_id; - size_t size; - - Alloc *free_list; - - Alloc() : - lock(0), - mem(NULL), - pool_id(POOL_ALLOCATOR_INVALID_ID), - size(0), - free_list(NULL) { - } - }; - - static Alloc *allocs; - static Alloc *free_list; - static uint32_t alloc_count; - static uint32_t allocs_used; - static Mutex *alloc_mutex; - static size_t total_memory; - static size_t max_memory; - - static void setup(uint32_t p_max_allocs = (1 << 16)); - static void cleanup(); -}; - -template <class T> -class PoolVector { - - MemoryPool::Alloc *alloc; - - void _copy_on_write() { - - if (!alloc) - return; - - // ERR_FAIL_COND(alloc->lock>0); should not be illegal to lock this for copy on write, as it's a copy on write after all - - // Refcount should not be zero, otherwise it's a misuse of COW - if (alloc->refcount.get() == 1) - return; //nothing to do - - //must allocate something - - MemoryPool::alloc_mutex->lock(); - if (MemoryPool::allocs_used == MemoryPool::alloc_count) { - MemoryPool::alloc_mutex->unlock(); - ERR_FAIL_MSG("All memory pool allocations are in use, can't COW."); - } - - MemoryPool::Alloc *old_alloc = alloc; - - //take one from the free list - alloc = MemoryPool::free_list; - MemoryPool::free_list = alloc->free_list; - //increment the used counter - MemoryPool::allocs_used++; - - //copy the alloc data - alloc->size = old_alloc->size; - alloc->refcount.init(); - alloc->pool_id = POOL_ALLOCATOR_INVALID_ID; - alloc->lock = 0; - -#ifdef DEBUG_ENABLED - MemoryPool::total_memory += alloc->size; - if (MemoryPool::total_memory > MemoryPool::max_memory) { - MemoryPool::max_memory = MemoryPool::total_memory; - } -#endif - - MemoryPool::alloc_mutex->unlock(); - - if (MemoryPool::memory_pool) { - - } else { - alloc->mem = memalloc(alloc->size); - } - - { - Write w; - w._ref(alloc); - Read r; - r._ref(old_alloc); - - int cur_elements = alloc->size / sizeof(T); - T *dst = (T *)w.ptr(); - const T *src = (const T *)r.ptr(); - for (int i = 0; i < cur_elements; i++) { - memnew_placement(&dst[i], T(src[i])); - } - } - - if (old_alloc->refcount.unref()) { - //this should never happen but.. - -#ifdef DEBUG_ENABLED - MemoryPool::alloc_mutex->lock(); - MemoryPool::total_memory -= old_alloc->size; - MemoryPool::alloc_mutex->unlock(); -#endif - - { - Write w; - w._ref(old_alloc); - - int cur_elements = old_alloc->size / sizeof(T); - T *elems = (T *)w.ptr(); - for (int i = 0; i < cur_elements; i++) { - elems[i].~T(); - } - } - - if (MemoryPool::memory_pool) { - //resize memory pool - //if none, create - //if some resize - } else { - - memfree(old_alloc->mem); - old_alloc->mem = NULL; - old_alloc->size = 0; - - MemoryPool::alloc_mutex->lock(); - old_alloc->free_list = MemoryPool::free_list; - MemoryPool::free_list = old_alloc; - MemoryPool::allocs_used--; - MemoryPool::alloc_mutex->unlock(); - } - } - } - - void _reference(const PoolVector &p_pool_vector) { - - if (alloc == p_pool_vector.alloc) - return; - - _unreference(); - - if (!p_pool_vector.alloc) { - return; - } - - if (p_pool_vector.alloc->refcount.ref()) { - alloc = p_pool_vector.alloc; - } - } - - void _unreference() { - - if (!alloc) - return; - - if (!alloc->refcount.unref()) { - alloc = NULL; - return; - } - - //must be disposed! - - { - int cur_elements = alloc->size / sizeof(T); - - // Don't use write() here because it could otherwise provoke COW, - // which is not desirable here because we are destroying the last reference anyways - Write w; - // Reference to still prevent other threads from touching the alloc - w._ref(alloc); - - for (int i = 0; i < cur_elements; i++) { - - w[i].~T(); - } - } - -#ifdef DEBUG_ENABLED - MemoryPool::alloc_mutex->lock(); - MemoryPool::total_memory -= alloc->size; - MemoryPool::alloc_mutex->unlock(); -#endif - - if (MemoryPool::memory_pool) { - //resize memory pool - //if none, create - //if some resize - } else { - - memfree(alloc->mem); - alloc->mem = NULL; - alloc->size = 0; - - MemoryPool::alloc_mutex->lock(); - alloc->free_list = MemoryPool::free_list; - MemoryPool::free_list = alloc; - MemoryPool::allocs_used--; - MemoryPool::alloc_mutex->unlock(); - } - - alloc = NULL; - } - -public: - class Access { - friend class PoolVector; - - protected: - MemoryPool::Alloc *alloc; - T *mem; - - _FORCE_INLINE_ void _ref(MemoryPool::Alloc *p_alloc) { - alloc = p_alloc; - if (alloc) { - if (atomic_increment(&alloc->lock) == 1) { - if (MemoryPool::memory_pool) { - //lock it and get mem - } - } - - mem = (T *)alloc->mem; - } - } - - _FORCE_INLINE_ void _unref() { - - if (alloc) { - if (atomic_decrement(&alloc->lock) == 0) { - if (MemoryPool::memory_pool) { - //put mem back - } - } - - mem = NULL; - alloc = NULL; - } - } - - Access() { - alloc = NULL; - mem = NULL; - } - - public: - virtual ~Access() { - _unref(); - } - - void release() { - _unref(); - } - }; - - class Read : public Access { - public: - _FORCE_INLINE_ const T &operator[](int p_index) const { return this->mem[p_index]; } - _FORCE_INLINE_ const T *ptr() const { return this->mem; } - - void operator=(const Read &p_read) { - if (this->alloc == p_read.alloc) - return; - this->_unref(); - this->_ref(p_read.alloc); - } - - Read(const Read &p_read) { - this->_ref(p_read.alloc); - } - - Read() {} - }; - - class Write : public Access { - public: - _FORCE_INLINE_ T &operator[](int p_index) const { return this->mem[p_index]; } - _FORCE_INLINE_ T *ptr() const { return this->mem; } - - void operator=(const Write &p_read) { - if (this->alloc == p_read.alloc) - return; - this->_unref(); - this->_ref(p_read.alloc); - } - - Write(const Write &p_read) { - this->_ref(p_read.alloc); - } - - Write() {} - }; - - Read read() const { - - Read r; - if (alloc) { - r._ref(alloc); - } - return r; - } - Write write() { - - Write w; - if (alloc) { - _copy_on_write(); //make sure there is only one being acessed - w._ref(alloc); - } - return w; - } - - template <class MC> - void fill_with(const MC &p_mc) { - - int c = p_mc.size(); - resize(c); - Write w = write(); - int idx = 0; - for (const typename MC::Element *E = p_mc.front(); E; E = E->next()) { - - w[idx++] = E->get(); - } - } - - void remove(int p_index) { - - int s = size(); - ERR_FAIL_INDEX(p_index, s); - Write w = write(); - for (int i = p_index; i < s - 1; i++) { - - w[i] = w[i + 1]; - }; - w = Write(); - resize(s - 1); - } - - inline int size() const; - inline bool empty() const; - T get(int p_index) const; - void set(int p_index, const T &p_val); - void push_back(const T &p_val); - void append(const T &p_val) { push_back(p_val); } - void append_array(const PoolVector<T> &p_arr) { - int ds = p_arr.size(); - if (ds == 0) - return; - int bs = size(); - resize(bs + ds); - Write w = write(); - Read r = p_arr.read(); - for (int i = 0; i < ds; i++) - w[bs + i] = r[i]; - } - - PoolVector<T> subarray(int p_from, int p_to) { - - if (p_from < 0) { - p_from = size() + p_from; - } - if (p_to < 0) { - p_to = size() + p_to; - } - - ERR_FAIL_INDEX_V(p_from, size(), PoolVector<T>()); - ERR_FAIL_INDEX_V(p_to, size(), PoolVector<T>()); - - PoolVector<T> slice; - int span = 1 + p_to - p_from; - slice.resize(span); - Read r = read(); - Write w = slice.write(); - for (int i = 0; i < span; ++i) { - w[i] = r[p_from + i]; - } - - return slice; - } - - Error insert(int p_pos, const T &p_val) { - - int s = size(); - ERR_FAIL_INDEX_V(p_pos, s + 1, ERR_INVALID_PARAMETER); - resize(s + 1); - { - Write w = write(); - for (int i = s; i > p_pos; i--) - w[i] = w[i - 1]; - w[p_pos] = p_val; - } - - return OK; - } - - String join(String delimiter) { - String rs = ""; - int s = size(); - Read r = read(); - for (int i = 0; i < s; i++) { - rs += r[i] + delimiter; - } - rs.erase(rs.length() - delimiter.length(), delimiter.length()); - return rs; - } - - bool is_locked() const { return alloc && alloc->lock > 0; } - - inline T operator[](int p_index) const; - - Error resize(int p_size); - - void invert(); - - void operator=(const PoolVector &p_pool_vector) { _reference(p_pool_vector); } - PoolVector() { alloc = NULL; } - PoolVector(const PoolVector &p_pool_vector) { - alloc = NULL; - _reference(p_pool_vector); - } - ~PoolVector() { _unreference(); } -}; - -template <class T> -int PoolVector<T>::size() const { - - return alloc ? alloc->size / sizeof(T) : 0; -} - -template <class T> -bool PoolVector<T>::empty() const { - - return alloc ? alloc->size == 0 : true; -} - -template <class T> -T PoolVector<T>::get(int p_index) const { - - return operator[](p_index); -} - -template <class T> -void PoolVector<T>::set(int p_index, const T &p_val) { - - ERR_FAIL_INDEX(p_index, size()); - - Write w = write(); - w[p_index] = p_val; -} - -template <class T> -void PoolVector<T>::push_back(const T &p_val) { - - resize(size() + 1); - set(size() - 1, p_val); -} - -template <class T> -T PoolVector<T>::operator[](int p_index) const { - - CRASH_BAD_INDEX(p_index, size()); - - Read r = read(); - return r[p_index]; -} - -template <class T> -Error PoolVector<T>::resize(int p_size) { - - ERR_FAIL_COND_V_MSG(p_size < 0, ERR_INVALID_PARAMETER, "Size of PoolVector cannot be negative."); - - if (alloc == NULL) { - - if (p_size == 0) - return OK; //nothing to do here - - //must allocate something - MemoryPool::alloc_mutex->lock(); - if (MemoryPool::allocs_used == MemoryPool::alloc_count) { - MemoryPool::alloc_mutex->unlock(); - ERR_FAIL_V_MSG(ERR_OUT_OF_MEMORY, "All memory pool allocations are in use."); - } - - //take one from the free list - alloc = MemoryPool::free_list; - MemoryPool::free_list = alloc->free_list; - //increment the used counter - MemoryPool::allocs_used++; - - //cleanup the alloc - alloc->size = 0; - alloc->refcount.init(); - alloc->pool_id = POOL_ALLOCATOR_INVALID_ID; - MemoryPool::alloc_mutex->unlock(); - - } else { - - ERR_FAIL_COND_V_MSG(alloc->lock > 0, ERR_LOCKED, "Can't resize PoolVector if locked."); //can't resize if locked! - } - - size_t new_size = sizeof(T) * p_size; - - if (alloc->size == new_size) - return OK; //nothing to do - - if (p_size == 0) { - _unreference(); - return OK; - } - - _copy_on_write(); // make it unique - -#ifdef DEBUG_ENABLED - MemoryPool::alloc_mutex->lock(); - MemoryPool::total_memory -= alloc->size; - MemoryPool::total_memory += new_size; - if (MemoryPool::total_memory > MemoryPool::max_memory) { - MemoryPool::max_memory = MemoryPool::total_memory; - } - MemoryPool::alloc_mutex->unlock(); -#endif - - int cur_elements = alloc->size / sizeof(T); - - if (p_size > cur_elements) { - - if (MemoryPool::memory_pool) { - //resize memory pool - //if none, create - //if some resize - } else { - - if (alloc->size == 0) { - alloc->mem = memalloc(new_size); - } else { - alloc->mem = memrealloc(alloc->mem, new_size); - } - } - - alloc->size = new_size; - - Write w = write(); - - for (int i = cur_elements; i < p_size; i++) { - - memnew_placement(&w[i], T); - } - - } else { - - { - Write w = write(); - for (int i = p_size; i < cur_elements; i++) { - - w[i].~T(); - } - } - - if (MemoryPool::memory_pool) { - //resize memory pool - //if none, create - //if some resize - } else { - - if (new_size == 0) { - memfree(alloc->mem); - alloc->mem = NULL; - alloc->size = 0; - - MemoryPool::alloc_mutex->lock(); - alloc->free_list = MemoryPool::free_list; - MemoryPool::free_list = alloc; - MemoryPool::allocs_used--; - MemoryPool::alloc_mutex->unlock(); - - } else { - alloc->mem = memrealloc(alloc->mem, new_size); - alloc->size = new_size; - } - } - } - - return OK; -} - -template <class T> -void PoolVector<T>::invert() { - T temp; - Write w = write(); - int s = size(); - int half_s = s / 2; - - for (int i = 0; i < half_s; i++) { - temp = w[i]; - w[i] = w[s - i - 1]; - w[s - i - 1] = temp; - } -} - -#endif // POOL_VECTOR_H diff --git a/core/project_settings.cpp b/core/project_settings.cpp index a01a8a35c6..90487bda0d 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -206,7 +206,7 @@ bool ProjectSettings::_get(const StringName &p_name, Variant &r_ret) const { name = feature_overrides[name]; } if (!props.has(name)) { - WARN_PRINTS("Property not found: " + String(name)); + WARN_PRINT("Property not found: " + String(name)); return false; } r_ret = props[name].variant; @@ -579,7 +579,7 @@ Error ProjectSettings::_load_settings_text(const String &p_path) { _convert_to_last_version(config_version); return OK; } else if (err != OK) { - ERR_PRINTS("Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted."); + ERR_PRINT("Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted."); memdelete(f); return err; } @@ -612,7 +612,7 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path, return OK; } else if (err_text != ERR_FILE_NOT_FOUND) { // If the text-based file exists but can't be loaded, we want to know it - ERR_PRINTS("Couldn't load file '" + p_text_path + "', error code " + itos(err_text) + "."); + ERR_PRINT("Couldn't load file '" + p_text_path + "', error code " + itos(err_text) + "."); return err_text; } @@ -1023,14 +1023,14 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("audio/default_bus_layout", "res://default_bus_layout.tres"); custom_prop_info["audio/default_bus_layout"] = PropertyInfo(Variant::STRING, "audio/default_bus_layout", PROPERTY_HINT_FILE, "*.tres"); - PoolStringArray extensions = PoolStringArray(); + PackedStringArray extensions = PackedStringArray(); extensions.push_back("gd"); if (Engine::get_singleton()->has_singleton("GodotSharp")) extensions.push_back("cs"); extensions.push_back("shader"); GLOBAL_DEF("editor/search_in_file_extensions", extensions); - custom_prop_info["editor/search_in_file_extensions"] = PropertyInfo(Variant::POOL_STRING_ARRAY, "editor/search_in_file_extensions"); + custom_prop_info["editor/search_in_file_extensions"] = PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/search_in_file_extensions"); GLOBAL_DEF("editor/script_templates_search_path", "res://script_templates"); custom_prop_info["editor/script_templates_search_path"] = PropertyInfo(Variant::STRING, "editor/script_templates_search_path", PROPERTY_HINT_DIR); diff --git a/core/reference.cpp b/core/reference.cpp index b24b2a3ec0..dd65ccce69 100644 --- a/core/reference.cpp +++ b/core/reference.cpp @@ -102,7 +102,8 @@ bool Reference::unreference() { return die; } -Reference::Reference() { +Reference::Reference() : + Object(true) { refcount.init(); refcount_init.init(); @@ -113,7 +114,7 @@ Reference::~Reference() { Variant WeakRef::get_ref() const { - if (ref == 0) + if (ref.is_null()) return Variant(); Object *obj = ObjectDB::get_instance(ref); @@ -129,16 +130,15 @@ Variant WeakRef::get_ref() const { } void WeakRef::set_obj(Object *p_object) { - ref = p_object ? p_object->get_instance_id() : 0; + ref = p_object ? p_object->get_instance_id() : ObjectID(); } void WeakRef::set_ref(const REF &p_ref) { - ref = p_ref.is_valid() ? p_ref->get_instance_id() : 0; + ref = p_ref.is_valid() ? p_ref->get_instance_id() : ObjectID(); } -WeakRef::WeakRef() : - ref(0) { +WeakRef::WeakRef() { } void WeakRef::_bind_methods() { diff --git a/core/reference.h b/core/reference.h index d2314005b9..b01e0035a7 100644 --- a/core/reference.h +++ b/core/reference.h @@ -33,7 +33,6 @@ #include "core/class_db.h" #include "core/object.h" -#include "core/ref_ptr.h" #include "core/safe_refcount.h" class Reference : public Object { @@ -133,17 +132,9 @@ public: return reference; } - RefPtr get_ref_ptr() const { - - RefPtr refptr; - Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data()); - *irr = *this; - return refptr; - }; - operator Variant() const { - return Variant(get_ref_ptr()); + return Variant(reference); } void operator=(const Ref &p_from) { @@ -165,33 +156,24 @@ public: r.reference = NULL; } - void operator=(const RefPtr &p_refptr) { + void operator=(const Variant &p_variant) { - Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data()); - Reference *refb = irr->ptr(); - if (!refb) { - unref(); + Object *object = p_variant.get_validated_object(); + + if (object == reference) { return; } - Ref r; - r.reference = Object::cast_to<T>(refb); - ref(r); - r.reference = NULL; - } - void operator=(const Variant &p_variant) { + unref(); - RefPtr refptr = p_variant; - Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data()); - Reference *refb = irr->ptr(); - if (!refb) { - unref(); + if (!object) { return; } - Ref r; - r.reference = Object::cast_to<T>(refb); - ref(r); - r.reference = NULL; + + Reference *r = Object::cast_to<Reference>(object); + if (r && r->reference()) { + reference = static_cast<T *>(r); + } } template <class T_Other> @@ -237,33 +219,19 @@ public: Ref(const Variant &p_variant) { - RefPtr refptr = p_variant; - Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data()); - reference = NULL; - Reference *refb = irr->ptr(); - if (!refb) { - unref(); + Object *object = p_variant.get_validated_object(); + + if (!object) { + reference = nullptr; return; } - Ref r; - r.reference = Object::cast_to<T>(refb); - ref(r); - r.reference = NULL; - } - - Ref(const RefPtr &p_refptr) { - Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data()); - reference = NULL; - Reference *refb = irr->ptr(); - if (!refb) { - unref(); - return; + Reference *r = Object::cast_to<Reference>(object); + if (r && r->reference()) { + reference = static_cast<T *>(r); + } else { + reference = nullptr; } - Ref r; - r.reference = Object::cast_to<T>(refb); - ref(r); - r.reference = NULL; } inline bool is_valid() const { return reference != NULL; } @@ -340,32 +308,6 @@ struct PtrToArg<const Ref<T> &> { } }; -//this is for RefPtr - -template <> -struct PtrToArg<RefPtr> { - - _FORCE_INLINE_ static RefPtr convert(const void *p_ptr) { - - return Ref<Reference>(const_cast<Reference *>(reinterpret_cast<const Reference *>(p_ptr))).get_ref_ptr(); - } - - _FORCE_INLINE_ static void encode(RefPtr p_val, const void *p_ptr) { - - Ref<Reference> r = p_val; - *(Ref<Reference> *)p_ptr = r; - } -}; - -template <> -struct PtrToArg<const RefPtr &> { - - _FORCE_INLINE_ static RefPtr convert(const void *p_ptr) { - - return Ref<Reference>(const_cast<Reference *>(reinterpret_cast<const Reference *>(p_ptr))).get_ref_ptr(); - } -}; - #endif // PTRCALL_ENABLED #ifdef DEBUG_METHODS_ENABLED diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 91d9289563..45b600a23d 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -40,12 +40,14 @@ #include "core/func_ref.h" #include "core/input_map.h" #include "core/io/config_file.h" +#include "core/io/dtls_server.h" #include "core/io/http_client.h" #include "core/io/image_loader.h" #include "core/io/marshalls.h" #include "core/io/multiplayer_api.h" #include "core/io/networked_multiplayer_peer.h" #include "core/io/packet_peer.h" +#include "core/io/packet_peer_dtls.h" #include "core/io/packet_peer_udp.h" #include "core/io/pck_packer.h" #include "core/io/resource_format_binary.h" @@ -53,6 +55,7 @@ #include "core/io/stream_peer_ssl.h" #include "core/io/tcp_server.h" #include "core/io/translation_loader_po.h" +#include "core/io/udp_server.h" #include "core/io/xml_parser.h" #include "core/math/a_star.h" #include "core/math/expression.h" @@ -98,7 +101,6 @@ void register_core_types() { ObjectDB::setup(); ResourceCache::setup(); - MemoryPool::setup(); _global_mutex = Mutex::create(); @@ -155,6 +157,9 @@ void register_core_types() { ClassDB::register_class<StreamPeerTCP>(); ClassDB::register_class<TCP_Server>(); ClassDB::register_class<PacketPeerUDP>(); + ClassDB::register_class<UDPServer>(); + ClassDB::register_custom_instance_class<PacketPeerDTLS>(); + ClassDB::register_custom_instance_class<DTLSServer>(); // Crypto ClassDB::register_class<HashingContext>(); @@ -316,6 +321,4 @@ void unregister_core_types() { memdelete(_global_mutex); _global_mutex = NULL; //still needed at a few places }; - - MemoryPool::cleanup(); } diff --git a/core/resource.h b/core/resource.h index 00d330a094..b30788010b 100644 --- a/core/resource.h +++ b/core/resource.h @@ -33,7 +33,6 @@ #include "core/class_db.h" #include "core/object.h" -#include "core/ref_ptr.h" #include "core/reference.h" #include "core/safe_refcount.h" #include "core/self_list.h" diff --git a/core/rid.h b/core/rid.h index 7e12409181..0c4a96efed 100644 --- a/core/rid.h +++ b/core/rid.h @@ -32,172 +32,46 @@ #define RID_H #include "core/list.h" +#include "core/oa_hash_map.h" #include "core/os/memory.h" #include "core/safe_refcount.h" #include "core/set.h" #include "core/typedefs.h" -class RID_OwnerBase; - -class RID_Data { - - friend class RID_OwnerBase; - -#ifndef DEBUG_ENABLED - RID_OwnerBase *_owner; -#endif - uint32_t _id; - -public: - _FORCE_INLINE_ uint32_t get_id() const { return _id; } - - virtual ~RID_Data(); -}; +class RID_AllocBase; class RID { - friend class RID_OwnerBase; - - mutable RID_Data *_data; + friend class RID_AllocBase; + uint64_t _id; public: - _FORCE_INLINE_ RID_Data *get_data() const { return _data; } - _FORCE_INLINE_ bool operator==(const RID &p_rid) const { - return _data == p_rid._data; + return _id == p_rid._id; } _FORCE_INLINE_ bool operator<(const RID &p_rid) const { - return _data < p_rid._data; + return _id < p_rid._id; } _FORCE_INLINE_ bool operator<=(const RID &p_rid) const { - return _data <= p_rid._data; + return _id <= p_rid._id; } _FORCE_INLINE_ bool operator>(const RID &p_rid) const { - return _data > p_rid._data; + return _id > p_rid._id; } _FORCE_INLINE_ bool operator!=(const RID &p_rid) const { - return _data != p_rid._data; + return _id != p_rid._id; } - _FORCE_INLINE_ bool is_valid() const { return _data != NULL; } + _FORCE_INLINE_ bool is_valid() const { return _id != 0; } + _FORCE_INLINE_ bool is_null() const { return _id == 0; } - _FORCE_INLINE_ uint32_t get_id() const { return _data ? _data->get_id() : 0; } + _FORCE_INLINE_ uint64_t get_id() const { return _id; } _FORCE_INLINE_ RID() { - _data = NULL; - } -}; - -class RID_OwnerBase { -protected: - static SafeRefCount refcount; - _FORCE_INLINE_ void _set_data(RID &p_rid, RID_Data *p_data) { - p_rid._data = p_data; - refcount.ref(); - p_data->_id = refcount.get(); -#ifndef DEBUG_ENABLED - p_data->_owner = this; -#endif - } - -#ifndef DEBUG_ENABLED - - _FORCE_INLINE_ bool _is_owner(const RID &p_rid) const { - - return this == p_rid._data->_owner; - } - - _FORCE_INLINE_ void _remove_owner(RID &p_rid) { - - p_rid._data->_owner = NULL; - } -#endif - -public: - virtual void get_owned_list(List<RID> *p_owned) = 0; - - static void init_rid(); - virtual ~RID_OwnerBase() {} -}; - -template <class T> -class RID_Owner : public RID_OwnerBase { -public: -#ifdef DEBUG_ENABLED - mutable Set<RID_Data *> id_map; -#endif -public: - _FORCE_INLINE_ RID make_rid(T *p_data) { - - RID rid; - _set_data(rid, p_data); - -#ifdef DEBUG_ENABLED - id_map.insert(p_data); -#endif - - return rid; - } - - _FORCE_INLINE_ T *get(const RID &p_rid) { - -#ifdef DEBUG_ENABLED - - ERR_FAIL_COND_V(!p_rid.is_valid(), NULL); - ERR_FAIL_COND_V(!id_map.has(p_rid.get_data()), NULL); -#endif - return static_cast<T *>(p_rid.get_data()); - } - - _FORCE_INLINE_ T *getornull(const RID &p_rid) { - -#ifdef DEBUG_ENABLED - - if (p_rid.get_data()) { - ERR_FAIL_COND_V(!id_map.has(p_rid.get_data()), NULL); - } -#endif - return static_cast<T *>(p_rid.get_data()); - } - - _FORCE_INLINE_ T *getptr(const RID &p_rid) { - - return static_cast<T *>(p_rid.get_data()); - } - - _FORCE_INLINE_ bool owns(const RID &p_rid) const { - - if (p_rid.get_data() == NULL) - return false; -#ifdef DEBUG_ENABLED - return id_map.has(p_rid.get_data()); -#else - return _is_owner(p_rid); -#endif - } - - void free(RID p_rid) { - -#ifdef DEBUG_ENABLED - id_map.erase(p_rid.get_data()); -#else - _remove_owner(p_rid); -#endif - } - - void get_owned_list(List<RID> *p_owned) { - -#ifdef DEBUG_ENABLED - - for (typename Set<RID_Data *>::Element *E = id_map.front(); E; E = E->next()) { - RID r; - _set_data(r, static_cast<T *>(E->get())); - p_owned->push_back(r); - } -#endif + _id = 0; } }; diff --git a/core/rid.cpp b/core/rid_owner.cpp index 727658314f..a5065f29f8 100644 --- a/core/rid.cpp +++ b/core/rid_owner.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* rid.cpp */ +/* rid_owner.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,14 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rid.h" +#include "rid_owner.h" -RID_Data::~RID_Data() { -} - -SafeRefCount RID_OwnerBase::refcount; - -void RID_OwnerBase::init_rid() { - - refcount.init(); -} +volatile uint64_t RID_AllocBase::base_id = 1; diff --git a/core/rid_owner.h b/core/rid_owner.h new file mode 100644 index 0000000000..bd01eba17d --- /dev/null +++ b/core/rid_owner.h @@ -0,0 +1,406 @@ +/*************************************************************************/ +/* rid_owner.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 RID_OWNER_H +#define RID_OWNER_H + +#include "core/print_string.h" +#include "core/rid.h" +#include "core/spin_lock.h" +#include <stdio.h> +#include <typeinfo> + +class RID_AllocBase { + + static volatile uint64_t base_id; + +protected: + static RID _make_from_id(uint64_t p_id) { + RID rid; + rid._id = p_id; + return rid; + } + + static uint64_t _gen_id() { + return atomic_increment(&base_id); + } + + static RID _gen_rid() { + return _make_from_id(_gen_id()); + } + +public: + virtual ~RID_AllocBase() {} +}; + +template <class T, bool THREAD_SAFE = false> +class RID_Alloc : public RID_AllocBase { + + T **chunks; + uint32_t **free_list_chunks; + uint32_t **validator_chunks; + + uint32_t elements_in_chunk; + uint32_t max_alloc; + uint32_t alloc_count; + + const char *description; + + SpinLock spin_lock; + +public: + RID make_rid(const T &p_value) { + + if (THREAD_SAFE) { + spin_lock.lock(); + } + + if (alloc_count == max_alloc) { + //allocate a new chunk + uint32_t chunk_count = alloc_count == 0 ? 0 : (max_alloc / elements_in_chunk); + + //grow chunks + chunks = (T **)memrealloc(chunks, sizeof(T *) * (chunk_count + 1)); + chunks[chunk_count] = (T *)memalloc(sizeof(T) * elements_in_chunk); //but don't initialize + + //grow validators + validator_chunks = (uint32_t **)memrealloc(validator_chunks, sizeof(uint32_t *) * (chunk_count + 1)); + validator_chunks[chunk_count] = (uint32_t *)memalloc(sizeof(uint32_t) * elements_in_chunk); + //grow free lists + free_list_chunks = (uint32_t **)memrealloc(free_list_chunks, sizeof(uint32_t *) * (chunk_count + 1)); + free_list_chunks[chunk_count] = (uint32_t *)memalloc(sizeof(uint32_t) * elements_in_chunk); + + //initialize + for (uint32_t i = 0; i < elements_in_chunk; i++) { + //dont initialize chunk + validator_chunks[chunk_count][i] = 0xFFFFFFFF; + free_list_chunks[chunk_count][i] = alloc_count + i; + } + + max_alloc += elements_in_chunk; + } + + uint32_t free_index = free_list_chunks[alloc_count / elements_in_chunk][alloc_count % elements_in_chunk]; + + uint32_t free_chunk = free_index / elements_in_chunk; + uint32_t free_element = free_index % elements_in_chunk; + + T *ptr = &chunks[free_chunk][free_element]; + memnew_placement(ptr, T(p_value)); + + uint32_t validator = (uint32_t)(_gen_id() & 0xFFFFFFFF); + uint64_t id = validator; + id <<= 32; + id |= free_index; + + validator_chunks[free_chunk][free_element] = validator; + alloc_count++; + + if (THREAD_SAFE) { + spin_lock.unlock(); + } + + return _make_from_id(id); + } + + _FORCE_INLINE_ T *getornull(const RID &p_rid) { + + if (THREAD_SAFE) { + spin_lock.lock(); + } + + uint64_t id = p_rid.get_id(); + uint32_t idx = uint32_t(id & 0xFFFFFFFF); + if (unlikely(idx >= max_alloc)) { + if (THREAD_SAFE) { + spin_lock.unlock(); + } + return NULL; + } + + uint32_t idx_chunk = idx / elements_in_chunk; + uint32_t idx_element = idx % elements_in_chunk; + + uint32_t validator = uint32_t(id >> 32); + if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) { + if (THREAD_SAFE) { + spin_lock.unlock(); + } + return NULL; + } + + T *ptr = &chunks[idx_chunk][idx_element]; + + if (THREAD_SAFE) { + spin_lock.unlock(); + } + + return ptr; + } + + _FORCE_INLINE_ bool owns(const RID &p_rid) { + + if (THREAD_SAFE) { + spin_lock.lock(); + } + + uint64_t id = p_rid.get_id(); + uint32_t idx = uint32_t(id & 0xFFFFFFFF); + if (unlikely(idx >= max_alloc)) { + if (THREAD_SAFE) { + spin_lock.unlock(); + } + return false; + } + + uint32_t idx_chunk = idx / elements_in_chunk; + uint32_t idx_element = idx % elements_in_chunk; + + uint32_t validator = uint32_t(id >> 32); + + bool owned = validator_chunks[idx_chunk][idx_element] == validator; + + if (THREAD_SAFE) { + spin_lock.unlock(); + } + + return owned; + } + + _FORCE_INLINE_ void free(const RID &p_rid) { + + if (THREAD_SAFE) { + spin_lock.lock(); + } + + uint64_t id = p_rid.get_id(); + uint32_t idx = uint32_t(id & 0xFFFFFFFF); + if (unlikely(idx >= max_alloc)) { + if (THREAD_SAFE) { + spin_lock.unlock(); + } + ERR_FAIL(); + } + + uint32_t idx_chunk = idx / elements_in_chunk; + uint32_t idx_element = idx % elements_in_chunk; + + uint32_t validator = uint32_t(id >> 32); + if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) { + if (THREAD_SAFE) { + spin_lock.unlock(); + } + ERR_FAIL(); + } + + chunks[idx_chunk][idx_element].~T(); + validator_chunks[idx_chunk][idx_element] = 0xFFFFFFFF; // go invalid + + alloc_count--; + free_list_chunks[alloc_count / elements_in_chunk][alloc_count % elements_in_chunk] = idx; + + if (THREAD_SAFE) { + spin_lock.unlock(); + } + } + + _FORCE_INLINE_ uint32_t get_rid_count() const { + return alloc_count; + } + + _FORCE_INLINE_ T *get_ptr_by_index(uint32_t p_index) { + ERR_FAIL_INDEX_V(p_index, alloc_count, NULL); + if (THREAD_SAFE) { + spin_lock.lock(); + } + uint64_t idx = free_list_chunks[p_index / elements_in_chunk][p_index % elements_in_chunk]; + T *ptr = &chunks[idx / elements_in_chunk][idx % elements_in_chunk]; + if (THREAD_SAFE) { + spin_lock.unlock(); + } + return ptr; + } + + _FORCE_INLINE_ RID get_rid_by_index(uint32_t p_index) { + ERR_FAIL_INDEX_V(p_index, alloc_count, RID()); + if (THREAD_SAFE) { + spin_lock.lock(); + } + uint64_t idx = free_list_chunks[p_index / elements_in_chunk][p_index % elements_in_chunk]; + uint64_t validator = validator_chunks[idx / elements_in_chunk][idx % elements_in_chunk]; + + RID rid = _make_from_id((validator << 32) | idx); + if (THREAD_SAFE) { + spin_lock.unlock(); + } + return rid; + } + + void get_owned_list(List<RID> *p_owned) { + if (THREAD_SAFE) { + spin_lock.lock(); + } + for (size_t i = 0; i < max_alloc; i++) { + uint64_t validator = validator_chunks[i / elements_in_chunk][i % elements_in_chunk]; + if (validator != 0xFFFFFFFF) { + p_owned->push_back(_make_from_id((validator << 32) | i)); + } + } + if (THREAD_SAFE) { + spin_lock.unlock(); + } + } + + void set_description(const char *p_descrption) { + description = p_descrption; + } + + RID_Alloc(uint32_t p_target_chunk_byte_size = 4096) { + chunks = NULL; + free_list_chunks = NULL; + validator_chunks = NULL; + + elements_in_chunk = sizeof(T) > p_target_chunk_byte_size ? 1 : (p_target_chunk_byte_size / sizeof(T)); + max_alloc = 0; + alloc_count = 0; + description = NULL; + } + + ~RID_Alloc() { + if (alloc_count) { + if (description) { + print_error("ERROR: " + itos(alloc_count) + " RID allocations of type '" + description + "' were leaked at exit."); + } else { + print_error("ERROR: " + itos(alloc_count) + " RID allocations of type '" + typeid(T).name() + "' were leaked at exit."); + } + + for (size_t i = 0; i < max_alloc; i++) { + uint64_t validator = validator_chunks[i / elements_in_chunk][i % elements_in_chunk]; + if (validator != 0xFFFFFFFF) { + chunks[i / elements_in_chunk][i % elements_in_chunk].~T(); + } + } + } + + uint32_t chunk_count = max_alloc / elements_in_chunk; + for (uint32_t i = 0; i < chunk_count; i++) { + memfree(chunks[i]); + memfree(validator_chunks[i]); + memfree(free_list_chunks[i]); + } + + if (chunks) { + memfree(chunks); + memfree(free_list_chunks); + memfree(validator_chunks); + } + } +}; + +template <class T, bool THREAD_SAFE = false> +class RID_PtrOwner { + RID_Alloc<T *, THREAD_SAFE> alloc; + +public: + _FORCE_INLINE_ RID make_rid(T *p_ptr) { + return alloc.make_rid(p_ptr); + } + + _FORCE_INLINE_ T *getornull(const RID &p_rid) { + T **ptr = alloc.getornull(p_rid); + if (unlikely(!ptr)) { + return NULL; + } + return *ptr; + } + + _FORCE_INLINE_ bool owns(const RID &p_rid) { + return alloc.owns(p_rid); + } + + _FORCE_INLINE_ void free(const RID &p_rid) { + alloc.free(p_rid); + } + + _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) { + return alloc.get_owned_list(p_owned); + } + + void set_description(const char *p_descrption) { + alloc.set_description(p_descrption); + } + RID_PtrOwner(uint32_t p_target_chunk_byte_size = 4096) : + alloc(p_target_chunk_byte_size) {} +}; + +template <class T, bool THREAD_SAFE = false> +class RID_Owner { + RID_Alloc<T, THREAD_SAFE> alloc; + +public: + _FORCE_INLINE_ RID make_rid(const T &p_ptr) { + return alloc.make_rid(p_ptr); + } + + _FORCE_INLINE_ T *getornull(const RID &p_rid) { + return alloc.getornull(p_rid); + } + + _FORCE_INLINE_ bool owns(const RID &p_rid) { + return alloc.owns(p_rid); + } + + _FORCE_INLINE_ void free(const RID &p_rid) { + alloc.free(p_rid); + } + + _FORCE_INLINE_ uint32_t get_rid_count() const { + return alloc.get_rid_count(); + } + + _FORCE_INLINE_ RID get_rid_by_index(uint32_t p_index) { + return alloc.get_rid_by_index(p_index); + } + + _FORCE_INLINE_ T *get_ptr_by_index(uint32_t p_index) { + return alloc.get_ptr_by_index(p_index); + } + + _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) { + return alloc.get_owned_list(p_owned); + } + + void set_description(const char *p_descrption) { + alloc.set_description(p_descrption); + } + RID_Owner(uint32_t p_target_chunk_byte_size = 4096) : + alloc(p_target_chunk_byte_size) {} +}; +#endif // RID_OWNER_H diff --git a/core/script_language.cpp b/core/script_language.cpp index 7392e7a0af..1149feac38 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -32,6 +32,7 @@ #include "core/core_string_names.h" #include "core/project_settings.h" +#include <stdint.h> ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES]; int ScriptServer::_language_count = 0; @@ -644,6 +645,14 @@ Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_nam return Variant(); } +uint16_t PlaceHolderScriptInstance::get_rpc_method_id(const StringName &p_method) const { + return UINT16_MAX; +} + +uint16_t PlaceHolderScriptInstance::get_rset_property_id(const StringName &p_method) const { + return UINT16_MAX; +} + PlaceHolderScriptInstance::PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner) : owner(p_owner), language(p_language), diff --git a/core/script_language.h b/core/script_language.h index 22f83080bc..2209f78fe4 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -40,6 +40,21 @@ class ScriptLanguage; typedef void (*ScriptEditRequestFunction)(const String &p_path); +struct ScriptNetData { + StringName name; + MultiplayerAPI::RPCMode mode; + bool operator==(ScriptNetData const &p_other) const { + return name == p_other.name; + } +}; + +struct SortNetData { + StringName::AlphCompare compare; + bool operator()(const ScriptNetData &p_a, const ScriptNetData &p_b) const { + return compare(p_a.name, p_b.name); + } +}; + class ScriptServer { enum { @@ -154,6 +169,18 @@ public: virtual bool is_placeholder_fallback_enabled() const { return false; } + virtual Vector<ScriptNetData> get_rpc_methods() const = 0; + virtual uint16_t get_rpc_method_id(const StringName &p_method) const = 0; + virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const = 0; + + virtual Vector<ScriptNetData> get_rset_properties() const = 0; + virtual uint16_t get_rset_property_id(const StringName &p_property) const = 0; + virtual StringName get_rset_property(const uint16_t p_rset_property_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const = 0; + Script() {} }; @@ -195,7 +222,16 @@ public: virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid); virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid); + virtual Vector<ScriptNetData> get_rpc_methods() const = 0; + virtual uint16_t get_rpc_method_id(const StringName &p_method) const = 0; + virtual StringName get_rpc_method(uint16_t p_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const = 0; virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const = 0; + + virtual Vector<ScriptNetData> get_rset_properties() const = 0; + virtual uint16_t get_rset_property_id(const StringName &p_variable) const = 0; + virtual StringName get_rset_property(uint16_t p_id) const = 0; + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const = 0; virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const = 0; virtual ScriptLanguage *get_language() = 0; @@ -277,7 +313,7 @@ public: virtual bool supports_builtin_mode() const = 0; virtual bool can_inherit_from_file() { return false; } virtual int find_function(const String &p_function, const String &p_code) const = 0; - virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const = 0; + virtual String make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const = 0; virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; } virtual bool overrides_external_editor() { return false; } @@ -409,7 +445,16 @@ public: virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid = NULL); virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid = NULL); + virtual Vector<ScriptNetData> get_rpc_methods() const { return Vector<ScriptNetData>(); } + virtual uint16_t get_rpc_method_id(const StringName &p_method) const; + virtual StringName get_rpc_method(uint16_t p_id) const { return StringName(); } + virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const { return MultiplayerAPI::RPC_MODE_DISABLED; } virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const { return MultiplayerAPI::RPC_MODE_DISABLED; } + + virtual Vector<ScriptNetData> get_rset_properties() const { return Vector<ScriptNetData>(); } + virtual uint16_t get_rset_property_id(const StringName &p_variable) const; + virtual StringName get_rset_property(uint16_t p_id) const { return StringName(); } + virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const { return MultiplayerAPI::RPC_MODE_DISABLED; } virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const { return MultiplayerAPI::RPC_MODE_DISABLED; } PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner); diff --git a/core/ref_ptr.h b/core/spin_lock.h index 4736106b4f..c48631f94a 100644 --- a/core/ref_ptr.h +++ b/core/spin_lock.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ref_ptr.h */ +/* spin_lock.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,35 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef REF_PTR_H -#define REF_PTR_H -/** - @author Juan Linietsky <reduzio@gmail.com> - * This class exists to workaround a limitation in C++ but keep the design OK. - * It's basically an opaque container of a Reference reference, so Variant can use it. -*/ +#ifndef SPIN_LOCK_H +#define SPIN_LOCK_H -#include "core/rid.h" +#include "core/typedefs.h" +#include <atomic> -class RefPtr { +class SpinLock { + std::atomic_flag locked = ATOMIC_FLAG_INIT; - enum { - - DATASIZE = sizeof(void *) //*4 -ref was shrunk - }; - - mutable char data[DATASIZE]; // too much probably, virtual class + pointer public: - bool is_null() const; - void operator=(const RefPtr &p_other); - bool operator==(const RefPtr &p_other) const; - bool operator!=(const RefPtr &p_other) const; - RID get_rid() const; - void unref(); - _FORCE_INLINE_ void *get_data() const { return data; } - RefPtr(const RefPtr &p_other); - RefPtr(); - ~RefPtr(); + _ALWAYS_INLINE_ void lock() { + while (locked.test_and_set(std::memory_order_acquire)) { + ; + } + } + _ALWAYS_INLINE_ void unlock() { + locked.clear(std::memory_order_release); + } }; - -#endif // REF_PTR_H +#endif // SPIN_LOCK_H diff --git a/core/ref_ptr.cpp b/core/thread_work_pool.cpp index 7e35bcc56c..c8311f102f 100644 --- a/core/ref_ptr.cpp +++ b/core/thread_work_pool.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ref_ptr.cpp */ +/* thread_work_pool.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,76 +28,56 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "ref_ptr.h" +#include "thread_work_pool.h" +#include "core/os/os.h" -#include "core/reference.h" -#include "core/resource.h" +void ThreadWorkPool::_thread_function(ThreadData *p_thread) { -void RefPtr::operator=(const RefPtr &p_other) { - - Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]); - Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0])); - - *ref = *ref_other; -} - -bool RefPtr::operator==(const RefPtr &p_other) const { - - Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]); - Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0])); - - return *ref == *ref_other; -} - -bool RefPtr::operator!=(const RefPtr &p_other) const { - - Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]); - Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0])); - - return *ref != *ref_other; + while (true) { + p_thread->start.wait(); + if (p_thread->exit.load()) { + break; + } + p_thread->work->work(); + p_thread->completed.post(); + } } -RefPtr::RefPtr(const RefPtr &p_other) { - - memnew_placement(&data[0], Ref<Reference>); - - Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]); - Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0])); - - *ref = *ref_other; -} +void ThreadWorkPool::init(int p_thread_count) { + ERR_FAIL_COND(threads != nullptr); + if (p_thread_count < 0) { + p_thread_count = OS::get_singleton()->get_processor_count(); + } -bool RefPtr::is_null() const { + thread_count = p_thread_count; + threads = memnew_arr(ThreadData, thread_count); - Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]); - return ref->is_null(); + for (uint32_t i = 0; i < thread_count; i++) { + threads[i].exit.store(false); + threads[i].thread = memnew(std::thread(ThreadWorkPool::_thread_function, &threads[i])); + } } -RID RefPtr::get_rid() const { +void ThreadWorkPool::finish() { - Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]); - if (ref->is_null()) - return RID(); - Resource *res = Object::cast_to<Resource>(ref->ptr()); - if (res) - return res->get_rid(); - return RID(); -} - -void RefPtr::unref() { - - Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]); - ref->unref(); -} + if (threads == nullptr) { + return; + } -RefPtr::RefPtr() { + for (uint32_t i = 0; i < thread_count; i++) { + threads[i].exit.store(true); + threads[i].start.post(); + } + for (uint32_t i = 0; i < thread_count; i++) { + threads[i].thread->join(); + memdelete(threads[i].thread); + } - ERR_FAIL_COND(sizeof(Ref<Reference>) > DATASIZE); - memnew_placement(&data[0], Ref<Reference>); + memdelete_arr(threads); + threads = nullptr; } -RefPtr::~RefPtr() { +ThreadWorkPool::~ThreadWorkPool() { - Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]); - ref->~Ref<Reference>(); + finish(); } diff --git a/core/thread_work_pool.h b/core/thread_work_pool.h new file mode 100644 index 0000000000..214d2c4aa7 --- /dev/null +++ b/core/thread_work_pool.h @@ -0,0 +1,111 @@ +/*************************************************************************/ +/* thread_work_pool.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 THREAD_WORK_POOL_H +#define THREAD_WORK_POOL_H + +#include "core/os/memory.h" +#include "core/os/semaphore.h" +#include <atomic> +#include <thread> +class ThreadWorkPool { + + std::atomic<uint32_t> index; + + struct BaseWork { + std::atomic<uint32_t> *index; + uint32_t max_elements; + virtual void work() = 0; + virtual ~BaseWork() = default; + }; + + template <class C, class M, class U> + struct Work : public BaseWork { + C *instance; + M method; + U userdata; + virtual void work() { + + while (true) { + uint32_t work_index = index->fetch_add(1, std::memory_order_relaxed); + if (work_index >= max_elements) { + break; + } + (instance->*method)(work_index, userdata); + } + } + }; + + struct ThreadData { + std::thread *thread; + Semaphore start; + Semaphore completed; + std::atomic<bool> exit; + BaseWork *work; + }; + + ThreadData *threads = nullptr; + uint32_t thread_count = 0; + + static void _thread_function(ThreadData *p_thread); + +public: + template <class C, class M, class U> + void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { + + ERR_FAIL_COND(!threads); //never initialized + + index.store(0); + + Work<C, M, U> *w = memnew((Work<C, M, U>)); + w->instance = p_instance; + w->userdata = p_userdata; + w->method = p_method; + w->index = &index; + w->max_elements = p_elements; + + for (uint32_t i = 0; i < thread_count; i++) { + threads[i].work = w; + threads[i].start.post(); + } + for (uint32_t i = 0; i < thread_count; i++) { + threads[i].completed.wait(); + threads[i].work = nullptr; + } + + memdelete(w); + } + + void init(int p_thread_count = -1); + void finish(); + ~ThreadWorkPool(); +}; + +#endif // THREAD_POOL_H diff --git a/core/translation.cpp b/core/translation.cpp index 02297cffc8..17c23b86cd 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -794,9 +794,9 @@ static const char *locale_renames[][2] = { /////////////////////////////////////////////// -PoolVector<String> Translation::_get_messages() const { +Vector<String> Translation::_get_messages() const { - PoolVector<String> msgs; + Vector<String> msgs; msgs.resize(translation_map.size() * 2); int idx = 0; for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) { @@ -809,9 +809,9 @@ PoolVector<String> Translation::_get_messages() const { return msgs; } -PoolVector<String> Translation::_get_message_list() const { +Vector<String> Translation::_get_message_list() const { - PoolVector<String> msgs; + Vector<String> msgs; msgs.resize(translation_map.size()); int idx = 0; for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) { @@ -823,12 +823,12 @@ PoolVector<String> Translation::_get_message_list() const { return msgs; } -void Translation::_set_messages(const PoolVector<String> &p_messages) { +void Translation::_set_messages(const Vector<String> &p_messages) { int msg_count = p_messages.size(); ERR_FAIL_COND(msg_count % 2); - PoolVector<String>::Read r = p_messages.read(); + const String *r = p_messages.ptr(); for (int i = 0; i < msg_count; i += 2) { @@ -898,7 +898,7 @@ void Translation::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_messages"), &Translation::_set_messages); ClassDB::bind_method(D_METHOD("_get_messages"), &Translation::_get_messages); - ADD_PROPERTY(PropertyInfo(Variant::POOL_STRING_ARRAY, "messages", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_messages", "_get_messages"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "messages", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_messages", "_get_messages"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "locale"), "set_locale", "get_locale"); } @@ -966,7 +966,7 @@ void TranslationServer::set_locale(const String &p_locale) { print_verbose(vformat("Unsupported locale '%s', falling back to '%s'.", p_locale, trimmed_locale)); if (!is_locale_valid(trimmed_locale)) { - ERR_PRINTS(vformat("Unsupported locale '%s', falling back to 'en'.", trimmed_locale)); + ERR_PRINT(vformat("Unsupported locale '%s', falling back to 'en'.", trimmed_locale)); locale = "en"; } else { locale = trimmed_locale; @@ -1146,12 +1146,12 @@ TranslationServer *TranslationServer::singleton = NULL; bool TranslationServer::_load_translations(const String &p_from) { if (ProjectSettings::get_singleton()->has_setting(p_from)) { - PoolVector<String> translations = ProjectSettings::get_singleton()->get(p_from); + Vector<String> translations = ProjectSettings::get_singleton()->get(p_from); int tcount = translations.size(); if (tcount) { - PoolVector<String>::Read r = translations.read(); + const String *r = translations.ptr(); for (int i = 0; i < tcount; i++) { diff --git a/core/translation.h b/core/translation.h index 8f56b7271d..0448ea56c5 100644 --- a/core/translation.h +++ b/core/translation.h @@ -42,10 +42,10 @@ class Translation : public Resource { String locale; Map<StringName, StringName> translation_map; - PoolVector<String> _get_message_list() const; + Vector<String> _get_message_list() const; - PoolVector<String> _get_messages() const; - void _set_messages(const PoolVector<String> &p_messages); + Vector<String> _get_messages() const; + void _set_messages(const Vector<String> &p_messages); protected: static void _bind_methods(); diff --git a/core/type_info.h b/core/type_info.h index c9b2055241..379735fd67 100644 --- a/core/type_info.h +++ b/core/type_info.h @@ -155,35 +155,24 @@ MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH) MAKE_TYPE_INFO(RID, Variant::_RID) MAKE_TYPE_INFO(Dictionary, Variant::DICTIONARY) MAKE_TYPE_INFO(Array, Variant::ARRAY) -MAKE_TYPE_INFO(PoolByteArray, Variant::POOL_BYTE_ARRAY) -MAKE_TYPE_INFO(PoolIntArray, Variant::POOL_INT_ARRAY) -MAKE_TYPE_INFO(PoolRealArray, Variant::POOL_REAL_ARRAY) -MAKE_TYPE_INFO(PoolStringArray, Variant::POOL_STRING_ARRAY) -MAKE_TYPE_INFO(PoolVector2Array, Variant::POOL_VECTOR2_ARRAY) -MAKE_TYPE_INFO(PoolVector3Array, Variant::POOL_VECTOR3_ARRAY) -MAKE_TYPE_INFO(PoolColorArray, Variant::POOL_COLOR_ARRAY) +MAKE_TYPE_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY) +MAKE_TYPE_INFO(PackedIntArray, Variant::PACKED_INT_ARRAY) +MAKE_TYPE_INFO(PackedRealArray, Variant::PACKED_REAL_ARRAY) +MAKE_TYPE_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY) +MAKE_TYPE_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) +MAKE_TYPE_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) +MAKE_TYPE_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY) MAKE_TYPE_INFO(StringName, Variant::STRING) MAKE_TYPE_INFO(IP_Address, Variant::STRING) -class BSP_Tree; -MAKE_TYPE_INFO(BSP_Tree, Variant::DICTIONARY) - -//for RefPtr -template <> -struct GetTypeInfo<RefPtr> { - static const Variant::Type VARIANT_TYPE = Variant::OBJECT; - static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; - static inline PropertyInfo get_class_info() { - return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference"); - } -}; +//objectID template <> -struct GetTypeInfo<const RefPtr &> { - static const Variant::Type VARIANT_TYPE = Variant::OBJECT; +struct GetTypeInfo<ObjectID> { + static const Variant::Type VARIANT_TYPE = Variant::INT; static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; static inline PropertyInfo get_class_info() { - return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference"); + return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_OBJECTID); } }; @@ -224,21 +213,25 @@ struct GetTypeInfo<const Variant &> { } \ }; -MAKE_TEMPLATE_TYPE_INFO(Vector, uint8_t, Variant::POOL_BYTE_ARRAY) -MAKE_TEMPLATE_TYPE_INFO(Vector, int, Variant::POOL_INT_ARRAY) -MAKE_TEMPLATE_TYPE_INFO(Vector, float, Variant::POOL_REAL_ARRAY) -MAKE_TEMPLATE_TYPE_INFO(Vector, String, Variant::POOL_STRING_ARRAY) -MAKE_TEMPLATE_TYPE_INFO(Vector, Vector2, Variant::POOL_VECTOR2_ARRAY) -MAKE_TEMPLATE_TYPE_INFO(Vector, Vector3, Variant::POOL_VECTOR3_ARRAY) -MAKE_TEMPLATE_TYPE_INFO(Vector, Color, Variant::POOL_COLOR_ARRAY) - MAKE_TEMPLATE_TYPE_INFO(Vector, Variant, Variant::ARRAY) MAKE_TEMPLATE_TYPE_INFO(Vector, RID, Variant::ARRAY) MAKE_TEMPLATE_TYPE_INFO(Vector, Plane, Variant::ARRAY) -MAKE_TEMPLATE_TYPE_INFO(Vector, StringName, Variant::POOL_STRING_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, Face3, Variant::PACKED_VECTOR3_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, StringName, Variant::PACKED_STRING_ARRAY) -MAKE_TEMPLATE_TYPE_INFO(PoolVector, Plane, Variant::ARRAY) -MAKE_TEMPLATE_TYPE_INFO(PoolVector, Face3, Variant::POOL_VECTOR3_ARRAY) +/* +MAKE_TEMPLATE_TYPE_INFO(Vector, uint8_t, Variant::PACKED_BYTE_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, int, Variant::PACKED_INT_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, float, Variant::PACKED_REAL_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, String, Variant::PACKED_STRING_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, Vector2, Variant::PACKED_VECTOR2_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, Vector3, Variant::PACKED_VECTOR3_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, Color, Variant::PACKED_COLOR_ARRAY) + + +MAKE_TEMPLATE_TYPE_INFO(Vector, Plane, Variant::ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, Face3, Variant::PACKED_VECTOR3_ARRAY) +*/ template <typename T> struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> { @@ -277,7 +270,7 @@ struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>: template <typename T> inline StringName __constant_get_enum_name(T param, const String &p_constant) { if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) - ERR_PRINTS("Missing VARIANT_ENUM_CAST for constant's enum: " + p_constant); + ERR_PRINT("Missing VARIANT_ENUM_CAST for constant's enum: " + p_constant); return GetTypeInfo<T>::get_class_info().class_name; } diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 5d1144e1f5..577879d448 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -293,7 +293,7 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) { Variant::CallError ce; obj->call(op.name, (const Variant **)argptrs.ptr(), argc, ce); if (ce.error != Variant::CallError::CALL_OK) { - ERR_PRINTS("Error calling method from signal '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, (const Variant **)argptrs.ptr(), argc, ce)); + ERR_PRINT("Error calling method from signal '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, (const Variant **)argptrs.ptr(), argc, ce)); } #ifdef TOOLS_ENABLED Resource *res = Object::cast_to<Resource>(obj); diff --git a/core/ustring.cpp b/core/ustring.cpp index 8a1fbfd383..c4543b89da 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -146,9 +146,11 @@ void CharString::copy_from(const char *p_cstr) { return; } - resize(len + 1); // include terminating null char + Error err = resize(++len); // include terminating null char - strcpy(ptrw(), p_cstr); + ERR_FAIL_COND_MSG(err != OK, "Failed to copy C-string."); + + memcpy(ptrw(), p_cstr, len); } void String::copy_from(const char *p_cstr) { @@ -644,6 +646,17 @@ String String::camelcase_to_underscore(bool lowercase) const { return lowercase ? new_string.to_lower() : new_string; } +String String::get_with_code_lines() const { + Vector<String> lines = split("\n"); + String ret; + for (int i = 0; i < lines.size(); i++) { + if (i > 0) { + ret += "\n"; + } + ret += itos(i + 1) + " " + lines[i]; + } + return ret; +} int String::get_slice_count(String p_splitter) const { if (empty()) @@ -3324,7 +3337,7 @@ String String::humanize_size(uint64_t p_size) { int prefix_idx = 0; - while (prefix_idx < prefixes.size() && p_size > (_div * 1024)) { + while (prefix_idx < prefixes.size() - 1 && p_size > (_div * 1024)) { _div *= 1024; prefix_idx++; } diff --git a/core/ustring.h b/core/ustring.h index 5bf73001aa..e70b2bfe27 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -258,6 +258,7 @@ public: String capitalize() const; String camelcase_to_underscore(bool lowercase = true) const; + String get_with_code_lines() const; int get_slice_count(String p_splitter) const; String get_slice(String p_splitter, int p_slice) const; String get_slicec(CharType p_splitter, int p_slice) const; diff --git a/core/variant.cpp b/core/variant.cpp index f4e4cd5341..b849a83cb4 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -145,38 +145,38 @@ String Variant::get_type_name(Variant::Type p_type) { } break; // arrays - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { - return "PoolByteArray"; + return "PackedByteArray"; } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { - return "PoolIntArray"; + return "PackedIntArray"; } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { - return "PoolRealArray"; + return "PackedRealArray"; } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { - return "PoolStringArray"; + return "PackedStringArray"; } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { - return "PoolVector2Array"; + return "PackedVector2Array"; } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - return "PoolVector3Array"; + return "PackedVector3Array"; } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { - return "PoolColorArray"; + return "PackedColorArray"; } break; default: { @@ -329,20 +329,20 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { case ARRAY: { static const Type valid[] = { - POOL_BYTE_ARRAY, - POOL_INT_ARRAY, - POOL_STRING_ARRAY, - POOL_REAL_ARRAY, - POOL_COLOR_ARRAY, - POOL_VECTOR2_ARRAY, - POOL_VECTOR3_ARRAY, + PACKED_BYTE_ARRAY, + PACKED_INT_ARRAY, + PACKED_STRING_ARRAY, + PACKED_REAL_ARRAY, + PACKED_COLOR_ARRAY, + PACKED_VECTOR2_ARRAY, + PACKED_VECTOR3_ARRAY, NIL }; valid_types = valid; } break; // arrays - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { static const Type valid[] = { ARRAY, @@ -351,7 +351,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { static const Type valid[] = { ARRAY, @@ -359,7 +359,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { }; valid_types = valid; } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { static const Type valid[] = { ARRAY, @@ -368,7 +368,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { static const Type valid[] = { ARRAY, @@ -376,7 +376,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { }; valid_types = valid; } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { static const Type valid[] = { ARRAY, @@ -385,7 +385,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { static const Type valid[] = { ARRAY, @@ -394,7 +394,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { static const Type valid[] = { ARRAY, @@ -576,20 +576,20 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type case ARRAY: { static const Type valid[] = { - POOL_BYTE_ARRAY, - POOL_INT_ARRAY, - POOL_STRING_ARRAY, - POOL_REAL_ARRAY, - POOL_COLOR_ARRAY, - POOL_VECTOR2_ARRAY, - POOL_VECTOR3_ARRAY, + PACKED_BYTE_ARRAY, + PACKED_INT_ARRAY, + PACKED_STRING_ARRAY, + PACKED_REAL_ARRAY, + PACKED_COLOR_ARRAY, + PACKED_VECTOR2_ARRAY, + PACKED_VECTOR3_ARRAY, NIL }; valid_types = valid; } break; // arrays - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { static const Type valid[] = { ARRAY, @@ -598,7 +598,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { static const Type valid[] = { ARRAY, @@ -606,7 +606,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type }; valid_types = valid; } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { static const Type valid[] = { ARRAY, @@ -615,7 +615,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { static const Type valid[] = { ARRAY, @@ -623,7 +623,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type }; valid_types = valid; } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { static const Type valid[] = { ARRAY, @@ -632,7 +632,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { static const Type valid[] = { ARRAY, @@ -641,7 +641,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { static const Type valid[] = { ARRAY, @@ -809,39 +809,39 @@ bool Variant::is_zero() const { } break; // arrays - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { - return reinterpret_cast<const PoolVector<uint8_t> *>(_data._mem)->size() == 0; + return reinterpret_cast<const Vector<uint8_t> *>(_data._mem)->size() == 0; } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { - return reinterpret_cast<const PoolVector<int> *>(_data._mem)->size() == 0; + return reinterpret_cast<const Vector<int> *>(_data._mem)->size() == 0; } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { - return reinterpret_cast<const PoolVector<real_t> *>(_data._mem)->size() == 0; + return reinterpret_cast<const Vector<real_t> *>(_data._mem)->size() == 0; } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { - return reinterpret_cast<const PoolVector<String> *>(_data._mem)->size() == 0; + return reinterpret_cast<const Vector<String> *>(_data._mem)->size() == 0; } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { - return reinterpret_cast<const PoolVector<Vector2> *>(_data._mem)->size() == 0; + return reinterpret_cast<const Vector<Vector2> *>(_data._mem)->size() == 0; } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - return reinterpret_cast<const PoolVector<Vector3> *>(_data._mem)->size() == 0; + return reinterpret_cast<const Vector<Vector3> *>(_data._mem)->size() == 0; } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { - return reinterpret_cast<const PoolVector<Color> *>(_data._mem)->size() == 0; + return reinterpret_cast<const Vector<Color> *>(_data._mem)->size() == 0; } break; default: { @@ -908,6 +908,14 @@ bool Variant::is_one() const { return false; } +bool Variant::is_null() const { + if (type == OBJECT && _get_obj().obj) { + return false; + } else { + return true; + } +} + void Variant::reference(const Variant &p_variant) { switch (type) { @@ -999,7 +1007,20 @@ void Variant::reference(const Variant &p_variant) { } break; case OBJECT: { - memnew_placement(_data._mem, ObjData(p_variant._get_obj())); + memnew_placement(_data._mem, ObjData); + + if (p_variant._get_obj().obj && p_variant._get_obj().id.is_reference()) { + Reference *reference = static_cast<Reference *>(p_variant._get_obj().obj); + if (!reference->reference()) { + _get_obj().obj = nullptr; + _get_obj().id = ObjectID(); + break; + } + } + + _get_obj().obj = const_cast<Object *>(p_variant._get_obj().obj); + _get_obj().id = p_variant._get_obj().id; + } break; case NODE_PATH: { @@ -1018,39 +1039,39 @@ void Variant::reference(const Variant &p_variant) { } break; // arrays - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { - memnew_placement(_data._mem, PoolVector<uint8_t>(*reinterpret_cast<const PoolVector<uint8_t> *>(p_variant._data._mem))); + memnew_placement(_data._mem, Vector<uint8_t>(*reinterpret_cast<const Vector<uint8_t> *>(p_variant._data._mem))); } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { - memnew_placement(_data._mem, PoolVector<int>(*reinterpret_cast<const PoolVector<int> *>(p_variant._data._mem))); + memnew_placement(_data._mem, Vector<int>(*reinterpret_cast<const Vector<int> *>(p_variant._data._mem))); } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { - memnew_placement(_data._mem, PoolVector<real_t>(*reinterpret_cast<const PoolVector<real_t> *>(p_variant._data._mem))); + memnew_placement(_data._mem, Vector<real_t>(*reinterpret_cast<const Vector<real_t> *>(p_variant._data._mem))); } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { - memnew_placement(_data._mem, PoolVector<String>(*reinterpret_cast<const PoolVector<String> *>(p_variant._data._mem))); + memnew_placement(_data._mem, Vector<String>(*reinterpret_cast<const Vector<String> *>(p_variant._data._mem))); } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { - memnew_placement(_data._mem, PoolVector<Vector2>(*reinterpret_cast<const PoolVector<Vector2> *>(p_variant._data._mem))); + memnew_placement(_data._mem, Vector<Vector2>(*reinterpret_cast<const Vector<Vector2> *>(p_variant._data._mem))); } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - memnew_placement(_data._mem, PoolVector<Vector3>(*reinterpret_cast<const PoolVector<Vector3> *>(p_variant._data._mem))); + memnew_placement(_data._mem, Vector<Vector3>(*reinterpret_cast<const Vector<Vector3> *>(p_variant._data._mem))); } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { - memnew_placement(_data._mem, PoolVector<Color>(*reinterpret_cast<const PoolVector<Color> *>(p_variant._data._mem))); + memnew_placement(_data._mem, Vector<Color>(*reinterpret_cast<const Vector<Color> *>(p_variant._data._mem))); } break; default: { @@ -1114,8 +1135,15 @@ void Variant::clear() { } break; case OBJECT: { + if (_get_obj().id.is_reference()) { + //we are safe that there is a reference here + Reference *reference = static_cast<Reference *>(_get_obj().obj); + if (reference->unreference()) { + memdelete(reference); + } + } _get_obj().obj = NULL; - _get_obj().ref.unref(); + _get_obj().id = ObjectID(); } break; case _RID: { // not much need probably @@ -1130,33 +1158,33 @@ void Variant::clear() { reinterpret_cast<Array *>(_data._mem)->~Array(); } break; // arrays - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { - reinterpret_cast<PoolVector<uint8_t> *>(_data._mem)->~PoolVector<uint8_t>(); + reinterpret_cast<Vector<uint8_t> *>(_data._mem)->~Vector<uint8_t>(); } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { - reinterpret_cast<PoolVector<int> *>(_data._mem)->~PoolVector<int>(); + reinterpret_cast<Vector<int> *>(_data._mem)->~Vector<int>(); } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { - reinterpret_cast<PoolVector<real_t> *>(_data._mem)->~PoolVector<real_t>(); + reinterpret_cast<Vector<real_t> *>(_data._mem)->~Vector<real_t>(); } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { - reinterpret_cast<PoolVector<String> *>(_data._mem)->~PoolVector<String>(); + reinterpret_cast<Vector<String> *>(_data._mem)->~Vector<String>(); } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { - reinterpret_cast<PoolVector<Vector2> *>(_data._mem)->~PoolVector<Vector2>(); + reinterpret_cast<Vector<Vector2> *>(_data._mem)->~Vector<Vector2>(); } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - reinterpret_cast<PoolVector<Vector3> *>(_data._mem)->~PoolVector<Vector3>(); + reinterpret_cast<Vector<Vector3> *>(_data._mem)->~Vector<Vector3>(); } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { - reinterpret_cast<PoolVector<Color> *>(_data._mem)->~PoolVector<Color>(); + reinterpret_cast<Vector<Color> *>(_data._mem)->~Vector<Color>(); } break; default: { } /* not needed */ @@ -1248,6 +1276,14 @@ Variant::operator uint64_t() const { } } +Variant::operator ObjectID() const { + if (type == INT) { + return ObjectID(_data._int); + } else { + return ObjectID(); + } +} + #ifdef NEED_LONG_INT Variant::operator signed long() const { @@ -1493,9 +1529,9 @@ String Variant::stringify(List<const void *> &stack) const { return str; } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { - PoolVector<Vector2> vec = operator PoolVector<Vector2>(); + Vector<Vector2> vec = operator Vector<Vector2>(); String str("["); for (int i = 0; i < vec.size(); i++) { @@ -1506,9 +1542,9 @@ String Variant::stringify(List<const void *> &stack) const { str += "]"; return str; } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - PoolVector<Vector3> vec = operator PoolVector<Vector3>(); + Vector<Vector3> vec = operator Vector<Vector3>(); String str("["); for (int i = 0; i < vec.size(); i++) { @@ -1519,9 +1555,9 @@ String Variant::stringify(List<const void *> &stack) const { str += "]"; return str; } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { - PoolVector<String> vec = operator PoolVector<String>(); + Vector<String> vec = operator Vector<String>(); String str("["); for (int i = 0; i < vec.size(); i++) { @@ -1532,9 +1568,9 @@ String Variant::stringify(List<const void *> &stack) const { str += "]"; return str; } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { - PoolVector<int> vec = operator PoolVector<int>(); + Vector<int> vec = operator Vector<int>(); String str("["); for (int i = 0; i < vec.size(); i++) { @@ -1545,9 +1581,9 @@ String Variant::stringify(List<const void *> &stack) const { str += "]"; return str; } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { - PoolVector<real_t> vec = operator PoolVector<real_t>(); + Vector<real_t> vec = operator Vector<real_t>(); String str("["); for (int i = 0; i < vec.size(); i++) { @@ -1581,14 +1617,11 @@ String Variant::stringify(List<const void *> &stack) const { case OBJECT: { if (_get_obj().obj) { -#ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) { - //only if debugging! - if (!ObjectDB::instance_validate(_get_obj().obj)) { - return "[Deleted Object]"; - }; + + if (!_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { + return "[Freed Object]"; }; -#endif + return _get_obj().obj->to_string(); } else return "[Object:null]"; @@ -1731,24 +1764,16 @@ Variant::operator NodePath() const { return NodePath(); } -Variant::operator RefPtr() const { - - if (type == OBJECT) - return _get_obj().ref; - else - return RefPtr(); -} - Variant::operator RID() const { if (type == _RID) return *reinterpret_cast<const RID *>(_data._mem); - else if (type == OBJECT && !_get_obj().ref.is_null()) { - return _get_obj().ref.get_rid(); + else if (type == OBJECT && _get_obj().obj == nullptr) { + return RID(); } else if (type == OBJECT && _get_obj().obj) { #ifdef DEBUG_ENABLED if (ScriptDebugger::get_singleton()) { - ERR_FAIL_COND_V_MSG(!ObjectDB::instance_validate(_get_obj().obj), RID(), "Invalid pointer (object was deleted)."); + ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, RID(), "Invalid pointer (object was freed)."); }; #endif Variant::CallError ce; @@ -1769,6 +1794,25 @@ Variant::operator Object *() const { else return NULL; } + +Object *Variant::get_validated_object_with_check(bool &r_previously_freed) const { + if (type == OBJECT) { + Object *instance = ObjectDB::get_instance(_get_obj().id); + r_previously_freed = !instance && _get_obj().id != ObjectID(); + return instance; + } else { + r_previously_freed = false; + return NULL; + } +} + +Object *Variant::get_validated_object() const { + if (type == OBJECT) + return ObjectDB::get_instance(_get_obj().id); + else + return NULL; +} + Variant::operator Node *() const { if (type == OBJECT) @@ -1814,26 +1858,26 @@ inline DA _convert_array_from_variant(const Variant &p_variant) { case Variant::ARRAY: { return _convert_array<DA, Array>(p_variant.operator Array()); } - case Variant::POOL_BYTE_ARRAY: { - return _convert_array<DA, PoolVector<uint8_t> >(p_variant.operator PoolVector<uint8_t>()); + case Variant::PACKED_BYTE_ARRAY: { + return _convert_array<DA, Vector<uint8_t> >(p_variant.operator Vector<uint8_t>()); } - case Variant::POOL_INT_ARRAY: { - return _convert_array<DA, PoolVector<int> >(p_variant.operator PoolVector<int>()); + case Variant::PACKED_INT_ARRAY: { + return _convert_array<DA, Vector<int> >(p_variant.operator Vector<int>()); } - case Variant::POOL_REAL_ARRAY: { - return _convert_array<DA, PoolVector<real_t> >(p_variant.operator PoolVector<real_t>()); + case Variant::PACKED_REAL_ARRAY: { + return _convert_array<DA, Vector<real_t> >(p_variant.operator Vector<real_t>()); } - case Variant::POOL_STRING_ARRAY: { - return _convert_array<DA, PoolVector<String> >(p_variant.operator PoolVector<String>()); + case Variant::PACKED_STRING_ARRAY: { + return _convert_array<DA, Vector<String> >(p_variant.operator Vector<String>()); } - case Variant::POOL_VECTOR2_ARRAY: { - return _convert_array<DA, PoolVector<Vector2> >(p_variant.operator PoolVector<Vector2>()); + case Variant::PACKED_VECTOR2_ARRAY: { + return _convert_array<DA, Vector<Vector2> >(p_variant.operator Vector<Vector2>()); } - case Variant::POOL_VECTOR3_ARRAY: { - return _convert_array<DA, PoolVector<Vector3> >(p_variant.operator PoolVector<Vector3>()); + case Variant::PACKED_VECTOR3_ARRAY: { + return _convert_array<DA, Vector<Vector3> >(p_variant.operator Vector<Vector3>()); } - case Variant::POOL_COLOR_ARRAY: { - return _convert_array<DA, PoolVector<Color> >(p_variant.operator PoolVector<Color>()); + case Variant::PACKED_COLOR_ARRAY: { + return _convert_array<DA, Vector<Color> >(p_variant.operator Vector<Color>()); } default: { return DA(); @@ -1849,56 +1893,56 @@ Variant::operator Array() const { return _convert_array_from_variant<Array>(*this); } -Variant::operator PoolVector<uint8_t>() const { +Variant::operator Vector<uint8_t>() const { - if (type == POOL_BYTE_ARRAY) - return *reinterpret_cast<const PoolVector<uint8_t> *>(_data._mem); + if (type == PACKED_BYTE_ARRAY) + return *reinterpret_cast<const Vector<uint8_t> *>(_data._mem); else - return _convert_array_from_variant<PoolVector<uint8_t> >(*this); + return _convert_array_from_variant<Vector<uint8_t> >(*this); } -Variant::operator PoolVector<int>() const { +Variant::operator Vector<int>() const { - if (type == POOL_INT_ARRAY) - return *reinterpret_cast<const PoolVector<int> *>(_data._mem); + if (type == PACKED_INT_ARRAY) + return *reinterpret_cast<const Vector<int> *>(_data._mem); else - return _convert_array_from_variant<PoolVector<int> >(*this); + return _convert_array_from_variant<Vector<int> >(*this); } -Variant::operator PoolVector<real_t>() const { +Variant::operator Vector<real_t>() const { - if (type == POOL_REAL_ARRAY) - return *reinterpret_cast<const PoolVector<real_t> *>(_data._mem); + if (type == PACKED_REAL_ARRAY) + return *reinterpret_cast<const Vector<real_t> *>(_data._mem); else - return _convert_array_from_variant<PoolVector<real_t> >(*this); + return _convert_array_from_variant<Vector<real_t> >(*this); } -Variant::operator PoolVector<String>() const { +Variant::operator Vector<String>() const { - if (type == POOL_STRING_ARRAY) - return *reinterpret_cast<const PoolVector<String> *>(_data._mem); + if (type == PACKED_STRING_ARRAY) + return *reinterpret_cast<const Vector<String> *>(_data._mem); else - return _convert_array_from_variant<PoolVector<String> >(*this); + return _convert_array_from_variant<Vector<String> >(*this); } -Variant::operator PoolVector<Vector3>() const { +Variant::operator Vector<Vector3>() const { - if (type == POOL_VECTOR3_ARRAY) - return *reinterpret_cast<const PoolVector<Vector3> *>(_data._mem); + if (type == PACKED_VECTOR3_ARRAY) + return *reinterpret_cast<const Vector<Vector3> *>(_data._mem); else - return _convert_array_from_variant<PoolVector<Vector3> >(*this); + return _convert_array_from_variant<Vector<Vector3> >(*this); } -Variant::operator PoolVector<Vector2>() const { +Variant::operator Vector<Vector2>() const { - if (type == POOL_VECTOR2_ARRAY) - return *reinterpret_cast<const PoolVector<Vector2> *>(_data._mem); + if (type == PACKED_VECTOR2_ARRAY) + return *reinterpret_cast<const Vector<Vector2> *>(_data._mem); else - return _convert_array_from_variant<PoolVector<Vector2> >(*this); + return _convert_array_from_variant<Vector<Vector2> >(*this); } -Variant::operator PoolVector<Color>() const { +Variant::operator Vector<Color>() const { - if (type == POOL_COLOR_ARRAY) - return *reinterpret_cast<const PoolVector<Color> *>(_data._mem); + if (type == PACKED_COLOR_ARRAY) + return *reinterpret_cast<const Vector<Color> *>(_data._mem); else - return _convert_array_from_variant<PoolVector<Color> >(*this); + return _convert_array_from_variant<Vector<Color> >(*this); } /* helpers */ @@ -1913,33 +1957,16 @@ Variant::operator Vector<RID>() const { return rids; } -Variant::operator Vector<Vector2>() const { - - PoolVector<Vector2> from = operator PoolVector<Vector2>(); - Vector<Vector2> to; - int len = from.size(); - if (len == 0) - return Vector<Vector2>(); - to.resize(len); - PoolVector<Vector2>::Read r = from.read(); - Vector2 *w = to.ptrw(); - for (int i = 0; i < len; i++) { - - w[i] = r[i]; - } - return to; -} - -Variant::operator PoolVector<Plane>() const { +Variant::operator Vector<Plane>() const { Array va = operator Array(); - PoolVector<Plane> planes; + Vector<Plane> planes; int va_size = va.size(); if (va_size == 0) return planes; planes.resize(va_size); - PoolVector<Plane>::Write w = planes.write(); + Plane *w = planes.ptrw(); for (int i = 0; i < va_size; i++) w[i] = va[i]; @@ -1947,17 +1974,17 @@ Variant::operator PoolVector<Plane>() const { return planes; } -Variant::operator PoolVector<Face3>() const { +Variant::operator Vector<Face3>() const { - PoolVector<Vector3> va = operator PoolVector<Vector3>(); - PoolVector<Face3> faces; + Vector<Vector3> va = operator Vector<Vector3>(); + Vector<Face3> faces; int va_size = va.size(); if (va_size == 0) return faces; faces.resize(va_size / 3); - PoolVector<Face3>::Write w = faces.write(); - PoolVector<Vector3>::Read r = va.read(); + Face3 *w = faces.ptrw(); + const Vector3 *r = va.ptr(); for (int i = 0; i < va_size; i++) w[i / 3].vertex[i % 3] = r[i]; @@ -1965,87 +1992,24 @@ Variant::operator PoolVector<Face3>() const { return faces; } -Variant::operator Vector<Plane>() const { +Variant::operator Vector<Variant>() const { Array va = operator Array(); - Vector<Plane> planes; + Vector<Variant> variants; int va_size = va.size(); if (va_size == 0) - return planes; - - planes.resize(va_size); + return variants; + variants.resize(va_size); + Variant *w = variants.ptrw(); for (int i = 0; i < va_size; i++) - planes.write[i] = va[i]; - - return planes; -} - -Variant::operator Vector<Variant>() const { - - Array from = operator Array(); - Vector<Variant> to; - int len = from.size(); - to.resize(len); - for (int i = 0; i < len; i++) { - - to.write[i] = from[i]; - } - return to; -} - -Variant::operator Vector<uint8_t>() const { - - PoolVector<uint8_t> from = operator PoolVector<uint8_t>(); - Vector<uint8_t> to; - int len = from.size(); - to.resize(len); - for (int i = 0; i < len; i++) { - - to.write[i] = from[i]; - } - return to; -} -Variant::operator Vector<int>() const { - - PoolVector<int> from = operator PoolVector<int>(); - Vector<int> to; - int len = from.size(); - to.resize(len); - for (int i = 0; i < len; i++) { - - to.write[i] = from[i]; - } - return to; -} -Variant::operator Vector<real_t>() const { - - PoolVector<real_t> from = operator PoolVector<real_t>(); - Vector<real_t> to; - int len = from.size(); - to.resize(len); - for (int i = 0; i < len; i++) { - - to.write[i] = from[i]; - } - return to; -} - -Variant::operator Vector<String>() const { - - PoolVector<String> from = operator PoolVector<String>(); - Vector<String> to; - int len = from.size(); - to.resize(len); - for (int i = 0; i < len; i++) { + w[i] = variants[i]; - to.write[i] = from[i]; - } - return to; + return variants; } Variant::operator Vector<StringName>() const { - PoolVector<String> from = operator PoolVector<String>(); + Vector<String> from = operator Vector<String>(); Vector<StringName> to; int len = from.size(); to.resize(len); @@ -2056,39 +2020,6 @@ Variant::operator Vector<StringName>() const { return to; } -Variant::operator Vector<Vector3>() const { - - PoolVector<Vector3> from = operator PoolVector<Vector3>(); - Vector<Vector3> to; - int len = from.size(); - if (len == 0) - return Vector<Vector3>(); - to.resize(len); - PoolVector<Vector3>::Read r = from.read(); - Vector3 *w = to.ptrw(); - for (int i = 0; i < len; i++) { - - w[i] = r[i]; - } - return to; -} -Variant::operator Vector<Color>() const { - - PoolVector<Color> from = operator PoolVector<Color>(); - Vector<Color> to; - int len = from.size(); - if (len == 0) - return Vector<Color>(); - to.resize(len); - PoolVector<Color>::Read r = from.read(); - Color *w = to.ptrw(); - for (int i = 0; i < len; i++) { - - w[i] = r[i]; - } - return to; -} - Variant::operator Margin() const { return (Margin) operator int(); @@ -2100,9 +2031,9 @@ Variant::operator Orientation() const { Variant::operator IP_Address() const { - if (type == POOL_REAL_ARRAY || type == POOL_INT_ARRAY || type == POOL_BYTE_ARRAY) { + if (type == PACKED_REAL_ARRAY || type == PACKED_INT_ARRAY || type == PACKED_BYTE_ARRAY) { - PoolVector<int> addr = operator PoolVector<int>(); + Vector<int> addr = operator Vector<int>(); if (addr.size() == 4) { return IP_Address(addr.get(0), addr.get(1), addr.get(2), addr.get(3)); } @@ -2193,6 +2124,11 @@ Variant::Variant(double p_double) { _data._real = p_double; } +Variant::Variant(const ObjectID &p_id) { + type = INT; + _data._int = p_id; +} + Variant::Variant(const StringName &p_string) { type = STRING; @@ -2276,15 +2212,6 @@ Variant::Variant(const NodePath &p_node_path) { memnew_placement(_data._mem, NodePath(p_node_path)); } -Variant::Variant(const RefPtr &p_resource) { - - type = OBJECT; - memnew_placement(_data._mem, ObjData); - REF *ref = reinterpret_cast<REF *>(p_resource.get_data()); - _get_obj().obj = ref->ptr(); - _get_obj().ref = p_resource; -} - Variant::Variant(const RID &p_rid) { type = _RID; @@ -2296,7 +2223,24 @@ Variant::Variant(const Object *p_object) { type = OBJECT; memnew_placement(_data._mem, ObjData); - _get_obj().obj = const_cast<Object *>(p_object); + + if (p_object) { + + if (p_object->is_reference()) { + Reference *reference = const_cast<Reference *>(static_cast<const Reference *>(p_object)); + if (!reference->init_ref()) { + _get_obj().obj = nullptr; + _get_obj().id = ObjectID(); + return; + } + } + + _get_obj().obj = const_cast<Object *>(p_object); + _get_obj().id = p_object->get_instance_id(); + } else { + _get_obj().obj = nullptr; + _get_obj().id = ObjectID(); + } } Variant::Variant(const Dictionary &p_dictionary) { @@ -2311,20 +2255,6 @@ Variant::Variant(const Array &p_array) { memnew_placement(_data._mem, Array(p_array)); } -Variant::Variant(const PoolVector<Plane> &p_array) { - - type = ARRAY; - - Array *plane_array = memnew_placement(_data._mem, Array); - - plane_array->resize(p_array.size()); - - for (int i = 0; i < p_array.size(); i++) { - - plane_array->operator[](i) = Variant(p_array[i]); - } -} - Variant::Variant(const Vector<Plane> &p_array) { type = ARRAY; @@ -2353,68 +2283,52 @@ Variant::Variant(const Vector<RID> &p_array) { } } -Variant::Variant(const Vector<Vector2> &p_array) { - - type = NIL; - PoolVector<Vector2> v; - int len = p_array.size(); - if (len > 0) { - v.resize(len); - PoolVector<Vector2>::Write w = v.write(); - const Vector2 *r = p_array.ptr(); - - for (int i = 0; i < len; i++) - w[i] = r[i]; - } - *this = v; -} - -Variant::Variant(const PoolVector<uint8_t> &p_raw_array) { +Variant::Variant(const Vector<uint8_t> &p_raw_array) { - type = POOL_BYTE_ARRAY; - memnew_placement(_data._mem, PoolVector<uint8_t>(p_raw_array)); + type = PACKED_BYTE_ARRAY; + memnew_placement(_data._mem, Vector<uint8_t>(p_raw_array)); } -Variant::Variant(const PoolVector<int> &p_int_array) { +Variant::Variant(const Vector<int> &p_int_array) { - type = POOL_INT_ARRAY; - memnew_placement(_data._mem, PoolVector<int>(p_int_array)); + type = PACKED_INT_ARRAY; + memnew_placement(_data._mem, Vector<int>(p_int_array)); } -Variant::Variant(const PoolVector<real_t> &p_real_array) { +Variant::Variant(const Vector<real_t> &p_real_array) { - type = POOL_REAL_ARRAY; - memnew_placement(_data._mem, PoolVector<real_t>(p_real_array)); + type = PACKED_REAL_ARRAY; + memnew_placement(_data._mem, Vector<real_t>(p_real_array)); } -Variant::Variant(const PoolVector<String> &p_string_array) { +Variant::Variant(const Vector<String> &p_string_array) { - type = POOL_STRING_ARRAY; - memnew_placement(_data._mem, PoolVector<String>(p_string_array)); + type = PACKED_STRING_ARRAY; + memnew_placement(_data._mem, Vector<String>(p_string_array)); } -Variant::Variant(const PoolVector<Vector3> &p_vector3_array) { +Variant::Variant(const Vector<Vector3> &p_vector3_array) { - type = POOL_VECTOR3_ARRAY; - memnew_placement(_data._mem, PoolVector<Vector3>(p_vector3_array)); + type = PACKED_VECTOR3_ARRAY; + memnew_placement(_data._mem, Vector<Vector3>(p_vector3_array)); } -Variant::Variant(const PoolVector<Vector2> &p_vector2_array) { +Variant::Variant(const Vector<Vector2> &p_vector2_array) { - type = POOL_VECTOR2_ARRAY; - memnew_placement(_data._mem, PoolVector<Vector2>(p_vector2_array)); + type = PACKED_VECTOR2_ARRAY; + memnew_placement(_data._mem, Vector<Vector2>(p_vector2_array)); } -Variant::Variant(const PoolVector<Color> &p_color_array) { +Variant::Variant(const Vector<Color> &p_color_array) { - type = POOL_COLOR_ARRAY; - memnew_placement(_data._mem, PoolVector<Color>(p_color_array)); + type = PACKED_COLOR_ARRAY; + memnew_placement(_data._mem, Vector<Color>(p_color_array)); } -Variant::Variant(const PoolVector<Face3> &p_face_array) { +Variant::Variant(const Vector<Face3> &p_face_array) { - PoolVector<Vector3> vertices; + Vector<Vector3> vertices; int face_count = p_face_array.size(); vertices.resize(face_count * 3); if (face_count) { - PoolVector<Face3>::Read r = p_face_array.read(); - PoolVector<Vector3>::Write w = vertices.write(); + const Face3 *r = p_face_array.ptr(); + Vector3 *w = vertices.ptrw(); for (int i = 0; i < face_count; i++) { @@ -2429,93 +2343,20 @@ Variant::Variant(const PoolVector<Face3> &p_face_array) { } /* helpers */ - Variant::Variant(const Vector<Variant> &p_array) { - - type = NIL; - Array v; - int len = p_array.size(); - v.resize(len); - for (int i = 0; i < len; i++) - v.set(i, p_array[i]); - *this = v; -} - -Variant::Variant(const Vector<uint8_t> &p_array) { - - type = NIL; - PoolVector<uint8_t> v; - int len = p_array.size(); - v.resize(len); - for (int i = 0; i < len; i++) - v.set(i, p_array[i]); - *this = v; -} - -Variant::Variant(const Vector<int> &p_array) { - - type = NIL; - PoolVector<int> v; - int len = p_array.size(); - v.resize(len); - for (int i = 0; i < len; i++) - v.set(i, p_array[i]); - *this = v; -} - -Variant::Variant(const Vector<real_t> &p_array) { - - type = NIL; - PoolVector<real_t> v; - int len = p_array.size(); - v.resize(len); - for (int i = 0; i < len; i++) - v.set(i, p_array[i]); - *this = v; -} - -Variant::Variant(const Vector<String> &p_array) { - - type = NIL; - PoolVector<String> v; - int len = p_array.size(); - v.resize(len); - for (int i = 0; i < len; i++) - v.set(i, p_array[i]); - *this = v; -} - -Variant::Variant(const Vector<StringName> &p_array) { - - type = NIL; - PoolVector<String> v; - int len = p_array.size(); - v.resize(len); - for (int i = 0; i < len; i++) - v.set(i, p_array[i]); - *this = v; -} - -Variant::Variant(const Vector<Vector3> &p_array) { - type = NIL; - PoolVector<Vector3> v; - int len = p_array.size(); - if (len > 0) { - v.resize(len); - PoolVector<Vector3>::Write w = v.write(); - const Vector3 *r = p_array.ptr(); - - for (int i = 0; i < len; i++) - w[i] = r[i]; + Array arr; + arr.resize(p_array.size()); + for (int i = 0; i < p_array.size(); i++) { + arr[i] = p_array[i]; } - *this = v; + *this = arr; } -Variant::Variant(const Vector<Color> &p_array) { +Variant::Variant(const Vector<StringName> &p_array) { type = NIL; - PoolVector<Color> v; + Vector<String> v; int len = p_array.size(); v.resize(len); for (int i = 0; i < len; i++) @@ -2607,7 +2448,26 @@ void Variant::operator=(const Variant &p_variant) { } break; case OBJECT: { - *reinterpret_cast<ObjData *>(_data._mem) = p_variant._get_obj(); + if (_get_obj().id.is_reference()) { + //we are safe that there is a reference here + Reference *reference = static_cast<Reference *>(_get_obj().obj); + if (reference->unreference()) { + memdelete(reference); + } + } + + if (p_variant._get_obj().obj && p_variant._get_obj().id.is_reference()) { + Reference *reference = static_cast<Reference *>(p_variant._get_obj().obj); + if (!reference->reference()) { + _get_obj().obj = nullptr; + _get_obj().id = ObjectID(); + break; + } + } + + _get_obj().obj = const_cast<Object *>(p_variant._get_obj().obj); + _get_obj().id = p_variant._get_obj().id; + } break; case NODE_PATH: { @@ -2623,33 +2483,33 @@ void Variant::operator=(const Variant &p_variant) { } break; // arrays - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { - *reinterpret_cast<PoolVector<uint8_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<uint8_t> *>(p_variant._data._mem); + *reinterpret_cast<Vector<uint8_t> *>(_data._mem) = *reinterpret_cast<const Vector<uint8_t> *>(p_variant._data._mem); } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { - *reinterpret_cast<PoolVector<int> *>(_data._mem) = *reinterpret_cast<const PoolVector<int> *>(p_variant._data._mem); + *reinterpret_cast<Vector<int> *>(_data._mem) = *reinterpret_cast<const Vector<int> *>(p_variant._data._mem); } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { - *reinterpret_cast<PoolVector<real_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<real_t> *>(p_variant._data._mem); + *reinterpret_cast<Vector<real_t> *>(_data._mem) = *reinterpret_cast<const Vector<real_t> *>(p_variant._data._mem); } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { - *reinterpret_cast<PoolVector<String> *>(_data._mem) = *reinterpret_cast<const PoolVector<String> *>(p_variant._data._mem); + *reinterpret_cast<Vector<String> *>(_data._mem) = *reinterpret_cast<const Vector<String> *>(p_variant._data._mem); } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { - *reinterpret_cast<PoolVector<Vector2> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector2> *>(p_variant._data._mem); + *reinterpret_cast<Vector<Vector2> *>(_data._mem) = *reinterpret_cast<const Vector<Vector2> *>(p_variant._data._mem); } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - *reinterpret_cast<PoolVector<Vector3> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector3> *>(p_variant._data._mem); + *reinterpret_cast<Vector<Vector3> *>(_data._mem) = *reinterpret_cast<const Vector<Vector3> *>(p_variant._data._mem); } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { - *reinterpret_cast<PoolVector<Color> *>(_data._mem) = *reinterpret_cast<const PoolVector<Color> *>(p_variant._data._mem); + *reinterpret_cast<Vector<Color> *>(_data._mem) = *reinterpret_cast<const Vector<Color> *>(p_variant._data._mem); } break; default: { } @@ -2822,51 +2682,51 @@ uint32_t Variant::hash() const { return arr.hash(); } break; - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { - const PoolVector<uint8_t> &arr = *reinterpret_cast<const PoolVector<uint8_t> *>(_data._mem); + const Vector<uint8_t> &arr = *reinterpret_cast<const Vector<uint8_t> *>(_data._mem); int len = arr.size(); if (likely(len)) { - PoolVector<uint8_t>::Read r = arr.read(); + const uint8_t *r = arr.ptr(); return hash_djb2_buffer((uint8_t *)&r[0], len); } else { return hash_djb2_one_64(0); } } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { - const PoolVector<int> &arr = *reinterpret_cast<const PoolVector<int> *>(_data._mem); + const Vector<int> &arr = *reinterpret_cast<const Vector<int> *>(_data._mem); int len = arr.size(); if (likely(len)) { - PoolVector<int>::Read r = arr.read(); + const int *r = arr.ptr(); return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(int)); } else { return hash_djb2_one_64(0); } } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { - const PoolVector<real_t> &arr = *reinterpret_cast<const PoolVector<real_t> *>(_data._mem); + const Vector<real_t> &arr = *reinterpret_cast<const Vector<real_t> *>(_data._mem); int len = arr.size(); if (likely(len)) { - PoolVector<real_t>::Read r = arr.read(); + const real_t *r = arr.ptr(); return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(real_t)); } else { return hash_djb2_one_float(0.0); } } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { uint32_t hash = 5831; - const PoolVector<String> &arr = *reinterpret_cast<const PoolVector<String> *>(_data._mem); + const Vector<String> &arr = *reinterpret_cast<const Vector<String> *>(_data._mem); int len = arr.size(); if (likely(len)) { - PoolVector<String>::Read r = arr.read(); + const String *r = arr.ptr(); for (int i = 0; i < len; i++) { hash = hash_djb2_one_32(r[i].hash(), hash); @@ -2875,14 +2735,14 @@ uint32_t Variant::hash() const { return hash; } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { uint32_t hash = 5831; - const PoolVector<Vector2> &arr = *reinterpret_cast<const PoolVector<Vector2> *>(_data._mem); + const Vector<Vector2> &arr = *reinterpret_cast<const Vector<Vector2> *>(_data._mem); int len = arr.size(); if (likely(len)) { - PoolVector<Vector2>::Read r = arr.read(); + const Vector2 *r = arr.ptr(); for (int i = 0; i < len; i++) { hash = hash_djb2_one_float(r[i].x, hash); @@ -2892,14 +2752,14 @@ uint32_t Variant::hash() const { return hash; } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { uint32_t hash = 5831; - const PoolVector<Vector3> &arr = *reinterpret_cast<const PoolVector<Vector3> *>(_data._mem); + const Vector<Vector3> &arr = *reinterpret_cast<const Vector<Vector3> *>(_data._mem); int len = arr.size(); if (likely(len)) { - PoolVector<Vector3>::Read r = arr.read(); + const Vector3 *r = arr.ptr(); for (int i = 0; i < len; i++) { hash = hash_djb2_one_float(r[i].x, hash); @@ -2910,14 +2770,14 @@ uint32_t Variant::hash() const { return hash; } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { uint32_t hash = 5831; - const PoolVector<Color> &arr = *reinterpret_cast<const PoolVector<Color> *>(_data._mem); + const Vector<Color> &arr = *reinterpret_cast<const Vector<Color> *>(_data._mem); int len = arr.size(); if (likely(len)) { - PoolVector<Color>::Read r = arr.read(); + const Color *r = arr.ptr(); for (int i = 0; i < len; i++) { hash = hash_djb2_one_float(r[i].r, hash); @@ -2960,21 +2820,21 @@ uint32_t Variant::hash() const { (hash_compare_scalar((p_lhs).b, (p_rhs).b)) && \ (hash_compare_scalar((p_lhs).a, (p_rhs).a)) -#define hash_compare_pool_array(p_lhs, p_rhs, p_type, p_compare_func) \ - const PoolVector<p_type> &l = *reinterpret_cast<const PoolVector<p_type> *>(p_lhs); \ - const PoolVector<p_type> &r = *reinterpret_cast<const PoolVector<p_type> *>(p_rhs); \ - \ - if (l.size() != r.size()) \ - return false; \ - \ - PoolVector<p_type>::Read lr = l.read(); \ - PoolVector<p_type>::Read rr = r.read(); \ - \ - for (int i = 0; i < l.size(); ++i) { \ - if (!p_compare_func((lr[i]), (rr[i]))) \ - return false; \ - } \ - \ +#define hash_compare_pool_array(p_lhs, p_rhs, p_type, p_compare_func) \ + const Vector<p_type> &l = *reinterpret_cast<const Vector<p_type> *>(p_lhs); \ + const Vector<p_type> &r = *reinterpret_cast<const Vector<p_type> *>(p_rhs); \ + \ + if (l.size() != r.size()) \ + return false; \ + \ + const p_type *lr = l.ptr(); \ + const p_type *rr = r.ptr(); \ + \ + for (int i = 0; i < l.size(); ++i) { \ + if (!p_compare_func((lr[i]), (rr[i]))) \ + return false; \ + } \ + \ return true bool Variant::hash_compare(const Variant &p_variant) const { @@ -3090,19 +2950,19 @@ bool Variant::hash_compare(const Variant &p_variant) const { return true; } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { hash_compare_pool_array(_data._mem, p_variant._data._mem, real_t, hash_compare_scalar); } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { hash_compare_pool_array(_data._mem, p_variant._data._mem, Vector2, hash_compare_vector2); } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { hash_compare_pool_array(_data._mem, p_variant._data._mem, Vector3, hash_compare_vector3); } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { hash_compare_pool_array(_data._mem, p_variant._data._mem, Color, hash_compare_color); } break; @@ -3118,7 +2978,7 @@ bool Variant::hash_compare(const Variant &p_variant) const { bool Variant::is_ref() const { - return type == OBJECT && !_get_obj().ref.is_null(); + return type == OBJECT && _get_obj().id.is_reference(); } Vector<Variant> varray() { diff --git a/core/variant.h b/core/variant.h index 06be914408..51f23b4b49 100644 --- a/core/variant.h +++ b/core/variant.h @@ -44,12 +44,11 @@ #include "core/math/transform_2d.h" #include "core/math/vector3.h" #include "core/node_path.h" -#include "core/pool_vector.h" -#include "core/ref_ptr.h" +#include "core/object_id.h" + #include "core/rid.h" #include "core/ustring.h" -class RefPtr; class Object; class Node; // helper class Control; // helper @@ -57,13 +56,13 @@ class Control; // helper struct PropertyInfo; struct MethodInfo; -typedef PoolVector<uint8_t> PoolByteArray; -typedef PoolVector<int> PoolIntArray; -typedef PoolVector<real_t> PoolRealArray; -typedef PoolVector<String> PoolStringArray; -typedef PoolVector<Vector2> PoolVector2Array; -typedef PoolVector<Vector3> PoolVector3Array; -typedef PoolVector<Color> PoolColorArray; +typedef Vector<uint8_t> PackedByteArray; +typedef Vector<int> PackedIntArray; +typedef Vector<real_t> PackedRealArray; +typedef Vector<String> PackedStringArray; +typedef Vector<Vector2> PackedVector2Array; +typedef Vector<Vector3> PackedVector3Array; +typedef Vector<Color> PackedColorArray; // Temporary workaround until c++11 alignas() #ifdef __GNUC__ @@ -106,13 +105,13 @@ public: ARRAY, // arrays - POOL_BYTE_ARRAY, // 20 - POOL_INT_ARRAY, - POOL_REAL_ARRAY, - POOL_STRING_ARRAY, - POOL_VECTOR2_ARRAY, - POOL_VECTOR3_ARRAY, // 25 - POOL_COLOR_ARRAY, + PACKED_BYTE_ARRAY, // 20 + PACKED_INT_ARRAY, + PACKED_REAL_ARRAY, + PACKED_STRING_ARRAY, + PACKED_VECTOR2_ARRAY, + PACKED_VECTOR3_ARRAY, // 25 + PACKED_COLOR_ARRAY, VARIANT_MAX @@ -127,12 +126,12 @@ private: struct ObjData { + ObjectID id; Object *obj; - RefPtr ref; }; - _FORCE_INLINE_ ObjData &_get_obj(); - _FORCE_INLINE_ const ObjData &_get_obj() const; + _ALWAYS_INLINE_ ObjData &_get_obj(); + _ALWAYS_INLINE_ const ObjData &_get_obj() const; union { bool _bool; @@ -161,6 +160,7 @@ public: bool is_shared() const; bool is_zero() const; bool is_one() const; + bool is_null() const; operator bool() const; operator signed int() const; @@ -177,6 +177,8 @@ public: operator unsigned long() const; #endif + operator ObjectID() const; + operator CharType() const; operator float() const; operator double() const; @@ -194,7 +196,6 @@ public: operator Color() const; operator NodePath() const; - operator RefPtr() const; operator RID() const; operator Object *() const; @@ -204,27 +205,19 @@ public: operator Dictionary() const; operator Array() const; - operator PoolVector<uint8_t>() const; - operator PoolVector<int>() const; - operator PoolVector<real_t>() const; - operator PoolVector<String>() const; - operator PoolVector<Vector3>() const; - operator PoolVector<Color>() const; - operator PoolVector<Plane>() const; - operator PoolVector<Face3>() const; - - operator Vector<Variant>() const; operator Vector<uint8_t>() const; operator Vector<int>() const; operator Vector<real_t>() const; operator Vector<String>() const; - operator Vector<StringName>() const; operator Vector<Vector3>() const; operator Vector<Color>() const; + operator Vector<Plane>() const; + operator Vector<Face3>() const; + + operator Vector<Variant>() const; + operator Vector<StringName>() const; operator Vector<RID>() const; operator Vector<Vector2>() const; - operator PoolVector<Vector2>() const; - operator Vector<Plane>() const; // some core type enums to convert to operator Margin() const; @@ -232,6 +225,9 @@ public: operator IP_Address() const; + Object *get_validated_object() const; + Object *get_validated_object_with_check(bool &r_previously_freed) const; + Variant(bool p_bool); Variant(signed int p_int); // real one Variant(unsigned int p_int); @@ -248,6 +244,7 @@ public: Variant(uint64_t p_int); Variant(float p_float); Variant(double p_double); + Variant(const ObjectID &p_id); Variant(const String &p_string); Variant(const StringName &p_string); Variant(const char *const p_cstring); @@ -263,33 +260,24 @@ public: Variant(const Transform &p_transform); Variant(const Color &p_color); Variant(const NodePath &p_node_path); - Variant(const RefPtr &p_resource); Variant(const RID &p_rid); Variant(const Object *p_object); Variant(const Dictionary &p_dictionary); Variant(const Array &p_array); - Variant(const PoolVector<Plane> &p_array); // helper - Variant(const PoolVector<uint8_t> &p_raw_array); - Variant(const PoolVector<int> &p_int_array); - Variant(const PoolVector<real_t> &p_real_array); - Variant(const PoolVector<String> &p_string_array); - Variant(const PoolVector<Vector3> &p_vector3_array); - Variant(const PoolVector<Color> &p_color_array); - Variant(const PoolVector<Face3> &p_face_array); + Variant(const Vector<Plane> &p_array); // helper + Variant(const Vector<uint8_t> &p_raw_array); + Variant(const Vector<int> &p_int_array); + Variant(const Vector<real_t> &p_real_array); + Variant(const Vector<String> &p_string_array); + Variant(const Vector<Vector3> &p_vector3_array); + Variant(const Vector<Color> &p_color_array); + Variant(const Vector<Face3> &p_face_array); Variant(const Vector<Variant> &p_array); - Variant(const Vector<uint8_t> &p_array); - Variant(const Vector<int> &p_array); - Variant(const Vector<real_t> &p_array); - Variant(const Vector<String> &p_array); Variant(const Vector<StringName> &p_array); - Variant(const Vector<Vector3> &p_array); - Variant(const Vector<Color> &p_array); - Variant(const Vector<Plane> &p_array); // helper Variant(const Vector<RID> &p_array); // helper Variant(const Vector<Vector2> &p_array); // helper - Variant(const PoolVector<Vector2> &p_vector2_array); // helper Variant(const IP_Address &p_address); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 6b5b947185..6506da58d4 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -317,17 +317,16 @@ struct _VariantCall { String *s = reinterpret_cast<String *>(p_self._data._mem); if (s->empty()) { - r_ret = PoolByteArray(); + r_ret = PackedByteArray(); return; } CharString charstr = s->ascii(); - PoolByteArray retval; + PackedByteArray retval; size_t len = charstr.length(); retval.resize(len); - PoolByteArray::Write w = retval.write(); - copymem(w.ptr(), charstr.ptr(), len); - w.release(); + uint8_t *w = retval.ptrw(); + copymem(w, charstr.ptr(), len); r_ret = retval; } @@ -336,17 +335,16 @@ struct _VariantCall { String *s = reinterpret_cast<String *>(p_self._data._mem); if (s->empty()) { - r_ret = PoolByteArray(); + r_ret = PackedByteArray(); return; } CharString charstr = s->utf8(); - PoolByteArray retval; + PackedByteArray retval; size_t len = charstr.length(); retval.resize(len); - PoolByteArray::Write w = retval.write(); - copymem(w.ptr(), charstr.ptr(), len); - w.release(); + uint8_t *w = retval.ptrw(); + copymem(w, charstr.ptr(), len); r_ret = retval; } @@ -488,7 +486,6 @@ struct _VariantCall { VCALL_LOCALMEM0R(Color, to_argb64); VCALL_LOCALMEM0R(Color, to_abgr64); VCALL_LOCALMEM0R(Color, to_rgba64); - VCALL_LOCALMEM0R(Color, gray); VCALL_LOCALMEM0R(Color, inverted); VCALL_LOCALMEM0R(Color, contrasted); VCALL_LOCALMEM2R(Color, linear_interpolate); @@ -555,15 +552,15 @@ struct _VariantCall { VCALL_LOCALMEM0R(Array, max); VCALL_LOCALMEM0R(Array, min); - static void _call_PoolByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { + static void _call_PackedByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem); + PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); String s; if (ba->size() > 0) { - PoolByteArray::Read r = ba->read(); + const uint8_t *r = ba->ptr(); CharString cs; cs.resize(ba->size() + 1); - copymem(cs.ptrw(), r.ptr(), ba->size()); + copymem(cs.ptrw(), r, ba->size()); cs[ba->size()] = 0; s = cs.get_data(); @@ -571,26 +568,26 @@ struct _VariantCall { r_ret = s; } - static void _call_PoolByteArray_get_string_from_utf8(Variant &r_ret, Variant &p_self, const Variant **p_args) { + static void _call_PackedByteArray_get_string_from_utf8(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem); + PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); String s; if (ba->size() > 0) { - PoolByteArray::Read r = ba->read(); - s.parse_utf8((const char *)r.ptr(), ba->size()); + const uint8_t *r = ba->ptr(); + s.parse_utf8((const char *)r, ba->size()); } r_ret = s; } - static void _call_PoolByteArray_compress(Variant &r_ret, Variant &p_self, const Variant **p_args) { + static void _call_PackedByteArray_compress(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem); - PoolByteArray compressed; + PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); + PackedByteArray compressed; if (ba->size() > 0) { Compression::Mode mode = (Compression::Mode)(int)(*p_args[0]); compressed.resize(Compression::get_max_compressed_buffer_size(ba->size(), mode)); - int result = Compression::compress(compressed.write().ptr(), ba->read().ptr(), ba->size(), mode); + int result = Compression::compress(compressed.ptrw(), ba->ptr(), ba->size(), mode); result = result >= 0 ? result : 0; compressed.resize(result); @@ -598,10 +595,10 @@ struct _VariantCall { r_ret = compressed; } - static void _call_PoolByteArray_decompress(Variant &r_ret, Variant &p_self, const Variant **p_args) { + static void _call_PackedByteArray_decompress(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem); - PoolByteArray decompressed; + PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); + PackedByteArray decompressed; Compression::Mode mode = (Compression::Mode)(int)(*p_args[1]); int buffer_size = (int)(*p_args[0]); @@ -612,7 +609,7 @@ struct _VariantCall { } decompressed.resize(buffer_size); - int result = Compression::decompress(decompressed.write().ptr(), buffer_size, ba->read().ptr(), ba->size(), mode); + int result = Compression::decompress(decompressed.ptrw(), buffer_size, ba->ptr(), ba->size(), mode); result = result >= 0 ? result : 0; decompressed.resize(result); @@ -620,102 +617,101 @@ struct _VariantCall { r_ret = decompressed; } - static void _call_PoolByteArray_hex_encode(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem); + static void _call_PackedByteArray_hex_encode(Variant &r_ret, Variant &p_self, const Variant **p_args) { + PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); if (ba->size() == 0) { r_ret = String(); return; } - PoolByteArray::Read r = ba->read(); + const uint8_t *r = ba->ptr(); String s = String::hex_encode_buffer(&r[0], ba->size()); r_ret = s; } - VCALL_LOCALMEM0R(PoolByteArray, size); - VCALL_LOCALMEM0R(PoolByteArray, empty); - VCALL_LOCALMEM2(PoolByteArray, set); - VCALL_LOCALMEM1R(PoolByteArray, get); - VCALL_LOCALMEM1(PoolByteArray, push_back); - VCALL_LOCALMEM1(PoolByteArray, resize); - VCALL_LOCALMEM2R(PoolByteArray, insert); - VCALL_LOCALMEM1(PoolByteArray, remove); - VCALL_LOCALMEM1(PoolByteArray, append); - VCALL_LOCALMEM1(PoolByteArray, append_array); - VCALL_LOCALMEM0(PoolByteArray, invert); - VCALL_LOCALMEM2R(PoolByteArray, subarray); - - VCALL_LOCALMEM0R(PoolIntArray, size); - VCALL_LOCALMEM0R(PoolIntArray, empty); - VCALL_LOCALMEM2(PoolIntArray, set); - VCALL_LOCALMEM1R(PoolIntArray, get); - VCALL_LOCALMEM1(PoolIntArray, push_back); - VCALL_LOCALMEM1(PoolIntArray, resize); - VCALL_LOCALMEM2R(PoolIntArray, insert); - VCALL_LOCALMEM1(PoolIntArray, remove); - VCALL_LOCALMEM1(PoolIntArray, append); - VCALL_LOCALMEM1(PoolIntArray, append_array); - VCALL_LOCALMEM0(PoolIntArray, invert); - - VCALL_LOCALMEM0R(PoolRealArray, size); - VCALL_LOCALMEM0R(PoolRealArray, empty); - VCALL_LOCALMEM2(PoolRealArray, set); - VCALL_LOCALMEM1R(PoolRealArray, get); - VCALL_LOCALMEM1(PoolRealArray, push_back); - VCALL_LOCALMEM1(PoolRealArray, resize); - VCALL_LOCALMEM2R(PoolRealArray, insert); - VCALL_LOCALMEM1(PoolRealArray, remove); - VCALL_LOCALMEM1(PoolRealArray, append); - VCALL_LOCALMEM1(PoolRealArray, append_array); - VCALL_LOCALMEM0(PoolRealArray, invert); - - VCALL_LOCALMEM0R(PoolStringArray, size); - VCALL_LOCALMEM0R(PoolStringArray, empty); - VCALL_LOCALMEM2(PoolStringArray, set); - VCALL_LOCALMEM1R(PoolStringArray, get); - VCALL_LOCALMEM1(PoolStringArray, push_back); - VCALL_LOCALMEM1(PoolStringArray, resize); - VCALL_LOCALMEM2R(PoolStringArray, insert); - VCALL_LOCALMEM1(PoolStringArray, remove); - VCALL_LOCALMEM1(PoolStringArray, append); - VCALL_LOCALMEM1(PoolStringArray, append_array); - VCALL_LOCALMEM0(PoolStringArray, invert); - VCALL_LOCALMEM1R(PoolStringArray, join); - - VCALL_LOCALMEM0R(PoolVector2Array, size); - VCALL_LOCALMEM0R(PoolVector2Array, empty); - VCALL_LOCALMEM2(PoolVector2Array, set); - VCALL_LOCALMEM1R(PoolVector2Array, get); - VCALL_LOCALMEM1(PoolVector2Array, push_back); - VCALL_LOCALMEM1(PoolVector2Array, resize); - VCALL_LOCALMEM2R(PoolVector2Array, insert); - VCALL_LOCALMEM1(PoolVector2Array, remove); - VCALL_LOCALMEM1(PoolVector2Array, append); - VCALL_LOCALMEM1(PoolVector2Array, append_array); - VCALL_LOCALMEM0(PoolVector2Array, invert); - - VCALL_LOCALMEM0R(PoolVector3Array, size); - VCALL_LOCALMEM0R(PoolVector3Array, empty); - VCALL_LOCALMEM2(PoolVector3Array, set); - VCALL_LOCALMEM1R(PoolVector3Array, get); - VCALL_LOCALMEM1(PoolVector3Array, push_back); - VCALL_LOCALMEM1(PoolVector3Array, resize); - VCALL_LOCALMEM2R(PoolVector3Array, insert); - VCALL_LOCALMEM1(PoolVector3Array, remove); - VCALL_LOCALMEM1(PoolVector3Array, append); - VCALL_LOCALMEM1(PoolVector3Array, append_array); - VCALL_LOCALMEM0(PoolVector3Array, invert); - - VCALL_LOCALMEM0R(PoolColorArray, size); - VCALL_LOCALMEM0R(PoolColorArray, empty); - VCALL_LOCALMEM2(PoolColorArray, set); - VCALL_LOCALMEM1R(PoolColorArray, get); - VCALL_LOCALMEM1(PoolColorArray, push_back); - VCALL_LOCALMEM1(PoolColorArray, resize); - VCALL_LOCALMEM2R(PoolColorArray, insert); - VCALL_LOCALMEM1(PoolColorArray, remove); - VCALL_LOCALMEM1(PoolColorArray, append); - VCALL_LOCALMEM1(PoolColorArray, append_array); - VCALL_LOCALMEM0(PoolColorArray, invert); + VCALL_LOCALMEM0R(PackedByteArray, size); + VCALL_LOCALMEM0R(PackedByteArray, empty); + VCALL_LOCALMEM2(PackedByteArray, set); + VCALL_LOCALMEM1R(PackedByteArray, get); + VCALL_LOCALMEM1(PackedByteArray, push_back); + VCALL_LOCALMEM1(PackedByteArray, resize); + VCALL_LOCALMEM2R(PackedByteArray, insert); + VCALL_LOCALMEM1(PackedByteArray, remove); + VCALL_LOCALMEM1(PackedByteArray, append); + VCALL_LOCALMEM1(PackedByteArray, append_array); + VCALL_LOCALMEM0(PackedByteArray, invert); + VCALL_LOCALMEM2R(PackedByteArray, subarray); + + VCALL_LOCALMEM0R(PackedIntArray, size); + VCALL_LOCALMEM0R(PackedIntArray, empty); + VCALL_LOCALMEM2(PackedIntArray, set); + VCALL_LOCALMEM1R(PackedIntArray, get); + VCALL_LOCALMEM1(PackedIntArray, push_back); + VCALL_LOCALMEM1(PackedIntArray, resize); + VCALL_LOCALMEM2R(PackedIntArray, insert); + VCALL_LOCALMEM1(PackedIntArray, remove); + VCALL_LOCALMEM1(PackedIntArray, append); + VCALL_LOCALMEM1(PackedIntArray, append_array); + VCALL_LOCALMEM0(PackedIntArray, invert); + + VCALL_LOCALMEM0R(PackedRealArray, size); + VCALL_LOCALMEM0R(PackedRealArray, empty); + VCALL_LOCALMEM2(PackedRealArray, set); + VCALL_LOCALMEM1R(PackedRealArray, get); + VCALL_LOCALMEM1(PackedRealArray, push_back); + VCALL_LOCALMEM1(PackedRealArray, resize); + VCALL_LOCALMEM2R(PackedRealArray, insert); + VCALL_LOCALMEM1(PackedRealArray, remove); + VCALL_LOCALMEM1(PackedRealArray, append); + VCALL_LOCALMEM1(PackedRealArray, append_array); + VCALL_LOCALMEM0(PackedRealArray, invert); + + VCALL_LOCALMEM0R(PackedStringArray, size); + VCALL_LOCALMEM0R(PackedStringArray, empty); + VCALL_LOCALMEM2(PackedStringArray, set); + VCALL_LOCALMEM1R(PackedStringArray, get); + VCALL_LOCALMEM1(PackedStringArray, push_back); + VCALL_LOCALMEM1(PackedStringArray, resize); + VCALL_LOCALMEM2R(PackedStringArray, insert); + VCALL_LOCALMEM1(PackedStringArray, remove); + VCALL_LOCALMEM1(PackedStringArray, append); + VCALL_LOCALMEM1(PackedStringArray, append_array); + VCALL_LOCALMEM0(PackedStringArray, invert); + + VCALL_LOCALMEM0R(PackedVector2Array, size); + VCALL_LOCALMEM0R(PackedVector2Array, empty); + VCALL_LOCALMEM2(PackedVector2Array, set); + VCALL_LOCALMEM1R(PackedVector2Array, get); + VCALL_LOCALMEM1(PackedVector2Array, push_back); + VCALL_LOCALMEM1(PackedVector2Array, resize); + VCALL_LOCALMEM2R(PackedVector2Array, insert); + VCALL_LOCALMEM1(PackedVector2Array, remove); + VCALL_LOCALMEM1(PackedVector2Array, append); + VCALL_LOCALMEM1(PackedVector2Array, append_array); + VCALL_LOCALMEM0(PackedVector2Array, invert); + + VCALL_LOCALMEM0R(PackedVector3Array, size); + VCALL_LOCALMEM0R(PackedVector3Array, empty); + VCALL_LOCALMEM2(PackedVector3Array, set); + VCALL_LOCALMEM1R(PackedVector3Array, get); + VCALL_LOCALMEM1(PackedVector3Array, push_back); + VCALL_LOCALMEM1(PackedVector3Array, resize); + VCALL_LOCALMEM2R(PackedVector3Array, insert); + VCALL_LOCALMEM1(PackedVector3Array, remove); + VCALL_LOCALMEM1(PackedVector3Array, append); + VCALL_LOCALMEM1(PackedVector3Array, append_array); + VCALL_LOCALMEM0(PackedVector3Array, invert); + + VCALL_LOCALMEM0R(PackedColorArray, size); + VCALL_LOCALMEM0R(PackedColorArray, empty); + VCALL_LOCALMEM2(PackedColorArray, set); + VCALL_LOCALMEM1R(PackedColorArray, get); + VCALL_LOCALMEM1(PackedColorArray, push_back); + VCALL_LOCALMEM1(PackedColorArray, resize); + VCALL_LOCALMEM2R(PackedColorArray, insert); + VCALL_LOCALMEM1(PackedColorArray, remove); + VCALL_LOCALMEM1(PackedColorArray, append); + VCALL_LOCALMEM1(PackedColorArray, append_array); + VCALL_LOCALMEM0(PackedColorArray, invert); #define VCALL_PTR0(m_type, m_method) \ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(); } @@ -782,7 +778,7 @@ struct _VariantCall { case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Vector2()); return; case Variant::RECT2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Rect2()); return; - case Variant::POOL_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator PoolVector2Array()); return; + case Variant::PACKED_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator PackedVector2Array()); return; default: r_ret = Variant(); } } @@ -793,7 +789,7 @@ struct _VariantCall { case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector2()); return; case Variant::RECT2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Rect2()); return; - case Variant::POOL_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator PoolVector2Array()); return; + case Variant::PACKED_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator PackedVector2Array()); return; default: r_ret = Variant(); } } @@ -851,7 +847,7 @@ struct _VariantCall { case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Vector3()); return; case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Plane()); return; case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::AABB()); return; - case Variant::POOL_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::PoolVector3Array()); return; + case Variant::PACKED_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::PackedVector3Array()); return; default: r_ret = Variant(); } } @@ -863,7 +859,7 @@ struct _VariantCall { case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector3()); return; case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Plane()); return; case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::AABB()); return; - case Variant::POOL_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::PoolVector3Array()); return; + case Variant::PACKED_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::PackedVector3Array()); return; default: r_ret = Variant(); } } @@ -1100,12 +1096,9 @@ void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p return; } #ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) { - //only if debugging! - if (!ObjectDB::instance_validate(obj)) { - r_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL; - return; - } + if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { + r_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL; + return; } #endif @@ -1176,14 +1169,14 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i case DICTIONARY: return Dictionary(); case ARRAY: return Array(); // 20 - case POOL_BYTE_ARRAY: return PoolByteArray(); - case POOL_INT_ARRAY: return PoolIntArray(); - case POOL_REAL_ARRAY: return PoolRealArray(); - case POOL_STRING_ARRAY: return PoolStringArray(); - case POOL_VECTOR2_ARRAY: - return PoolVector2Array(); // 25 - case POOL_VECTOR3_ARRAY: return PoolVector3Array(); - case POOL_COLOR_ARRAY: return PoolColorArray(); + case PACKED_BYTE_ARRAY: return PackedByteArray(); + case PACKED_INT_ARRAY: return PackedIntArray(); + case PACKED_REAL_ARRAY: return PackedRealArray(); + case PACKED_STRING_ARRAY: return PackedStringArray(); + case PACKED_VECTOR2_ARRAY: + return PackedVector2Array(); // 25 + case PACKED_VECTOR3_ARRAY: return PackedVector3Array(); + case PACKED_COLOR_ARRAY: return PackedColorArray(); default: return Variant(); } @@ -1233,14 +1226,14 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i return p_args[0]->operator Array(); // 20 // arrays - case POOL_BYTE_ARRAY: return (PoolByteArray(*p_args[0])); - case POOL_INT_ARRAY: return (PoolIntArray(*p_args[0])); - case POOL_REAL_ARRAY: return (PoolRealArray(*p_args[0])); - case POOL_STRING_ARRAY: return (PoolStringArray(*p_args[0])); - case POOL_VECTOR2_ARRAY: - return (PoolVector2Array(*p_args[0])); // 25 - case POOL_VECTOR3_ARRAY: return (PoolVector3Array(*p_args[0])); - case POOL_COLOR_ARRAY: return (PoolColorArray(*p_args[0])); + case PACKED_BYTE_ARRAY: return (PackedByteArray(*p_args[0])); + case PACKED_INT_ARRAY: return (PackedIntArray(*p_args[0])); + case PACKED_REAL_ARRAY: return (PackedRealArray(*p_args[0])); + case PACKED_STRING_ARRAY: return (PackedStringArray(*p_args[0])); + case PACKED_VECTOR2_ARRAY: + return (PackedVector2Array(*p_args[0])); // 25 + case PACKED_VECTOR3_ARRAY: return (PackedVector3Array(*p_args[0])); + case PACKED_COLOR_ARRAY: return (PackedColorArray(*p_args[0])); default: return Variant(); } } else if (p_argcount >= 1) { @@ -1275,18 +1268,11 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i bool Variant::has_method(const StringName &p_method) const { if (type == OBJECT) { - Object *obj = operator Object *(); + Object *obj = get_validated_object(); if (!obj) return false; -#ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton()) { - if (ObjectDB::instance_validate(obj)) { -#endif - return obj->has_method(p_method); -#ifdef DEBUG_ENABLED - } - } -#endif + + return obj->has_method(p_method); } const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[type]; @@ -1554,7 +1540,7 @@ void register_variant_methods() { ADDFUNC1R(STRING, BOOL, String, ends_with, STRING, "text", varray()); ADDFUNC1R(STRING, BOOL, String, is_subsequence_of, STRING, "text", varray()); ADDFUNC1R(STRING, BOOL, String, is_subsequence_ofi, STRING, "text", varray()); - ADDFUNC0R(STRING, POOL_STRING_ARRAY, String, bigrams, varray()); + ADDFUNC0R(STRING, PACKED_STRING_ARRAY, String, bigrams, varray()); ADDFUNC1R(STRING, REAL, String, similarity, STRING, "text", varray()); ADDFUNC2R(STRING, STRING, String, format, NIL, "values", STRING, "placeholder", varray("{_}")); @@ -1563,9 +1549,9 @@ void register_variant_methods() { ADDFUNC1R(STRING, STRING, String, repeat, INT, "count", varray()); ADDFUNC2R(STRING, STRING, String, insert, INT, "position", STRING, "what", varray()); ADDFUNC0R(STRING, STRING, String, capitalize, varray()); - ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, split, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); - ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, rsplit, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); - ADDFUNC2R(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "delimiter", BOOL, "allow_empty", varray(true)); + ADDFUNC3R(STRING, PACKED_STRING_ARRAY, String, split, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); + ADDFUNC3R(STRING, PACKED_STRING_ARRAY, String, rsplit, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); + ADDFUNC2R(STRING, PACKED_REAL_ARRAY, String, split_floats, STRING, "delimiter", BOOL, "allow_empty", varray(true)); ADDFUNC0R(STRING, STRING, String, to_upper, varray()); ADDFUNC0R(STRING, STRING, String, to_lower, varray()); @@ -1586,9 +1572,9 @@ void register_variant_methods() { ADDFUNC0R(STRING, STRING, String, md5_text, varray()); ADDFUNC0R(STRING, STRING, String, sha1_text, varray()); ADDFUNC0R(STRING, STRING, String, sha256_text, varray()); - ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, md5_buffer, varray()); - ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, sha1_buffer, varray()); - ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, sha256_buffer, varray()); + ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, md5_buffer, varray()); + ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, sha1_buffer, varray()); + ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, sha256_buffer, varray()); ADDFUNC0R(STRING, BOOL, String, empty, varray()); ADDFUNC1R(STRING, STRING, String, humanize_size, INT, "size", varray()); ADDFUNC0R(STRING, BOOL, String, is_abs_path, varray()); @@ -1619,8 +1605,8 @@ void register_variant_methods() { ADDFUNC1R(STRING, STRING, String, trim_prefix, STRING, "prefix", varray()); ADDFUNC1R(STRING, STRING, String, trim_suffix, STRING, "suffix", varray()); - ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_ascii, varray()); - ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_utf8, varray()); + ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_ascii, varray()); + ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf8, varray()); ADDFUNC0R(VECTOR2, REAL, Vector2, angle, varray()); ADDFUNC1R(VECTOR2, REAL, Vector2, angle_to, VECTOR2, "to", varray()); @@ -1737,7 +1723,6 @@ void register_variant_methods() { ADDFUNC0R(COLOR, INT, Color, to_argb64, varray()); ADDFUNC0R(COLOR, INT, Color, to_abgr64, varray()); ADDFUNC0R(COLOR, INT, Color, to_rgba64, varray()); - ADDFUNC0R(COLOR, REAL, Color, gray, varray()); ADDFUNC0R(COLOR, COLOR, Color, inverted, varray()); ADDFUNC0R(COLOR, COLOR, Color, contrasted, varray()); ADDFUNC2R(COLOR, COLOR, Color, linear_interpolate, COLOR, "b", REAL, "t", varray()); @@ -1802,90 +1787,89 @@ void register_variant_methods() { ADDFUNC0R(ARRAY, NIL, Array, max, varray()); ADDFUNC0R(ARRAY, NIL, Array, min, varray()); - ADDFUNC0R(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray()); - ADDFUNC0R(POOL_BYTE_ARRAY, BOOL, PoolByteArray, empty, varray()); - ADDFUNC2(POOL_BYTE_ARRAY, NIL, PoolByteArray, set, INT, "idx", INT, "byte", varray()); - ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, push_back, INT, "byte", varray()); - ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, append, INT, "byte", varray()); - ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, append_array, POOL_BYTE_ARRAY, "array", varray()); - ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, remove, INT, "idx", varray()); - ADDFUNC2R(POOL_BYTE_ARRAY, INT, PoolByteArray, insert, INT, "idx", INT, "byte", varray()); - ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, resize, INT, "idx", varray()); - ADDFUNC0(POOL_BYTE_ARRAY, NIL, PoolByteArray, invert, varray()); - ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, subarray, INT, "from", INT, "to", varray()); - - ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray()); - ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray()); - ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, hex_encode, varray()); - ADDFUNC1R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0)); - ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0)); - - ADDFUNC0R(POOL_INT_ARRAY, INT, PoolIntArray, size, varray()); - ADDFUNC0R(POOL_INT_ARRAY, BOOL, PoolIntArray, empty, varray()); - ADDFUNC2(POOL_INT_ARRAY, NIL, PoolIntArray, set, INT, "idx", INT, "integer", varray()); - ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, push_back, INT, "integer", varray()); - ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, append, INT, "integer", varray()); - ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, append_array, POOL_INT_ARRAY, "array", varray()); - ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, remove, INT, "idx", varray()); - ADDFUNC2R(POOL_INT_ARRAY, INT, PoolIntArray, insert, INT, "idx", INT, "integer", varray()); - ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, resize, INT, "idx", varray()); - ADDFUNC0(POOL_INT_ARRAY, NIL, PoolIntArray, invert, varray()); - - ADDFUNC0R(POOL_REAL_ARRAY, INT, PoolRealArray, size, varray()); - ADDFUNC0R(POOL_REAL_ARRAY, BOOL, PoolRealArray, empty, varray()); - ADDFUNC2(POOL_REAL_ARRAY, NIL, PoolRealArray, set, INT, "idx", REAL, "value", varray()); - ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, push_back, REAL, "value", varray()); - ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, append, REAL, "value", varray()); - ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, append_array, POOL_REAL_ARRAY, "array", varray()); - ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, remove, INT, "idx", varray()); - ADDFUNC2R(POOL_REAL_ARRAY, INT, PoolRealArray, insert, INT, "idx", REAL, "value", varray()); - ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, resize, INT, "idx", varray()); - ADDFUNC0(POOL_REAL_ARRAY, NIL, PoolRealArray, invert, varray()); - - ADDFUNC0R(POOL_STRING_ARRAY, INT, PoolStringArray, size, varray()); - ADDFUNC0R(POOL_STRING_ARRAY, BOOL, PoolStringArray, empty, varray()); - ADDFUNC2(POOL_STRING_ARRAY, NIL, PoolStringArray, set, INT, "idx", STRING, "string", varray()); - ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, push_back, STRING, "string", varray()); - ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, append, STRING, "string", varray()); - ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, append_array, POOL_STRING_ARRAY, "array", varray()); - ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, remove, INT, "idx", varray()); - ADDFUNC2R(POOL_STRING_ARRAY, INT, PoolStringArray, insert, INT, "idx", STRING, "string", varray()); - ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, resize, INT, "idx", varray()); - ADDFUNC0(POOL_STRING_ARRAY, NIL, PoolStringArray, invert, varray()); - ADDFUNC1(POOL_STRING_ARRAY, STRING, PoolStringArray, join, STRING, "delimiter", varray()); - - ADDFUNC0R(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, size, varray()); - ADDFUNC0R(POOL_VECTOR2_ARRAY, BOOL, PoolVector2Array, empty, varray()); - ADDFUNC2(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, set, INT, "idx", VECTOR2, "vector2", varray()); - ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, push_back, VECTOR2, "vector2", varray()); - ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, append, VECTOR2, "vector2", varray()); - ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, append_array, POOL_VECTOR2_ARRAY, "array", varray()); - ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, remove, INT, "idx", varray()); - ADDFUNC2R(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, insert, INT, "idx", VECTOR2, "vector2", varray()); - ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, resize, INT, "idx", varray()); - ADDFUNC0(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, invert, varray()); - - ADDFUNC0R(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, size, varray()); - ADDFUNC0R(POOL_VECTOR3_ARRAY, BOOL, PoolVector3Array, empty, varray()); - ADDFUNC2(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, set, INT, "idx", VECTOR3, "vector3", varray()); - ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, push_back, VECTOR3, "vector3", varray()); - ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, append, VECTOR3, "vector3", varray()); - ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, append_array, POOL_VECTOR3_ARRAY, "array", varray()); - ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, remove, INT, "idx", varray()); - ADDFUNC2R(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, insert, INT, "idx", VECTOR3, "vector3", varray()); - ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, resize, INT, "idx", varray()); - ADDFUNC0(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, invert, varray()); - - ADDFUNC0R(POOL_COLOR_ARRAY, INT, PoolColorArray, size, varray()); - ADDFUNC0R(POOL_COLOR_ARRAY, BOOL, PoolColorArray, empty, varray()); - ADDFUNC2(POOL_COLOR_ARRAY, NIL, PoolColorArray, set, INT, "idx", COLOR, "color", varray()); - ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, push_back, COLOR, "color", varray()); - ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, append, COLOR, "color", varray()); - ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, append_array, POOL_COLOR_ARRAY, "array", varray()); - ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, remove, INT, "idx", varray()); - ADDFUNC2R(POOL_COLOR_ARRAY, INT, PoolColorArray, insert, INT, "idx", COLOR, "color", varray()); - ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, resize, INT, "idx", varray()); - ADDFUNC0(POOL_COLOR_ARRAY, NIL, PoolColorArray, invert, varray()); + ADDFUNC0R(PACKED_BYTE_ARRAY, INT, PackedByteArray, size, varray()); + ADDFUNC0R(PACKED_BYTE_ARRAY, BOOL, PackedByteArray, empty, varray()); + ADDFUNC2(PACKED_BYTE_ARRAY, NIL, PackedByteArray, set, INT, "idx", INT, "byte", varray()); + ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, push_back, INT, "byte", varray()); + ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, append, INT, "byte", varray()); + ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, append_array, PACKED_BYTE_ARRAY, "array", varray()); + ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, remove, INT, "idx", varray()); + ADDFUNC2R(PACKED_BYTE_ARRAY, INT, PackedByteArray, insert, INT, "idx", INT, "byte", varray()); + ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, resize, INT, "idx", varray()); + ADDFUNC0(PACKED_BYTE_ARRAY, NIL, PackedByteArray, invert, varray()); + ADDFUNC2R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, subarray, INT, "from", INT, "to", varray()); + + ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_ascii, varray()); + ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf8, varray()); + ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, hex_encode, varray()); + ADDFUNC1R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, compress, INT, "compression_mode", varray(0)); + ADDFUNC2R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0)); + + ADDFUNC0R(PACKED_INT_ARRAY, INT, PackedIntArray, size, varray()); + ADDFUNC0R(PACKED_INT_ARRAY, BOOL, PackedIntArray, empty, varray()); + ADDFUNC2(PACKED_INT_ARRAY, NIL, PackedIntArray, set, INT, "idx", INT, "integer", varray()); + ADDFUNC1(PACKED_INT_ARRAY, NIL, PackedIntArray, push_back, INT, "integer", varray()); + ADDFUNC1(PACKED_INT_ARRAY, NIL, PackedIntArray, append, INT, "integer", varray()); + ADDFUNC1(PACKED_INT_ARRAY, NIL, PackedIntArray, append_array, PACKED_INT_ARRAY, "array", varray()); + ADDFUNC1(PACKED_INT_ARRAY, NIL, PackedIntArray, remove, INT, "idx", varray()); + ADDFUNC2R(PACKED_INT_ARRAY, INT, PackedIntArray, insert, INT, "idx", INT, "integer", varray()); + ADDFUNC1(PACKED_INT_ARRAY, NIL, PackedIntArray, resize, INT, "idx", varray()); + ADDFUNC0(PACKED_INT_ARRAY, NIL, PackedIntArray, invert, varray()); + + ADDFUNC0R(PACKED_REAL_ARRAY, INT, PackedRealArray, size, varray()); + ADDFUNC0R(PACKED_REAL_ARRAY, BOOL, PackedRealArray, empty, varray()); + ADDFUNC2(PACKED_REAL_ARRAY, NIL, PackedRealArray, set, INT, "idx", REAL, "value", varray()); + ADDFUNC1(PACKED_REAL_ARRAY, NIL, PackedRealArray, push_back, REAL, "value", varray()); + ADDFUNC1(PACKED_REAL_ARRAY, NIL, PackedRealArray, append, REAL, "value", varray()); + ADDFUNC1(PACKED_REAL_ARRAY, NIL, PackedRealArray, append_array, PACKED_REAL_ARRAY, "array", varray()); + ADDFUNC1(PACKED_REAL_ARRAY, NIL, PackedRealArray, remove, INT, "idx", varray()); + ADDFUNC2R(PACKED_REAL_ARRAY, INT, PackedRealArray, insert, INT, "idx", REAL, "value", varray()); + ADDFUNC1(PACKED_REAL_ARRAY, NIL, PackedRealArray, resize, INT, "idx", varray()); + ADDFUNC0(PACKED_REAL_ARRAY, NIL, PackedRealArray, invert, varray()); + + ADDFUNC0R(PACKED_STRING_ARRAY, INT, PackedStringArray, size, varray()); + ADDFUNC0R(PACKED_STRING_ARRAY, BOOL, PackedStringArray, empty, varray()); + ADDFUNC2(PACKED_STRING_ARRAY, NIL, PackedStringArray, set, INT, "idx", STRING, "string", varray()); + ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, push_back, STRING, "string", varray()); + ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, append, STRING, "string", varray()); + ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, append_array, PACKED_STRING_ARRAY, "array", varray()); + ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, remove, INT, "idx", varray()); + ADDFUNC2R(PACKED_STRING_ARRAY, INT, PackedStringArray, insert, INT, "idx", STRING, "string", varray()); + ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, resize, INT, "idx", varray()); + ADDFUNC0(PACKED_STRING_ARRAY, NIL, PackedStringArray, invert, varray()); + + ADDFUNC0R(PACKED_VECTOR2_ARRAY, INT, PackedVector2Array, size, varray()); + ADDFUNC0R(PACKED_VECTOR2_ARRAY, BOOL, PackedVector2Array, empty, varray()); + ADDFUNC2(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, set, INT, "idx", VECTOR2, "vector2", varray()); + ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, push_back, VECTOR2, "vector2", varray()); + ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, append, VECTOR2, "vector2", varray()); + ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, append_array, PACKED_VECTOR2_ARRAY, "array", varray()); + ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, remove, INT, "idx", varray()); + ADDFUNC2R(PACKED_VECTOR2_ARRAY, INT, PackedVector2Array, insert, INT, "idx", VECTOR2, "vector2", varray()); + ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, resize, INT, "idx", varray()); + ADDFUNC0(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, invert, varray()); + + ADDFUNC0R(PACKED_VECTOR3_ARRAY, INT, PackedVector3Array, size, varray()); + ADDFUNC0R(PACKED_VECTOR3_ARRAY, BOOL, PackedVector3Array, empty, varray()); + ADDFUNC2(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, set, INT, "idx", VECTOR3, "vector3", varray()); + ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, push_back, VECTOR3, "vector3", varray()); + ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, append, VECTOR3, "vector3", varray()); + ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, append_array, PACKED_VECTOR3_ARRAY, "array", varray()); + ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, remove, INT, "idx", varray()); + ADDFUNC2R(PACKED_VECTOR3_ARRAY, INT, PackedVector3Array, insert, INT, "idx", VECTOR3, "vector3", varray()); + ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, resize, INT, "idx", varray()); + ADDFUNC0(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, invert, varray()); + + ADDFUNC0R(PACKED_COLOR_ARRAY, INT, PackedColorArray, size, varray()); + ADDFUNC0R(PACKED_COLOR_ARRAY, BOOL, PackedColorArray, empty, varray()); + ADDFUNC2(PACKED_COLOR_ARRAY, NIL, PackedColorArray, set, INT, "idx", COLOR, "color", varray()); + ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, push_back, COLOR, "color", varray()); + ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, append, COLOR, "color", varray()); + ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, append_array, PACKED_COLOR_ARRAY, "array", varray()); + ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, remove, INT, "idx", varray()); + ADDFUNC2R(PACKED_COLOR_ARRAY, INT, PackedColorArray, insert, INT, "idx", COLOR, "color", varray()); + ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, resize, INT, "idx", varray()); + ADDFUNC0(PACKED_COLOR_ARRAY, NIL, PackedColorArray, invert, varray()); //pointerbased diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 6caa224cfe..566c87dac1 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -38,33 +38,33 @@ CASE_TYPE(PREFIX, OP, INT) \ CASE_TYPE_ALL_BUT_INT(PREFIX, OP) -#define CASE_TYPE_ALL_BUT_INT(PREFIX, OP) \ - CASE_TYPE(PREFIX, OP, NIL) \ - CASE_TYPE(PREFIX, OP, BOOL) \ - CASE_TYPE(PREFIX, OP, REAL) \ - CASE_TYPE(PREFIX, OP, STRING) \ - CASE_TYPE(PREFIX, OP, VECTOR2) \ - CASE_TYPE(PREFIX, OP, RECT2) \ - CASE_TYPE(PREFIX, OP, VECTOR3) \ - CASE_TYPE(PREFIX, OP, TRANSFORM2D) \ - CASE_TYPE(PREFIX, OP, PLANE) \ - CASE_TYPE(PREFIX, OP, QUAT) \ - CASE_TYPE(PREFIX, OP, AABB) \ - CASE_TYPE(PREFIX, OP, BASIS) \ - CASE_TYPE(PREFIX, OP, TRANSFORM) \ - CASE_TYPE(PREFIX, OP, COLOR) \ - CASE_TYPE(PREFIX, OP, NODE_PATH) \ - CASE_TYPE(PREFIX, OP, _RID) \ - CASE_TYPE(PREFIX, OP, OBJECT) \ - CASE_TYPE(PREFIX, OP, DICTIONARY) \ - CASE_TYPE(PREFIX, OP, ARRAY) \ - CASE_TYPE(PREFIX, OP, POOL_BYTE_ARRAY) \ - CASE_TYPE(PREFIX, OP, POOL_INT_ARRAY) \ - CASE_TYPE(PREFIX, OP, POOL_REAL_ARRAY) \ - CASE_TYPE(PREFIX, OP, POOL_STRING_ARRAY) \ - CASE_TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY) \ - CASE_TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY) \ - CASE_TYPE(PREFIX, OP, POOL_COLOR_ARRAY) +#define CASE_TYPE_ALL_BUT_INT(PREFIX, OP) \ + CASE_TYPE(PREFIX, OP, NIL) \ + CASE_TYPE(PREFIX, OP, BOOL) \ + CASE_TYPE(PREFIX, OP, REAL) \ + CASE_TYPE(PREFIX, OP, STRING) \ + CASE_TYPE(PREFIX, OP, VECTOR2) \ + CASE_TYPE(PREFIX, OP, RECT2) \ + CASE_TYPE(PREFIX, OP, VECTOR3) \ + CASE_TYPE(PREFIX, OP, TRANSFORM2D) \ + CASE_TYPE(PREFIX, OP, PLANE) \ + CASE_TYPE(PREFIX, OP, QUAT) \ + CASE_TYPE(PREFIX, OP, AABB) \ + CASE_TYPE(PREFIX, OP, BASIS) \ + CASE_TYPE(PREFIX, OP, TRANSFORM) \ + CASE_TYPE(PREFIX, OP, COLOR) \ + CASE_TYPE(PREFIX, OP, NODE_PATH) \ + CASE_TYPE(PREFIX, OP, _RID) \ + CASE_TYPE(PREFIX, OP, OBJECT) \ + CASE_TYPE(PREFIX, OP, DICTIONARY) \ + CASE_TYPE(PREFIX, OP, ARRAY) \ + CASE_TYPE(PREFIX, OP, PACKED_BYTE_ARRAY) \ + CASE_TYPE(PREFIX, OP, PACKED_INT_ARRAY) \ + CASE_TYPE(PREFIX, OP, PACKED_REAL_ARRAY) \ + CASE_TYPE(PREFIX, OP, PACKED_STRING_ARRAY) \ + CASE_TYPE(PREFIX, OP, PACKED_VECTOR2_ARRAY) \ + CASE_TYPE(PREFIX, OP, PACKED_VECTOR3_ARRAY) \ + CASE_TYPE(PREFIX, OP, PACKED_COLOR_ARRAY) #ifdef __GNUC__ #define TYPE(PREFIX, OP, TYPE) &&PREFIX##_##OP##_##TYPE @@ -91,13 +91,13 @@ TYPE(PREFIX, OP, OBJECT), \ TYPE(PREFIX, OP, DICTIONARY), \ TYPE(PREFIX, OP, ARRAY), \ - TYPE(PREFIX, OP, POOL_BYTE_ARRAY), \ - TYPE(PREFIX, OP, POOL_INT_ARRAY), \ - TYPE(PREFIX, OP, POOL_REAL_ARRAY), \ - TYPE(PREFIX, OP, POOL_STRING_ARRAY), \ - TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY), \ - TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY), \ - TYPE(PREFIX, OP, POOL_COLOR_ARRAY), \ + TYPE(PREFIX, OP, PACKED_BYTE_ARRAY), \ + TYPE(PREFIX, OP, PACKED_INT_ARRAY), \ + TYPE(PREFIX, OP, PACKED_REAL_ARRAY), \ + TYPE(PREFIX, OP, PACKED_STRING_ARRAY), \ + TYPE(PREFIX, OP, PACKED_VECTOR2_ARRAY), \ + TYPE(PREFIX, OP, PACKED_VECTOR3_ARRAY), \ + TYPE(PREFIX, OP, PACKED_COLOR_ARRAY), \ } /* clang-format on */ @@ -357,16 +357,16 @@ bool Variant::booleanize() const { if (p_a.type != p_b.type) \ _RETURN_FAIL \ \ - const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \ - const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \ + const Vector<m_type> &array_a = *reinterpret_cast<const Vector<m_type> *>(p_a._data._mem); \ + const Vector<m_type> &array_b = *reinterpret_cast<const Vector<m_type> *>(p_b._data._mem); \ \ int a_len = array_a.size(); \ if (a_len m_opa array_b.size()) { \ _RETURN(m_ret_s); \ } else { \ \ - PoolVector<m_type>::Read ra = array_a.read(); \ - PoolVector<m_type>::Read rb = array_b.read(); \ + const m_type *ra = array_a.ptr(); \ + const m_type *rb = array_b.ptr(); \ \ for (int i = 0; i < a_len; i++) { \ if (ra[i] m_opb rb[i]) \ @@ -376,16 +376,16 @@ bool Variant::booleanize() const { _RETURN(m_ret_def); \ } -#define DEFAULT_OP_ARRAY_ADD(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_a.type != p_b.type) \ - _RETURN_FAIL; \ - \ - const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \ - const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \ - PoolVector<m_type> sum = array_a; \ - sum.append_array(array_b); \ - _RETURN(sum); \ +#define DEFAULT_OP_ARRAY_ADD(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_a.type != p_b.type) \ + _RETURN_FAIL; \ + \ + const Vector<m_type> &array_a = *reinterpret_cast<const Vector<m_type> *>(p_a._data._mem); \ + const Vector<m_type> &array_b = *reinterpret_cast<const Vector<m_type> *>(p_b._data._mem); \ + Vector<m_type> sum = array_a; \ + sum.append_array(array_b); \ + _RETURN(sum); \ } void Variant::evaluate(const Operator &p_op, const Variant &p_a, @@ -473,13 +473,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, DEFAULT_OP_STR_NULL(math, OP_EQUAL, NODE_PATH, ==, NodePath); DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, _RID, ==, RID); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR2_ARRAY, Vector2); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_COLOR_ARRAY, Color); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_INT_ARRAY, int); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_VECTOR2_ARRAY, Vector2); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_COLOR_ARRAY, Color); } SWITCH_OP(math, OP_NOT_EQUAL, p_a.type) { @@ -563,13 +563,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, DEFAULT_OP_STR_NULL(math, OP_NOT_EQUAL, NODE_PATH, !=, NodePath); DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, _RID, !=, RID); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_VECTOR2_ARRAY, Vector2); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_COLOR_ARRAY, Color); + DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_INT_ARRAY, int); + DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_VECTOR2_ARRAY, Vector2); + DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_COLOR_ARRAY, Color); } SWITCH_OP(math, OP_LESS, p_a.type) { @@ -617,13 +617,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2, <, Vector2); DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3, <, Vector3); DEFAULT_OP_LOCALMEM(math, OP_LESS, _RID, <, RID); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR2_ARRAY, Vector3); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_COLOR_ARRAY, Color); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_INT_ARRAY, int); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_VECTOR2_ARRAY, Vector3); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_COLOR_ARRAY, Color); CASE_TYPE(math, OP_LESS, NIL) CASE_TYPE(math, OP_LESS, RECT2) @@ -666,13 +666,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, CASE_TYPE(math, OP_LESS_EQUAL, NODE_PATH) CASE_TYPE(math, OP_LESS_EQUAL, DICTIONARY) CASE_TYPE(math, OP_LESS_EQUAL, ARRAY) - CASE_TYPE(math, OP_LESS_EQUAL, POOL_BYTE_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, POOL_INT_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, POOL_REAL_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, POOL_STRING_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR2_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR3_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, POOL_COLOR_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, PACKED_BYTE_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, PACKED_INT_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, PACKED_REAL_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, PACKED_STRING_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, PACKED_VECTOR2_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, PACKED_VECTOR3_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, PACKED_COLOR_ARRAY); _RETURN_FAIL; } @@ -721,13 +721,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2, <, Vector2); DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3, <, Vector3); DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, _RID, <, RID); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR2_ARRAY, Vector3); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_COLOR_ARRAY, Color); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_INT_ARRAY, int); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_VECTOR2_ARRAY, Vector3); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_COLOR_ARRAY, Color); CASE_TYPE(math, OP_GREATER, NIL) CASE_TYPE(math, OP_GREATER, RECT2) @@ -770,13 +770,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, CASE_TYPE(math, OP_GREATER_EQUAL, NODE_PATH) CASE_TYPE(math, OP_GREATER_EQUAL, DICTIONARY) CASE_TYPE(math, OP_GREATER_EQUAL, ARRAY) - CASE_TYPE(math, OP_GREATER_EQUAL, POOL_BYTE_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, POOL_INT_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, POOL_REAL_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, POOL_STRING_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR2_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR3_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, POOL_COLOR_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_BYTE_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_INT_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_REAL_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_STRING_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_VECTOR2_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_VECTOR3_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_COLOR_ARRAY); _RETURN_FAIL; } @@ -806,13 +806,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, DEFAULT_OP_LOCALMEM(math, OP_ADD, QUAT, +, Quat); DEFAULT_OP_LOCALMEM(math, OP_ADD, COLOR, +, Color); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR2_ARRAY, Vector2); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_COLOR_ARRAY, Color); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_INT_ARRAY, int); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_VECTOR2_ARRAY, Vector2); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_COLOR_ARRAY, Color); CASE_TYPE(math, OP_ADD, NIL) CASE_TYPE(math, OP_ADD, BOOL) @@ -851,13 +851,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, CASE_TYPE(math, OP_SUBTRACT, OBJECT) CASE_TYPE(math, OP_SUBTRACT, DICTIONARY) CASE_TYPE(math, OP_SUBTRACT, ARRAY) - CASE_TYPE(math, OP_SUBTRACT, POOL_BYTE_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, POOL_INT_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, POOL_REAL_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, POOL_STRING_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR2_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR3_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, POOL_COLOR_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, PACKED_BYTE_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, PACKED_INT_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, PACKED_REAL_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, PACKED_STRING_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, PACKED_VECTOR2_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, PACKED_VECTOR3_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, PACKED_COLOR_ARRAY); _RETURN_FAIL; } @@ -930,13 +930,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, CASE_TYPE(math, OP_MULTIPLY, OBJECT) CASE_TYPE(math, OP_MULTIPLY, DICTIONARY) CASE_TYPE(math, OP_MULTIPLY, ARRAY) - CASE_TYPE(math, OP_MULTIPLY, POOL_BYTE_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, POOL_INT_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, POOL_REAL_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, POOL_STRING_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR2_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR3_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, POOL_COLOR_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, PACKED_BYTE_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, PACKED_INT_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, PACKED_REAL_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, PACKED_STRING_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, PACKED_VECTOR2_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, PACKED_VECTOR3_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, PACKED_COLOR_ARRAY); _RETURN_FAIL; } @@ -973,13 +973,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, CASE_TYPE(math, OP_DIVIDE, OBJECT) CASE_TYPE(math, OP_DIVIDE, DICTIONARY) CASE_TYPE(math, OP_DIVIDE, ARRAY) - CASE_TYPE(math, OP_DIVIDE, POOL_BYTE_ARRAY); - CASE_TYPE(math, OP_DIVIDE, POOL_INT_ARRAY); - CASE_TYPE(math, OP_DIVIDE, POOL_REAL_ARRAY); - CASE_TYPE(math, OP_DIVIDE, POOL_STRING_ARRAY); - CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR2_ARRAY); - CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR3_ARRAY); - CASE_TYPE(math, OP_DIVIDE, POOL_COLOR_ARRAY); + CASE_TYPE(math, OP_DIVIDE, PACKED_BYTE_ARRAY); + CASE_TYPE(math, OP_DIVIDE, PACKED_INT_ARRAY); + CASE_TYPE(math, OP_DIVIDE, PACKED_REAL_ARRAY); + CASE_TYPE(math, OP_DIVIDE, PACKED_STRING_ARRAY); + CASE_TYPE(math, OP_DIVIDE, PACKED_VECTOR2_ARRAY); + CASE_TYPE(math, OP_DIVIDE, PACKED_VECTOR3_ARRAY); + CASE_TYPE(math, OP_DIVIDE, PACKED_COLOR_ARRAY); _RETURN_FAIL; } @@ -1005,13 +1005,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, CASE_TYPE(math, OP_POSITIVE, OBJECT) CASE_TYPE(math, OP_POSITIVE, DICTIONARY) CASE_TYPE(math, OP_POSITIVE, ARRAY) - CASE_TYPE(math, OP_POSITIVE, POOL_BYTE_ARRAY) - CASE_TYPE(math, OP_POSITIVE, POOL_INT_ARRAY) - CASE_TYPE(math, OP_POSITIVE, POOL_REAL_ARRAY) - CASE_TYPE(math, OP_POSITIVE, POOL_STRING_ARRAY) - CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR2_ARRAY) - CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR3_ARRAY) - CASE_TYPE(math, OP_POSITIVE, POOL_COLOR_ARRAY) + CASE_TYPE(math, OP_POSITIVE, PACKED_BYTE_ARRAY) + CASE_TYPE(math, OP_POSITIVE, PACKED_INT_ARRAY) + CASE_TYPE(math, OP_POSITIVE, PACKED_REAL_ARRAY) + CASE_TYPE(math, OP_POSITIVE, PACKED_STRING_ARRAY) + CASE_TYPE(math, OP_POSITIVE, PACKED_VECTOR2_ARRAY) + CASE_TYPE(math, OP_POSITIVE, PACKED_VECTOR3_ARRAY) + CASE_TYPE(math, OP_POSITIVE, PACKED_COLOR_ARRAY) _RETURN_FAIL; } @@ -1038,13 +1038,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, CASE_TYPE(math, OP_NEGATE, OBJECT) CASE_TYPE(math, OP_NEGATE, DICTIONARY) CASE_TYPE(math, OP_NEGATE, ARRAY) - CASE_TYPE(math, OP_NEGATE, POOL_BYTE_ARRAY) - CASE_TYPE(math, OP_NEGATE, POOL_INT_ARRAY) - CASE_TYPE(math, OP_NEGATE, POOL_REAL_ARRAY) - CASE_TYPE(math, OP_NEGATE, POOL_STRING_ARRAY) - CASE_TYPE(math, OP_NEGATE, POOL_VECTOR2_ARRAY) - CASE_TYPE(math, OP_NEGATE, POOL_VECTOR3_ARRAY) - CASE_TYPE(math, OP_NEGATE, POOL_COLOR_ARRAY) + CASE_TYPE(math, OP_NEGATE, PACKED_BYTE_ARRAY) + CASE_TYPE(math, OP_NEGATE, PACKED_INT_ARRAY) + CASE_TYPE(math, OP_NEGATE, PACKED_REAL_ARRAY) + CASE_TYPE(math, OP_NEGATE, PACKED_STRING_ARRAY) + CASE_TYPE(math, OP_NEGATE, PACKED_VECTOR2_ARRAY) + CASE_TYPE(math, OP_NEGATE, PACKED_VECTOR3_ARRAY) + CASE_TYPE(math, OP_NEGATE, PACKED_COLOR_ARRAY) _RETURN_FAIL; } @@ -1098,13 +1098,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, CASE_TYPE(math, OP_MODULE, OBJECT) CASE_TYPE(math, OP_MODULE, DICTIONARY) CASE_TYPE(math, OP_MODULE, ARRAY) - CASE_TYPE(math, OP_MODULE, POOL_BYTE_ARRAY) - CASE_TYPE(math, OP_MODULE, POOL_INT_ARRAY) - CASE_TYPE(math, OP_MODULE, POOL_REAL_ARRAY) - CASE_TYPE(math, OP_MODULE, POOL_STRING_ARRAY) - CASE_TYPE(math, OP_MODULE, POOL_VECTOR2_ARRAY) - CASE_TYPE(math, OP_MODULE, POOL_VECTOR3_ARRAY) - CASE_TYPE(math, OP_MODULE, POOL_COLOR_ARRAY) + CASE_TYPE(math, OP_MODULE, PACKED_BYTE_ARRAY) + CASE_TYPE(math, OP_MODULE, PACKED_INT_ARRAY) + CASE_TYPE(math, OP_MODULE, PACKED_REAL_ARRAY) + CASE_TYPE(math, OP_MODULE, PACKED_STRING_ARRAY) + CASE_TYPE(math, OP_MODULE, PACKED_VECTOR2_ARRAY) + CASE_TYPE(math, OP_MODULE, PACKED_VECTOR3_ARRAY) + CASE_TYPE(math, OP_MODULE, PACKED_COLOR_ARRAY) _RETURN_FAIL; } @@ -1515,7 +1515,7 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool #ifdef DEBUG_ENABLED if (!_get_obj().obj) { break; - } else if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) { + } else if (ScriptDebugger::get_singleton() && ObjectDB::get_instance(_get_obj().id) == nullptr) { break; } @@ -1684,7 +1684,7 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { return "Instance base is null."; } else { - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) { + if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { if (r_valid) *r_valid = false; return "Attempted use of stray pointer object."; @@ -1725,10 +1725,10 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; #define DEFAULT_OP_DVECTOR_SET(m_name, dv_type, skip_cond) \ - DEFAULT_OP_ARRAY_CMD(m_name, PoolVector<dv_type>, if (skip_cond) return;, arr->set(index, p_value); return ) + DEFAULT_OP_ARRAY_CMD(m_name, Vector<dv_type>, if (skip_cond) return;, arr->set(index, p_value); return ) #define DEFAULT_OP_DVECTOR_GET(m_name, dv_type) \ - DEFAULT_OP_ARRAY_CMD(m_name, const PoolVector<dv_type>, ;, return arr->get(index)) + DEFAULT_OP_ARRAY_CMD(m_name, const Vector<dv_type>, ;, return arr->get(index)) void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) { @@ -2172,13 +2172,11 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) if (obj) { #ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) { + if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - if (!ObjectDB::instance_validate(obj)) { - WARN_PRINT("Attempted use of stray pointer object."); - valid = false; - return; - } + WARN_PRINT("Attempted use of previously freed pointer object."); + valid = false; + return; } #endif @@ -2199,13 +2197,13 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) return; } break; DEFAULT_OP_ARRAY_CMD(ARRAY, Array, ;, (*arr)[index] = p_value; return ) // 20 - DEFAULT_OP_DVECTOR_SET(POOL_BYTE_ARRAY, uint8_t, p_value.type != Variant::REAL && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(POOL_INT_ARRAY, int, p_value.type != Variant::REAL && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(POOL_REAL_ARRAY, real_t, p_value.type != Variant::REAL && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(POOL_STRING_ARRAY, String, p_value.type != Variant::STRING) - DEFAULT_OP_DVECTOR_SET(POOL_VECTOR2_ARRAY, Vector2, p_value.type != Variant::VECTOR2) // 25 - DEFAULT_OP_DVECTOR_SET(POOL_VECTOR3_ARRAY, Vector3, p_value.type != Variant::VECTOR3) - DEFAULT_OP_DVECTOR_SET(POOL_COLOR_ARRAY, Color, p_value.type != Variant::COLOR) + DEFAULT_OP_DVECTOR_SET(PACKED_BYTE_ARRAY, uint8_t, p_value.type != Variant::REAL && p_value.type != Variant::INT) + DEFAULT_OP_DVECTOR_SET(PACKED_INT_ARRAY, int, p_value.type != Variant::REAL && p_value.type != Variant::INT) + DEFAULT_OP_DVECTOR_SET(PACKED_REAL_ARRAY, real_t, p_value.type != Variant::REAL && p_value.type != Variant::INT) + DEFAULT_OP_DVECTOR_SET(PACKED_STRING_ARRAY, String, p_value.type != Variant::STRING) + DEFAULT_OP_DVECTOR_SET(PACKED_VECTOR2_ARRAY, Vector2, p_value.type != Variant::VECTOR2) // 25 + DEFAULT_OP_DVECTOR_SET(PACKED_VECTOR3_ARRAY, Vector3, p_value.type != Variant::VECTOR3) + DEFAULT_OP_DVECTOR_SET(PACKED_COLOR_ARRAY, Color, p_value.type != Variant::COLOR) default: return; } @@ -2546,12 +2544,10 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { if (obj) { #ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) { - //only if debugging! - if (!ObjectDB::instance_validate(obj)) { - valid = false; - return "Attempted get on stray pointer."; - } + + if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { + valid = false; + return "Attempted get on previously freed instance."; } #endif @@ -2573,13 +2569,13 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } } break; DEFAULT_OP_ARRAY_CMD(ARRAY, const Array, ;, return (*arr)[index]) // 20 - DEFAULT_OP_DVECTOR_GET(POOL_BYTE_ARRAY, uint8_t) - DEFAULT_OP_DVECTOR_GET(POOL_INT_ARRAY, int) - DEFAULT_OP_DVECTOR_GET(POOL_REAL_ARRAY, real_t) - DEFAULT_OP_DVECTOR_GET(POOL_STRING_ARRAY, String) - DEFAULT_OP_DVECTOR_GET(POOL_VECTOR2_ARRAY, Vector2) // 25 - DEFAULT_OP_DVECTOR_GET(POOL_VECTOR3_ARRAY, Vector3) - DEFAULT_OP_DVECTOR_GET(POOL_COLOR_ARRAY, Color) + DEFAULT_OP_DVECTOR_GET(PACKED_BYTE_ARRAY, uint8_t) + DEFAULT_OP_DVECTOR_GET(PACKED_INT_ARRAY, int) + DEFAULT_OP_DVECTOR_GET(PACKED_REAL_ARRAY, real_t) + DEFAULT_OP_DVECTOR_GET(PACKED_STRING_ARRAY, String) + DEFAULT_OP_DVECTOR_GET(PACKED_VECTOR2_ARRAY, Vector2) // 25 + DEFAULT_OP_DVECTOR_GET(PACKED_VECTOR3_ARRAY, Vector3) + DEFAULT_OP_DVECTOR_GET(PACKED_COLOR_ARRAY, Color) default: return Variant(); } @@ -2611,15 +2607,14 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { bool valid = false; #ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) { - //only if debugging! - if (!ObjectDB::instance_validate(obj)) { - if (r_valid) { - *r_valid = false; - } - return true; // Attempted get on stray pointer. + + if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { + if (r_valid) { + *r_valid = false; } + return true; // Attempted get on stray pointer. } + #endif if (p_index.get_type() != Variant::STRING) { @@ -2656,14 +2651,14 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { return false; } break; - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) { int index = p_index; - const PoolVector<uint8_t> *arr = reinterpret_cast<const PoolVector<uint8_t> *>(_data._mem); + const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem); int l = arr->size(); if (l) { - PoolVector<uint8_t>::Read r = arr->read(); + const uint8_t *r = arr->ptr(); for (int i = 0; i < l; i++) { if (r[i] == index) return true; @@ -2674,14 +2669,14 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } } break; - case POOL_INT_ARRAY: { + case PACKED_INT_ARRAY: { if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) { int index = p_index; - const PoolVector<int> *arr = reinterpret_cast<const PoolVector<int> *>(_data._mem); + const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem); int l = arr->size(); if (l) { - PoolVector<int>::Read r = arr->read(); + const int *r = arr->ptr(); for (int i = 0; i < l; i++) { if (r[i] == index) return true; @@ -2691,15 +2686,15 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { return false; } } break; - case POOL_REAL_ARRAY: { + case PACKED_REAL_ARRAY: { if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) { real_t index = p_index; - const PoolVector<real_t> *arr = reinterpret_cast<const PoolVector<real_t> *>(_data._mem); + const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem); int l = arr->size(); if (l) { - PoolVector<real_t>::Read r = arr->read(); + const real_t *r = arr->ptr(); for (int i = 0; i < l; i++) { if (r[i] == index) return true; @@ -2710,15 +2705,15 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } } break; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { if (p_index.get_type() == Variant::STRING) { String index = p_index; - const PoolVector<String> *arr = reinterpret_cast<const PoolVector<String> *>(_data._mem); + const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem); int l = arr->size(); if (l) { - PoolVector<String>::Read r = arr->read(); + const String *r = arr->ptr(); for (int i = 0; i < l; i++) { if (r[i] == index) return true; @@ -2729,15 +2724,15 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } } break; //25 - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { if (p_index.get_type() == Variant::VECTOR2) { Vector2 index = p_index; - const PoolVector<Vector2> *arr = reinterpret_cast<const PoolVector<Vector2> *>(_data._mem); + const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem); int l = arr->size(); if (l) { - PoolVector<Vector2>::Read r = arr->read(); + const Vector2 *r = arr->ptr(); for (int i = 0; i < l; i++) { if (r[i] == index) return true; @@ -2748,15 +2743,15 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { if (p_index.get_type() == Variant::VECTOR3) { Vector3 index = p_index; - const PoolVector<Vector3> *arr = reinterpret_cast<const PoolVector<Vector3> *>(_data._mem); + const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem); int l = arr->size(); if (l) { - PoolVector<Vector3>::Read r = arr->read(); + const Vector3 *r = arr->ptr(); for (int i = 0; i < l; i++) { if (r[i] == index) return true; @@ -2767,16 +2762,16 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { if (p_index.get_type() == Variant::COLOR) { Color index = p_index; - const PoolVector<Color> *arr = reinterpret_cast<const PoolVector<Color> *>(_data._mem); + const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem); int l = arr->size(); if (l) { - PoolVector<Color>::Read r = arr->read(); + const Color *r = arr->ptr(); for (int i = 0; i < l; i++) { if (r[i] == index) return true; @@ -2883,13 +2878,12 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { Object *obj = _get_obj().obj; if (obj) { #ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) { - //only if debugging! - if (!ObjectDB::instance_validate(obj)) { - WARN_PRINT("Attempted get_property list on stray pointer."); - return; - } + + if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { + WARN_PRINT("Attempted get_property list on previously freed instance."); + return; } + #endif obj->get_property_list(p_list); @@ -2908,13 +2902,13 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { } } break; case ARRAY: // 20 - case POOL_BYTE_ARRAY: - case POOL_INT_ARRAY: - case POOL_REAL_ARRAY: - case POOL_STRING_ARRAY: - case POOL_VECTOR2_ARRAY: // 25 - case POOL_VECTOR3_ARRAY: - case POOL_COLOR_ARRAY: { + case PACKED_BYTE_ARRAY: + case PACKED_INT_ARRAY: + case PACKED_REAL_ARRAY: + case PACKED_STRING_ARRAY: + case PACKED_VECTOR2_ARRAY: // 25 + case PACKED_VECTOR3_ARRAY: + case PACKED_COLOR_ARRAY: { //nothing } break; @@ -2961,16 +2955,18 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { } break; case OBJECT: { -#ifdef DEBUG_ENABLED if (!_get_obj().obj) { valid = false; return false; } - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) { +#ifdef DEBUG_ENABLED + + if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { valid = false; return false; } + #endif Variant::CallError ce; ce.error = Variant::CallError::CALL_OK; @@ -3016,56 +3012,56 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { r_iter = 0; return true; } break; - case POOL_BYTE_ARRAY: { - const PoolVector<uint8_t> *arr = reinterpret_cast<const PoolVector<uint8_t> *>(_data._mem); + case PACKED_BYTE_ARRAY: { + const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem); if (arr->size() == 0) return false; r_iter = 0; return true; } break; - case POOL_INT_ARRAY: { - const PoolVector<int> *arr = reinterpret_cast<const PoolVector<int> *>(_data._mem); + case PACKED_INT_ARRAY: { + const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem); if (arr->size() == 0) return false; r_iter = 0; return true; } break; - case POOL_REAL_ARRAY: { - const PoolVector<real_t> *arr = reinterpret_cast<const PoolVector<real_t> *>(_data._mem); + case PACKED_REAL_ARRAY: { + const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem); if (arr->size() == 0) return false; r_iter = 0; return true; } break; - case POOL_STRING_ARRAY: { - const PoolVector<String> *arr = reinterpret_cast<const PoolVector<String> *>(_data._mem); + case PACKED_STRING_ARRAY: { + const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem); if (arr->size() == 0) return false; r_iter = 0; return true; } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { - const PoolVector<Vector2> *arr = reinterpret_cast<const PoolVector<Vector2> *>(_data._mem); + const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem); if (arr->size() == 0) return false; r_iter = 0; return true; } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - const PoolVector<Vector3> *arr = reinterpret_cast<const PoolVector<Vector3> *>(_data._mem); + const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem); if (arr->size() == 0) return false; r_iter = 0; return true; } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { - const PoolVector<Color> *arr = reinterpret_cast<const PoolVector<Color> *>(_data._mem); + const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem); if (arr->size() == 0) return false; r_iter = 0; @@ -3129,16 +3125,18 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { } break; case OBJECT: { -#ifdef DEBUG_ENABLED if (!_get_obj().obj) { valid = false; return false; } - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) { +#ifdef DEBUG_ENABLED + + if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { valid = false; return false; } + #endif Variant::CallError ce; ce.error = Variant::CallError::CALL_OK; @@ -3189,8 +3187,8 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { r_iter = idx; return true; } break; - case POOL_BYTE_ARRAY: { - const PoolVector<uint8_t> *arr = reinterpret_cast<const PoolVector<uint8_t> *>(_data._mem); + case PACKED_BYTE_ARRAY: { + const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem); int idx = r_iter; idx++; if (idx >= arr->size()) @@ -3199,8 +3197,8 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { return true; } break; - case POOL_INT_ARRAY: { - const PoolVector<int> *arr = reinterpret_cast<const PoolVector<int> *>(_data._mem); + case PACKED_INT_ARRAY: { + const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem); int idx = r_iter; idx++; if (idx >= arr->size()) @@ -3209,8 +3207,8 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { return true; } break; - case POOL_REAL_ARRAY: { - const PoolVector<real_t> *arr = reinterpret_cast<const PoolVector<real_t> *>(_data._mem); + case PACKED_REAL_ARRAY: { + const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem); int idx = r_iter; idx++; if (idx >= arr->size()) @@ -3219,8 +3217,8 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { return true; } break; - case POOL_STRING_ARRAY: { - const PoolVector<String> *arr = reinterpret_cast<const PoolVector<String> *>(_data._mem); + case PACKED_STRING_ARRAY: { + const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem); int idx = r_iter; idx++; if (idx >= arr->size()) @@ -3228,9 +3226,9 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { r_iter = idx; return true; } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { - const PoolVector<Vector2> *arr = reinterpret_cast<const PoolVector<Vector2> *>(_data._mem); + const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem); int idx = r_iter; idx++; if (idx >= arr->size()) @@ -3238,9 +3236,9 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { r_iter = idx; return true; } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - const PoolVector<Vector3> *arr = reinterpret_cast<const PoolVector<Vector3> *>(_data._mem); + const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem); int idx = r_iter; idx++; if (idx >= arr->size()) @@ -3248,9 +3246,9 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { r_iter = idx; return true; } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { - const PoolVector<Color> *arr = reinterpret_cast<const PoolVector<Color> *>(_data._mem); + const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem); int idx = r_iter; idx++; if (idx >= arr->size()) @@ -3288,16 +3286,16 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { } break; case OBJECT: { -#ifdef DEBUG_ENABLED if (!_get_obj().obj) { r_valid = false; return Variant(); } - - if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) { +#ifdef DEBUG_ENABLED + if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { r_valid = false; return Variant(); } + #endif Variant::CallError ce; ce.error = Variant::CallError::CALL_OK; @@ -3336,8 +3334,8 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { #endif return arr->get(idx); } break; - case POOL_BYTE_ARRAY: { - const PoolVector<uint8_t> *arr = reinterpret_cast<const PoolVector<uint8_t> *>(_data._mem); + case PACKED_BYTE_ARRAY: { + const Vector<uint8_t> *arr = reinterpret_cast<const Vector<uint8_t> *>(_data._mem); int idx = r_iter; #ifdef DEBUG_ENABLED if (idx < 0 || idx >= arr->size()) { @@ -3347,8 +3345,8 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { #endif return arr->get(idx); } break; - case POOL_INT_ARRAY: { - const PoolVector<int> *arr = reinterpret_cast<const PoolVector<int> *>(_data._mem); + case PACKED_INT_ARRAY: { + const Vector<int> *arr = reinterpret_cast<const Vector<int> *>(_data._mem); int idx = r_iter; #ifdef DEBUG_ENABLED if (idx < 0 || idx >= arr->size()) { @@ -3358,8 +3356,8 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { #endif return arr->get(idx); } break; - case POOL_REAL_ARRAY: { - const PoolVector<real_t> *arr = reinterpret_cast<const PoolVector<real_t> *>(_data._mem); + case PACKED_REAL_ARRAY: { + const Vector<real_t> *arr = reinterpret_cast<const Vector<real_t> *>(_data._mem); int idx = r_iter; #ifdef DEBUG_ENABLED if (idx < 0 || idx >= arr->size()) { @@ -3369,8 +3367,8 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { #endif return arr->get(idx); } break; - case POOL_STRING_ARRAY: { - const PoolVector<String> *arr = reinterpret_cast<const PoolVector<String> *>(_data._mem); + case PACKED_STRING_ARRAY: { + const Vector<String> *arr = reinterpret_cast<const Vector<String> *>(_data._mem); int idx = r_iter; #ifdef DEBUG_ENABLED if (idx < 0 || idx >= arr->size()) { @@ -3380,9 +3378,9 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { #endif return arr->get(idx); } break; - case POOL_VECTOR2_ARRAY: { + case PACKED_VECTOR2_ARRAY: { - const PoolVector<Vector2> *arr = reinterpret_cast<const PoolVector<Vector2> *>(_data._mem); + const Vector<Vector2> *arr = reinterpret_cast<const Vector<Vector2> *>(_data._mem); int idx = r_iter; #ifdef DEBUG_ENABLED if (idx < 0 || idx >= arr->size()) { @@ -3392,9 +3390,9 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { #endif return arr->get(idx); } break; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - const PoolVector<Vector3> *arr = reinterpret_cast<const PoolVector<Vector3> *>(_data._mem); + const Vector<Vector3> *arr = reinterpret_cast<const Vector<Vector3> *>(_data._mem); int idx = r_iter; #ifdef DEBUG_ENABLED if (idx < 0 || idx >= arr->size()) { @@ -3404,9 +3402,9 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { #endif return arr->get(idx); } break; - case POOL_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: { - const PoolVector<Color> *arr = reinterpret_cast<const PoolVector<Color> *>(_data._mem); + const Vector<Color> *arr = reinterpret_cast<const Vector<Color> *>(_data._mem); int idx = r_iter; #ifdef DEBUG_ENABLED if (idx < 0 || idx >= arr->size()) { @@ -3660,25 +3658,25 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & r_dst = a; } return; - case POOL_BYTE_ARRAY: { + case PACKED_BYTE_ARRAY: { r_dst = a; } return; - case POOL_INT_ARRAY: { - const PoolVector<int> *arr_a = reinterpret_cast<const PoolVector<int> *>(a._data._mem); - const PoolVector<int> *arr_b = reinterpret_cast<const PoolVector<int> *>(b._data._mem); + case PACKED_INT_ARRAY: { + const Vector<int> *arr_a = reinterpret_cast<const Vector<int> *>(a._data._mem); + const Vector<int> *arr_b = reinterpret_cast<const Vector<int> *>(b._data._mem); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { r_dst = a; } else { - PoolVector<int> v; + Vector<int> v; v.resize(sz); { - PoolVector<int>::Write vw = v.write(); - PoolVector<int>::Read ar = arr_a->read(); - PoolVector<int>::Read br = arr_b->read(); + int *vw = v.ptrw(); + const int *ar = arr_a->ptr(); + const int *br = arr_b->ptr(); Variant va; for (int i = 0; i < sz; i++) { @@ -3690,21 +3688,21 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } } return; - case POOL_REAL_ARRAY: { - const PoolVector<real_t> *arr_a = reinterpret_cast<const PoolVector<real_t> *>(a._data._mem); - const PoolVector<real_t> *arr_b = reinterpret_cast<const PoolVector<real_t> *>(b._data._mem); + case PACKED_REAL_ARRAY: { + const Vector<real_t> *arr_a = reinterpret_cast<const Vector<real_t> *>(a._data._mem); + const Vector<real_t> *arr_b = reinterpret_cast<const Vector<real_t> *>(b._data._mem); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { r_dst = a; } else { - PoolVector<real_t> v; + Vector<real_t> v; v.resize(sz); { - PoolVector<real_t>::Write vw = v.write(); - PoolVector<real_t>::Read ar = arr_a->read(); - PoolVector<real_t>::Read br = arr_b->read(); + real_t *vw = v.ptrw(); + const real_t *ar = arr_a->ptr(); + const real_t *br = arr_b->ptr(); Variant va; for (int i = 0; i < sz; i++) { @@ -3716,25 +3714,25 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } } return; - case POOL_STRING_ARRAY: { + case PACKED_STRING_ARRAY: { r_dst = a; } return; - case POOL_VECTOR2_ARRAY: { - const PoolVector<Vector2> *arr_a = reinterpret_cast<const PoolVector<Vector2> *>(a._data._mem); - const PoolVector<Vector2> *arr_b = reinterpret_cast<const PoolVector<Vector2> *>(b._data._mem); + case PACKED_VECTOR2_ARRAY: { + const Vector<Vector2> *arr_a = reinterpret_cast<const Vector<Vector2> *>(a._data._mem); + const Vector<Vector2> *arr_b = reinterpret_cast<const Vector<Vector2> *>(b._data._mem); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { r_dst = a; } else { - PoolVector<Vector2> v; + Vector<Vector2> v; v.resize(sz); { - PoolVector<Vector2>::Write vw = v.write(); - PoolVector<Vector2>::Read ar = arr_a->read(); - PoolVector<Vector2>::Read br = arr_b->read(); + Vector2 *vw = v.ptrw(); + const Vector2 *ar = arr_a->ptr(); + const Vector2 *br = arr_b->ptr(); for (int i = 0; i < sz; i++) { vw[i] = ar[i].linear_interpolate(br[i], c); @@ -3744,22 +3742,22 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } } return; - case POOL_VECTOR3_ARRAY: { + case PACKED_VECTOR3_ARRAY: { - const PoolVector<Vector3> *arr_a = reinterpret_cast<const PoolVector<Vector3> *>(a._data._mem); - const PoolVector<Vector3> *arr_b = reinterpret_cast<const PoolVector<Vector3> *>(b._data._mem); + const Vector<Vector3> *arr_a = reinterpret_cast<const Vector<Vector3> *>(a._data._mem); + const Vector<Vector3> *arr_b = reinterpret_cast<const Vector<Vector3> *>(b._data._mem); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { r_dst = a; } else { - PoolVector<Vector3> v; + Vector<Vector3> v; v.resize(sz); { - PoolVector<Vector3>::Write vw = v.write(); - PoolVector<Vector3>::Read ar = arr_a->read(); - PoolVector<Vector3>::Read br = arr_b->read(); + Vector3 *vw = v.ptrw(); + const Vector3 *ar = arr_a->ptr(); + const Vector3 *br = arr_b->ptr(); for (int i = 0; i < sz; i++) { vw[i] = ar[i].linear_interpolate(br[i], c); @@ -3769,21 +3767,21 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } } return; - case POOL_COLOR_ARRAY: { - const PoolVector<Color> *arr_a = reinterpret_cast<const PoolVector<Color> *>(a._data._mem); - const PoolVector<Color> *arr_b = reinterpret_cast<const PoolVector<Color> *>(b._data._mem); + case PACKED_COLOR_ARRAY: { + const Vector<Color> *arr_a = reinterpret_cast<const Vector<Color> *>(a._data._mem); + const Vector<Color> *arr_b = reinterpret_cast<const Vector<Color> *>(b._data._mem); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { r_dst = a; } else { - PoolVector<Color> v; + Vector<Color> v; v.resize(sz); { - PoolVector<Color>::Write vw = v.write(); - PoolVector<Color>::Read ar = arr_a->read(); - PoolVector<Color>::Read br = arr_b->read(); + Color *vw = v.ptrw(); + const Color *ar = arr_a->ptr(); + const Color *br = arr_b->ptr(); for (int i = 0; i < sz; i++) { vw[i] = ar[i].linear_interpolate(br[i], c); diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 6ca9d6c246..f036e00ed5 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -51,10 +51,16 @@ bool VariantParser::StreamFile::is_eof() const { CharType VariantParser::StreamString::get_char() { - if (pos >= s.length()) + if (pos > s.length()) { return 0; - else + } else if (pos == s.length()) { + // You need to try to read again when you have reached the end for EOF to be reported, + // so this works the same as files (like StreamFile does) + pos++; + return 0; + } else { return s[pos++]; + } } bool VariantParser::StreamString::is_utf8() const { @@ -229,8 +235,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri case 'f': res = 12; break; case 'r': res = 13; break; case 'u': { - //hexnumbarh - oct is deprecated - + //hex number for (int j = 0; j < 4; j++) { CharType c = p_stream->get_char(); if (c == 0) { @@ -254,7 +259,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri v = c - 'A'; v += 10; } else { - ERR_PRINT("BUG"); + ERR_PRINT("Bug parsing hex constant."); v = 0; } @@ -263,13 +268,8 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri } } break; - //case '\"': res='\"'; break; - //case '\\': res='\\'; break; - //case '/': res='/'; break; default: { res = next; - //r_err_str="Invalid escape sequence"; - //return ERR_PARSE_ERROR; } break; } @@ -860,210 +860,19 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } } -#ifndef DISABLE_DEPRECATED - } else if (id == "InputEvent") { - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_PARENTHESIS_OPEN) { - r_err_str = "Expected '('"; - return ERR_PARSE_ERROR; - } - - get_token(p_stream, token, line, r_err_str); - - if (token.type != TK_IDENTIFIER) { - r_err_str = "Expected identifier"; - return ERR_PARSE_ERROR; - } - - String id2 = token.value; - - Ref<InputEvent> ie; - - if (id2 == "NONE") { - - get_token(p_stream, token, line, r_err_str); - - if (token.type != TK_PARENTHESIS_CLOSE) { - r_err_str = "Expected ')'"; - return ERR_PARSE_ERROR; - } - - } else if (id2 == "KEY") { - - Ref<InputEventKey> key; - key.instance(); - ie = key; - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_COMMA) { - r_err_str = "Expected ','"; - return ERR_PARSE_ERROR; - } - - get_token(p_stream, token, line, r_err_str); - if (token.type == TK_IDENTIFIER) { - String name = token.value; - key->set_scancode(find_keycode(name)); - } else if (token.type == TK_NUMBER) { - - key->set_scancode(token.value); - } else { - - r_err_str = "Expected string or integer for keycode"; - return ERR_PARSE_ERROR; - } - - get_token(p_stream, token, line, r_err_str); - - if (token.type == TK_COMMA) { - - get_token(p_stream, token, line, r_err_str); - - if (token.type != TK_IDENTIFIER) { - r_err_str = "Expected identifier with modifier flas"; - return ERR_PARSE_ERROR; - } - - String mods = token.value; - - if (mods.findn("C") != -1) - key->set_control(true); - if (mods.findn("A") != -1) - key->set_alt(true); - if (mods.findn("S") != -1) - key->set_shift(true); - if (mods.findn("M") != -1) - key->set_metakey(true); - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_PARENTHESIS_CLOSE) { - r_err_str = "Expected ')'"; - return ERR_PARSE_ERROR; - } - - } else if (token.type != TK_PARENTHESIS_CLOSE) { - - r_err_str = "Expected ')' or modifier flags."; - return ERR_PARSE_ERROR; - } - - } else if (id2 == "MBUTTON") { - - Ref<InputEventMouseButton> mb; - mb.instance(); - ie = mb; - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_COMMA) { - r_err_str = "Expected ','"; - return ERR_PARSE_ERROR; - } - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_NUMBER) { - r_err_str = "Expected button index"; - return ERR_PARSE_ERROR; - } - - mb->set_button_index(token.value); - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_PARENTHESIS_CLOSE) { - r_err_str = "Expected ')'"; - return ERR_PARSE_ERROR; - } - - } else if (id2 == "JBUTTON") { - - Ref<InputEventJoypadButton> jb; - jb.instance(); - ie = jb; - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_COMMA) { - r_err_str = "Expected ','"; - return ERR_PARSE_ERROR; - } - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_NUMBER) { - r_err_str = "Expected button index"; - return ERR_PARSE_ERROR; - } - - jb->set_button_index(token.value); - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_PARENTHESIS_CLOSE) { - r_err_str = "Expected ')'"; - return ERR_PARSE_ERROR; - } - - } else if (id2 == "JAXIS") { - - Ref<InputEventJoypadMotion> jm; - jm.instance(); - ie = jm; - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_COMMA) { - r_err_str = "Expected ','"; - return ERR_PARSE_ERROR; - } - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_NUMBER) { - r_err_str = "Expected axis index"; - return ERR_PARSE_ERROR; - } - - jm->set_axis(token.value); - - get_token(p_stream, token, line, r_err_str); - - if (token.type != TK_COMMA) { - r_err_str = "Expected ',' after axis index"; - return ERR_PARSE_ERROR; - } - - get_token(p_stream, token, line, r_err_str); - if (token.type != TK_NUMBER) { - r_err_str = "Expected axis sign"; - return ERR_PARSE_ERROR; - } - - jm->set_axis_value(token.value); - - get_token(p_stream, token, line, r_err_str); - - if (token.type != TK_PARENTHESIS_CLOSE) { - r_err_str = "Expected ')' for jaxis"; - return ERR_PARSE_ERROR; - } - - } else { - - r_err_str = "Invalid input event type."; - return ERR_PARSE_ERROR; - } - value = ie; - - return OK; -#endif - } else if (id == "PoolByteArray" || id == "ByteArray") { + } else if (id == "PackedByteArray" || id == "PoolByteArray" || id == "ByteArray") { Vector<uint8_t> args; Error err = _parse_construct<uint8_t>(p_stream, args, line, r_err_str); if (err) return err; - PoolVector<uint8_t> arr; + Vector<uint8_t> arr; { int len = args.size(); arr.resize(len); - PoolVector<uint8_t>::Write w = arr.write(); + uint8_t *w = arr.ptrw(); for (int i = 0; i < len; i++) { w[i] = args[i]; } @@ -1073,18 +882,18 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return OK; - } else if (id == "PoolIntArray" || id == "IntArray") { + } else if (id == "PackedIntArray" || id == "PoolIntArray" || id == "IntArray") { Vector<int> args; Error err = _parse_construct<int>(p_stream, args, line, r_err_str); if (err) return err; - PoolVector<int> arr; + Vector<int> arr; { int len = args.size(); arr.resize(len); - PoolVector<int>::Write w = arr.write(); + int *w = arr.ptrw(); for (int i = 0; i < len; i++) { w[i] = int(args[i]); } @@ -1094,18 +903,18 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return OK; - } else if (id == "PoolRealArray" || id == "FloatArray") { + } else if (id == "PackedRealArray" || id == "PoolRealArray" || id == "FloatArray") { Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); if (err) return err; - PoolVector<float> arr; + Vector<float> arr; { int len = args.size(); arr.resize(len); - PoolVector<float>::Write w = arr.write(); + float *w = arr.ptrw(); for (int i = 0; i < len; i++) { w[i] = args[i]; } @@ -1114,7 +923,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, value = arr; return OK; - } else if (id == "PoolStringArray" || id == "StringArray") { + } else if (id == "PackedStringArray" || id == "PoolStringArray" || id == "StringArray") { get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { @@ -1151,11 +960,11 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, cs.push_back(token.value); } - PoolVector<String> arr; + Vector<String> arr; { int len = cs.size(); arr.resize(len); - PoolVector<String>::Write w = arr.write(); + String *w = arr.ptrw(); for (int i = 0; i < len; i++) { w[i] = cs[i]; } @@ -1165,18 +974,18 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return OK; - } else if (id == "PoolVector2Array" || id == "Vector2Array") { + } else if (id == "PackedVector2Array" || id == "PoolVector2Array" || id == "Vector2Array") { Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); if (err) return err; - PoolVector<Vector2> arr; + Vector<Vector2> arr; { int len = args.size() / 2; arr.resize(len); - PoolVector<Vector2>::Write w = arr.write(); + Vector2 *w = arr.ptrw(); for (int i = 0; i < len; i++) { w[i] = Vector2(args[i * 2 + 0], args[i * 2 + 1]); } @@ -1186,18 +995,18 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return OK; - } else if (id == "PoolVector3Array" || id == "Vector3Array") { + } else if (id == "PackedVector3Array" || id == "PoolVector3Array" || id == "Vector3Array") { Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); if (err) return err; - PoolVector<Vector3> arr; + Vector<Vector3> arr; { int len = args.size() / 3; arr.resize(len); - PoolVector<Vector3>::Write w = arr.write(); + Vector3 *w = arr.ptrw(); for (int i = 0; i < len; i++) { w[i] = Vector3(args[i * 3 + 0], args[i * 3 + 1], args[i * 3 + 2]); } @@ -1207,18 +1016,18 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return OK; - } else if (id == "PoolColorArray" || id == "ColorArray") { + } else if (id == "PackedColorArray" || id == "PoolColorArray" || id == "ColorArray") { Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); if (err) return err; - PoolVector<Color> arr; + Vector<Color> arr; { int len = args.size() / 4; arr.resize(len); - PoolVector<Color>::Write w = arr.write(); + Color *w = arr.ptrw(); for (int i = 0; i < len; i++) { w[i] = Color(args[i * 4 + 0], args[i * 4 + 1], args[i * 4 + 2], args[i * 4 + 3]); } @@ -1800,14 +1609,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; - case Variant::POOL_BYTE_ARRAY: { + case Variant::PACKED_BYTE_ARRAY: { - p_store_string_func(p_store_string_ud, "PoolByteArray( "); + p_store_string_func(p_store_string_ud, "PackedByteArray( "); String s; - PoolVector<uint8_t> data = p_variant; + Vector<uint8_t> data = p_variant; int len = data.size(); - PoolVector<uint8_t>::Read r = data.read(); - const uint8_t *ptr = r.ptr(); + const uint8_t *ptr = data.ptr(); + for (int i = 0; i < len; i++) { if (i > 0) @@ -1819,13 +1628,12 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, " )"); } break; - case Variant::POOL_INT_ARRAY: { + case Variant::PACKED_INT_ARRAY: { - p_store_string_func(p_store_string_ud, "PoolIntArray( "); - PoolVector<int> data = p_variant; + p_store_string_func(p_store_string_ud, "PackedIntArray( "); + Vector<int> data = p_variant; int len = data.size(); - PoolVector<int>::Read r = data.read(); - const int *ptr = r.ptr(); + const int *ptr = data.ptr(); for (int i = 0; i < len; i++) { @@ -1838,13 +1646,12 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, " )"); } break; - case Variant::POOL_REAL_ARRAY: { + case Variant::PACKED_REAL_ARRAY: { - p_store_string_func(p_store_string_ud, "PoolRealArray( "); - PoolVector<real_t> data = p_variant; + p_store_string_func(p_store_string_ud, "PackedRealArray( "); + Vector<real_t> data = p_variant; int len = data.size(); - PoolVector<real_t>::Read r = data.read(); - const real_t *ptr = r.ptr(); + const real_t *ptr = data.ptr(); for (int i = 0; i < len; i++) { @@ -1856,13 +1663,13 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, " )"); } break; - case Variant::POOL_STRING_ARRAY: { + case Variant::PACKED_STRING_ARRAY: { - p_store_string_func(p_store_string_ud, "PoolStringArray( "); - PoolVector<String> data = p_variant; + p_store_string_func(p_store_string_ud, "PackedStringArray( "); + Vector<String> data = p_variant; int len = data.size(); - PoolVector<String>::Read r = data.read(); - const String *ptr = r.ptr(); + const String *ptr = data.ptr(); + String s; //write_string("\n"); @@ -1877,13 +1684,12 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, " )"); } break; - case Variant::POOL_VECTOR2_ARRAY: { + case Variant::PACKED_VECTOR2_ARRAY: { - p_store_string_func(p_store_string_ud, "PoolVector2Array( "); - PoolVector<Vector2> data = p_variant; + p_store_string_func(p_store_string_ud, "PackedVector2Array( "); + Vector<Vector2> data = p_variant; int len = data.size(); - PoolVector<Vector2>::Read r = data.read(); - const Vector2 *ptr = r.ptr(); + const Vector2 *ptr = data.ptr(); for (int i = 0; i < len; i++) { @@ -1895,13 +1701,12 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, " )"); } break; - case Variant::POOL_VECTOR3_ARRAY: { + case Variant::PACKED_VECTOR3_ARRAY: { - p_store_string_func(p_store_string_ud, "PoolVector3Array( "); - PoolVector<Vector3> data = p_variant; + p_store_string_func(p_store_string_ud, "PackedVector3Array( "); + Vector<Vector3> data = p_variant; int len = data.size(); - PoolVector<Vector3>::Read r = data.read(); - const Vector3 *ptr = r.ptr(); + const Vector3 *ptr = data.ptr(); for (int i = 0; i < len; i++) { @@ -1913,14 +1718,13 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, " )"); } break; - case Variant::POOL_COLOR_ARRAY: { + case Variant::PACKED_COLOR_ARRAY: { - p_store_string_func(p_store_string_ud, "PoolColorArray( "); + p_store_string_func(p_store_string_ud, "PackedColorArray( "); - PoolVector<Color> data = p_variant; + Vector<Color> data = p_variant; int len = data.size(); - PoolVector<Color>::Read r = data.read(); - const Color *ptr = r.ptr(); + const Color *ptr = data.ptr(); for (int i = 0; i < len; i++) { diff --git a/core/vector.h b/core/vector.h index 44add2c4d7..d3476679ff 100644 --- a/core/vector.h +++ b/core/vector.h @@ -34,7 +34,7 @@ /** * @class Vector * @author Juan Linietsky - * Vector container. Regular Vector Container. Use with care and for smaller arrays when possible. Use PoolVector for large arrays. + * Vector container. Regular Vector Container. Use with care and for smaller arrays when possible. Use Vector for large arrays. */ #include "core/cowdata.h" @@ -64,12 +64,13 @@ private: public: bool push_back(T p_elem); + _FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } //alias void remove(int p_index) { _cowdata.remove(p_index); } void erase(const T &p_val) { int idx = find(p_val); if (idx >= 0) remove(idx); - }; + } void invert(); _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } @@ -123,6 +124,30 @@ public: return *this; } + Vector<T> subarray(int p_from, int p_to) const { + + if (p_from < 0) { + p_from = size() + p_from; + } + if (p_to < 0) { + p_to = size() + p_to; + } + + ERR_FAIL_INDEX_V(p_from, size(), Vector<T>()); + ERR_FAIL_INDEX_V(p_to, size(), Vector<T>()); + + Vector<T> slice; + int span = 1 + p_to - p_from; + slice.resize(span); + const T *r = ptr(); + T *w = slice.ptrw(); + for (int i = 0; i < span; ++i) { + w[i] = r[p_from + i]; + } + + return slice; + } + _FORCE_INLINE_ ~Vector() {} }; |