diff options
Diffstat (limited to 'core')
112 files changed, 1773 insertions, 702 deletions
diff --git a/core/SCsub b/core/SCsub index 166b7083e4..85e5f1b089 100644 --- a/core/SCsub +++ b/core/SCsub @@ -47,15 +47,11 @@ env_thirdparty.disable_warnings() thirdparty_misc_dir = "#thirdparty/misc/" thirdparty_misc_sources = [ # C sources - "base64.c", "fastlz.c", - "sha256.c", "smaz.c", # C++ sources - "aes256.cpp", "hq2x.cpp", - "md5.cpp", "pcg.cpp", "triangulator.cpp", "clipper.cpp", @@ -130,10 +126,10 @@ if env['builtin_zstd']: thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources] env_thirdparty.Prepend(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"]) - env_thirdparty.Append(CPPFLAGS="-DZSTD_STATIC_LINKING_ONLY") + env_thirdparty.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"]) env.Prepend(CPPPATH=thirdparty_zstd_dir) # Also needed in main env includes will trigger warnings - env.Append(CPPFLAGS="-DZSTD_STATIC_LINKING_ONLY") + env.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"]) env_thirdparty.add_source_files(env.core_sources, thirdparty_zstd_sources) @@ -146,7 +142,7 @@ env.Depends("#core/io/certs_compressed.gen.h", ["#thirdparty/certs/ca-certificat env.CommandNoCache("#core/io/certs_compressed.gen.h", "#thirdparty/certs/ca-certificates.crt", run_in_subprocess(core_builders.make_certs_header)) # Make binders -env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', run_in_subprocess(make_binders.run)) +env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc', 'method_bind_free_func.gen.inc'], 'make_binders.py', run_in_subprocess(make_binders.run)) # Authors env.Depends('#core/authors.gen.h', "../AUTHORS.md") diff --git a/core/array.cpp b/core/array.cpp index 65934d6ec9..a334af2c04 100644 --- a/core/array.cpp +++ b/core/array.cpp @@ -133,12 +133,18 @@ void Array::erase(const Variant &p_value) { } Variant Array::front() const { - ERR_FAIL_COND_V(_p->array.size() == 0, Variant()); + if (_p->array.size() == 0) { + ERR_EXPLAIN("Can't take value from empty array"); + ERR_FAIL_V(Variant()); + } return operator[](0); } Variant Array::back() const { - ERR_FAIL_COND_V(_p->array.size() == 0, Variant()); + if (_p->array.size() == 0) { + ERR_EXPLAIN("Can't take value from empty array"); + ERR_FAIL_V(Variant()); + } return operator[](_p->array.size() - 1); } @@ -165,8 +171,8 @@ int Array::rfind(const Variant &p_value, int p_from) const { if (_p->array[i] == p_value) { return i; - }; - }; + } + } return -1; } @@ -186,8 +192,8 @@ int Array::count(const Variant &p_value) const { if (_p->array[i] == p_value) { amount++; - }; - }; + } + } return amount; } diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 27b33d942b..b41b84ab1e 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -34,13 +34,12 @@ #include "core/io/file_access_encrypted.h" #include "core/io/json.h" #include "core/io/marshalls.h" +#include "core/math/crypto_core.h" #include "core/math/geometry.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/project_settings.h" -#include "thirdparty/misc/base64.h" - /** * Time constants borrowed from loc_time.h */ @@ -76,7 +75,7 @@ RES _ResourceLoader::load(const String &p_path, const String &p_type_hint, bool if (err != OK) { ERR_EXPLAIN("Error loading resource: '" + p_path + "'"); - ERR_FAIL_COND_V(err != OK, ret); + ERR_FAIL_V(ret); } return ret; } @@ -149,8 +148,10 @@ _ResourceLoader::_ResourceLoader() { } Error _ResourceSaver::save(const String &p_path, const RES &p_resource, SaverFlags p_flags) { - - ERR_FAIL_COND_V(p_resource.is_null(), ERR_INVALID_PARAMETER); + if (p_resource.is_null()) { + ERR_EXPLAIN("Can't save empty resource to path: " + String(p_path)) + ERR_FAIL_V(ERR_INVALID_PARAMETER); + } return ResourceSaver::save(p_path, p_resource, p_flags); } @@ -246,11 +247,11 @@ PoolStringArray _OS::get_connected_midi_inputs() { } void _OS::open_midi_inputs() { - return OS::get_singleton()->open_midi_inputs(); + OS::get_singleton()->open_midi_inputs(); } void _OS::close_midi_inputs() { - return OS::get_singleton()->close_midi_inputs(); + OS::get_singleton()->close_midi_inputs(); } void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen) { @@ -308,6 +309,14 @@ void _OS::set_window_position(const Point2 &p_position) { OS::get_singleton()->set_window_position(p_position); } +Size2 _OS::get_max_window_size() const { + return OS::get_singleton()->get_max_window_size(); +} + +Size2 _OS::get_min_window_size() const { + return OS::get_singleton()->get_min_window_size(); +} + Size2 _OS::get_window_size() const { return OS::get_singleton()->get_window_size(); } @@ -316,6 +325,14 @@ Size2 _OS::get_real_window_size() const { return OS::get_singleton()->get_real_window_size(); } +void _OS::set_max_window_size(const Size2 &p_size) { + OS::get_singleton()->set_max_window_size(p_size); +} + +void _OS::set_min_window_size(const Size2 &p_size) { + OS::get_singleton()->set_min_window_size(p_size); +} + void _OS::set_window_size(const Size2 &p_size) { OS::get_singleton()->set_window_size(p_size); } @@ -442,14 +459,14 @@ Error _OS::shell_open(String p_uri) { return OS::get_singleton()->shell_open(p_uri); }; -int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output) { +int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output, bool p_read_stderr) { OS::ProcessID pid = -2; List<String> args; for (int i = 0; i < p_arguments.size(); i++) args.push_back(p_arguments[i]); String pipe; - Error err = OS::get_singleton()->execute(p_path, args, p_blocking, &pid, &pipe); + Error err = OS::get_singleton()->execute(p_path, args, p_blocking, &pid, &pipe, NULL, p_read_stderr); p_output.clear(); p_output.push_back(pipe); if (err != OK) @@ -1139,6 +1156,10 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_window_position"), &_OS::get_window_position); ClassDB::bind_method(D_METHOD("set_window_position", "position"), &_OS::set_window_position); ClassDB::bind_method(D_METHOD("get_window_size"), &_OS::get_window_size); + ClassDB::bind_method(D_METHOD("get_max_window_size"), &_OS::get_max_window_size); + ClassDB::bind_method(D_METHOD("get_min_window_size"), &_OS::get_min_window_size); + ClassDB::bind_method(D_METHOD("set_max_window_size", "size"), &_OS::set_max_window_size); + ClassDB::bind_method(D_METHOD("set_min_window_size", "size"), &_OS::set_min_window_size); ClassDB::bind_method(D_METHOD("set_window_size", "size"), &_OS::set_window_size); ClassDB::bind_method(D_METHOD("get_window_safe_area"), &_OS::get_window_safe_area); ClassDB::bind_method(D_METHOD("set_window_fullscreen", "enabled"), &_OS::set_window_fullscreen); @@ -1183,7 +1204,7 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_processor_count"), &_OS::get_processor_count); ClassDB::bind_method(D_METHOD("get_executable_path"), &_OS::get_executable_path); - ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "blocking", "output"), &_OS::execute, DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "blocking", "output", "read_stderr"), &_OS::execute, DEFVAL(Array()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("kill", "pid"), &_OS::kill); ClassDB::bind_method(D_METHOD("shell_open", "uri"), &_OS::shell_open); ClassDB::bind_method(D_METHOD("get_process_id"), &_OS::get_process_id); @@ -1284,6 +1305,8 @@ void _OS::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vsync_enabled"), "set_use_vsync", "is_vsync_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_screen_on"), "set_keep_screen_on", "is_keep_screen_on"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "min_window_size"), "set_min_window_size", "get_min_window_size"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "max_window_size"), "set_max_window_size", "get_max_window_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor"), "set_screen_orientation", "get_screen_orientation"); ADD_GROUP("Window", "window_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_borderless"), "set_borderless_window", "get_borderless_window"); @@ -1295,6 +1318,26 @@ void _OS::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_position"), "set_window_position", "get_window_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_size"), "set_window_size", "get_window_size"); + // Those default values need to be specified for the docs generator, + // to avoid using values from the documentation writer's own OS instance. + ADD_PROPERTY_DEFAULT("clipboard", ""); + ADD_PROPERTY_DEFAULT("current_screen", 0); + ADD_PROPERTY_DEFAULT("exit_code", 0); + ADD_PROPERTY_DEFAULT("vsync_enabled", true); + ADD_PROPERTY_DEFAULT("low_processor_usage_mode", false); + ADD_PROPERTY_DEFAULT("keep_screen_on", true); + ADD_PROPERTY_DEFAULT("min_window_size", Vector2()); + ADD_PROPERTY_DEFAULT("max_window_size", Vector2()); + ADD_PROPERTY_DEFAULT("screen_orientation", 0); + ADD_PROPERTY_DEFAULT("window_borderless", false); + ADD_PROPERTY_DEFAULT("window_per_pixel_transparency_enabled", false); + ADD_PROPERTY_DEFAULT("window_fullscreen", false); + ADD_PROPERTY_DEFAULT("window_maximized", false); + ADD_PROPERTY_DEFAULT("window_minimized", false); + ADD_PROPERTY_DEFAULT("window_resizable", true); + ADD_PROPERTY_DEFAULT("window_position", Vector2()); + ADD_PROPERTY_DEFAULT("window_size", Vector2()); + BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES2); BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES3); @@ -1502,6 +1545,11 @@ bool _Geometry::is_polygon_clockwise(const Vector<Vector2> &p_polygon) { return Geometry::is_polygon_clockwise(p_polygon); } +bool _Geometry::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) { + + return Geometry::is_point_in_polygon(p_point, p_polygon); +} + Vector<int> _Geometry::triangulate_polygon(const Vector<Vector2> &p_polygon) { return Geometry::triangulate_polygon(p_polygon); @@ -1684,6 +1732,7 @@ void _Geometry::_bind_methods() { ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &_Geometry::point_is_inside_triangle); ClassDB::bind_method(D_METHOD("is_polygon_clockwise", "polygon"), &_Geometry::is_polygon_clockwise); + ClassDB::bind_method(D_METHOD("is_point_in_polygon", "point", "polygon"), &_Geometry::is_point_in_polygon); ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &_Geometry::triangulate_polygon); ClassDB::bind_method(D_METHOD("triangulate_delaunay_2d", "points"), &_Geometry::triangulate_delaunay_2d); ClassDB::bind_method(D_METHOD("convex_hull_2d", "points"), &_Geometry::convex_hull_2d); @@ -1883,13 +1932,15 @@ PoolVector<uint8_t> _File::get_buffer(int p_length) const { ERR_FAIL_COND_V(p_length < 0, data); if (p_length == 0) return data; + Error err = data.resize(p_length); ERR_FAIL_COND_V(err != OK, data); + PoolVector<uint8_t>::Write w = data.write(); int len = f->get_buffer(&w[0], p_length); ERR_FAIL_COND_V(len < 0, PoolVector<uint8_t>()); - w = PoolVector<uint8_t>::Write(); + w.release(); if (len < p_length) data.resize(p_length); @@ -2064,11 +2115,11 @@ void _File::store_var(const Variant &p_var, bool p_full_objects) { PoolVector<uint8_t> buff; buff.resize(len); - PoolVector<uint8_t>::Write w = buff.write(); + PoolVector<uint8_t>::Write w = buff.write(); err = encode_variant(p_var, &w[0], len, p_full_objects); ERR_FAIL_COND(err != OK); - w = PoolVector<uint8_t>::Write(); + w.release(); store_32(len); store_buffer(buff); @@ -2218,7 +2269,7 @@ bool _Directory::current_is_dir() const { void _Directory::list_dir_end() { ERR_FAIL_COND(!d); - return d->list_dir_end(); + d->list_dir_end(); } int _Directory::get_drive_count() { @@ -2383,15 +2434,8 @@ String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) err = encode_variant(p_var, &w[0], len, p_full_objects); ERR_FAIL_COND_V(err != OK, ""); - int b64len = len / 3 * 4 + 4 + 1; - PoolVector<uint8_t> b64buff; - b64buff.resize(b64len); - PoolVector<uint8_t>::Write w64 = b64buff.write(); - - int strlen = base64_encode((char *)(&w64[0]), (char *)(&w[0]), len); - //OS::get_singleton()->print("len is %i, vector size is %i\n", b64len, strlen); - w64[strlen] = 0; - String ret = (char *)&w64[0]; + String ret = CryptoCore::b64_encode_str(&w[0], len); + ERR_FAIL_COND_V(ret == "", ret); return ret; }; @@ -2405,7 +2449,8 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) buf.resize(strlen / 4 * 3 + 1); PoolVector<uint8_t>::Write w = buf.write(); - int len = base64_decode((char *)(&w[0]), (char *)cstr.get_data(), strlen); + size_t len = 0; + ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &len, (unsigned char *)cstr.get_data(), strlen) != OK, Variant()); Variant v; Error err = decode_variant(v, &w[0], len, NULL, p_allow_objects); @@ -2416,18 +2461,8 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) String _Marshalls::raw_to_base64(const PoolVector<uint8_t> &p_arr) { - int len = p_arr.size(); - PoolVector<uint8_t>::Read r = p_arr.read(); - - int b64len = len / 3 * 4 + 4 + 1; - PoolVector<uint8_t> b64buff; - b64buff.resize(b64len); - PoolVector<uint8_t>::Write w64 = b64buff.write(); - - int strlen = base64_encode((char *)(&w64[0]), (char *)(&r[0]), len); - w64[strlen] = 0; - String ret = (char *)&w64[0]; - + String ret = CryptoCore::b64_encode_str(p_arr.read().ptr(), p_arr.size()); + ERR_FAIL_COND_V(ret == "", ret); return ret; }; @@ -2436,35 +2471,24 @@ PoolVector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) { int strlen = p_str.length(); CharString cstr = p_str.ascii(); - int arr_len; + size_t arr_len = 0; PoolVector<uint8_t> buf; { buf.resize(strlen / 4 * 3 + 1); PoolVector<uint8_t>::Write w = buf.write(); - arr_len = base64_decode((char *)(&w[0]), (char *)cstr.get_data(), strlen); - }; + ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &arr_len, (unsigned char *)cstr.get_data(), strlen) != OK, PoolVector<uint8_t>()); + } buf.resize(arr_len); - // conversion from PoolVector<uint8_t> to raw array? return buf; }; String _Marshalls::utf8_to_base64(const String &p_str) { CharString cstr = p_str.utf8(); - int len = cstr.length(); - - int b64len = len / 3 * 4 + 4 + 1; - PoolVector<uint8_t> b64buff; - b64buff.resize(b64len); - PoolVector<uint8_t>::Write w64 = b64buff.write(); - - int strlen = base64_encode((char *)(&w64[0]), (char *)cstr.get_data(), len); - - w64[strlen] = 0; - String ret = (char *)&w64[0]; - + String ret = CryptoCore::b64_encode_str((unsigned char *)cstr.get_data(), cstr.length()); + ERR_FAIL_COND_V(ret == "", ret); return ret; }; @@ -2477,7 +2501,8 @@ String _Marshalls::base64_to_utf8(const String &p_str) { buf.resize(strlen / 4 * 3 + 1 + 1); PoolVector<uint8_t>::Write w = buf.write(); - int len = base64_decode((char *)(&w[0]), (char *)cstr.get_data(), strlen); + size_t len = 0; + ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &len, (unsigned char *)cstr.get_data(), strlen) != OK, String()); w[len] = 0; String ret = String::utf8((char *)&w[0]); @@ -2652,6 +2677,8 @@ Variant _Thread::wait_to_finish() { target_method = StringName(); target_instance = NULL; userdata = Variant(); + if (thread) + memdelete(thread); thread = NULL; return r; @@ -2914,6 +2941,10 @@ float _Engine::get_physics_jitter_fix() const { return Engine::get_singleton()->get_physics_jitter_fix(); } +float _Engine::get_physics_interpolation_fraction() const { + return Engine::get_singleton()->get_physics_interpolation_fraction(); +} + void _Engine::set_target_fps(int p_fps) { Engine::get_singleton()->set_target_fps(p_fps); } @@ -3002,6 +3033,7 @@ void _Engine::_bind_methods() { ClassDB::bind_method(D_METHOD("get_iterations_per_second"), &_Engine::get_iterations_per_second); ClassDB::bind_method(D_METHOD("set_physics_jitter_fix", "physics_jitter_fix"), &_Engine::set_physics_jitter_fix); ClassDB::bind_method(D_METHOD("get_physics_jitter_fix"), &_Engine::get_physics_jitter_fix); + ClassDB::bind_method(D_METHOD("get_physics_interpolation_fraction"), &_Engine::get_physics_interpolation_fraction); ClassDB::bind_method(D_METHOD("set_target_fps", "target_fps"), &_Engine::set_target_fps); ClassDB::bind_method(D_METHOD("get_target_fps"), &_Engine::get_target_fps); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 3e46d24627..f0f86e003f 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -175,9 +175,13 @@ public: virtual int get_screen_dpi(int p_screen = -1) const; virtual Point2 get_window_position() const; virtual void set_window_position(const Point2 &p_position); + virtual Size2 get_max_window_size() const; + virtual Size2 get_min_window_size() const; virtual Size2 get_window_size() const; virtual Size2 get_real_window_size() const; virtual Rect2 get_window_safe_area() const; + virtual void set_max_window_size(const Size2 &p_size); + virtual void set_min_window_size(const Size2 &p_size); virtual void set_window_size(const Size2 &p_size); virtual void set_window_fullscreen(bool p_enabled); virtual bool is_window_fullscreen() const; @@ -214,7 +218,7 @@ public: bool is_in_low_processor_usage_mode() const; String get_executable_path() const; - int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output = Array()); + int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output = Array(), bool p_read_stderr = false); Error kill(int p_pid); Error shell_open(String p_uri); @@ -404,6 +408,7 @@ public: int get_uv84_normal_bit(const Vector3 &p_vector); bool is_polygon_clockwise(const Vector<Vector2> &p_polygon); + bool is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon); Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon); Vector<int> triangulate_delaunay_2d(const Vector<Vector2> &p_points); Vector<Point2> convex_hull_2d(const Vector<Point2> &p_points); @@ -690,7 +695,7 @@ VARIANT_ENUM_CAST(_Thread::Priority); class _ClassDB : public Object { - GDCLASS(_ClassDB, Object) + GDCLASS(_ClassDB, Object); protected: static void _bind_methods(); @@ -741,6 +746,7 @@ public: void set_physics_jitter_fix(float p_threshold); float get_physics_jitter_fix() const; + float get_physics_interpolation_fraction() const; void set_target_fps(int p_fps); int get_target_fps() const; @@ -775,7 +781,7 @@ public: class _JSON; class JSONParseResult : public Reference { - GDCLASS(JSONParseResult, Reference) + GDCLASS(JSONParseResult, Reference); friend class _JSON; @@ -800,10 +806,13 @@ public: void set_result(const Variant &p_result); Variant get_result() const; + + JSONParseResult() : + error_line(-1) {} }; class _JSON : public Object { - GDCLASS(_JSON, Object) + GDCLASS(_JSON, Object); protected: static void _bind_methods(); diff --git a/core/class_db.cpp b/core/class_db.cpp index 0c844657a4..794d990083 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -545,6 +545,11 @@ bool ClassDB::can_instance(const StringName &p_class) { ClassInfo *ti = classes.getptr(p_class); ERR_FAIL_COND_V(!ti, false); +#ifdef TOOLS_ENABLED + if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) { + return false; + } +#endif return (!ti->disabled && ti->creation_func != NULL); } @@ -552,7 +557,7 @@ void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherit OBJTYPE_WLOCK; - StringName name = p_class; + const StringName &name = p_class; ERR_FAIL_COND(classes.has(name)); @@ -666,10 +671,8 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName OBJTYPE_WLOCK; ClassInfo *type = classes.getptr(p_class); - if (!type) { - ERR_FAIL_COND(!type); - } + ERR_FAIL_COND(!type); if (type->constant_map.has(p_name)) { @@ -922,7 +925,7 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons #ifdef DEBUG_METHODS_ENABLED if (!mb_set) { ERR_EXPLAIN("Invalid Setter: " + p_class + "::" + p_setter + " for property: " + p_pinfo.name); - ERR_FAIL_COND(!mb_set); + ERR_FAIL(); } else { int exp_args = 1 + (p_index >= 0 ? 1 : 0); if (mb_set->get_argument_count() != exp_args) { @@ -941,7 +944,7 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons if (!mb_get) { ERR_EXPLAIN("Invalid Getter: " + p_class + "::" + p_getter + " for property: " + p_pinfo.name); - ERR_FAIL_COND(!mb_get); + ERR_FAIL(); } else { int exp_args = 0 + (p_index >= 0 ? 1 : 0); @@ -982,6 +985,13 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons type->property_setget[p_pinfo.name] = psg; } +void ClassDB::set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default) { + if (!default_values.has(p_class)) { + default_values[p_class] = HashMap<StringName, Variant>(); + } + default_values[p_class][p_name] = p_default; +} + void ClassDB::get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) { OBJTYPE_RLOCK; @@ -1138,7 +1148,7 @@ Variant::Type ClassDB::get_property_type(const StringName &p_class, const String return Variant::NIL; } -StringName ClassDB::get_property_setter(StringName p_class, const StringName p_property) { +StringName ClassDB::get_property_setter(StringName p_class, const StringName &p_property) { ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; @@ -1155,7 +1165,7 @@ StringName ClassDB::get_property_setter(StringName p_class, const StringName p_p return StringName(); } -StringName ClassDB::get_property_getter(StringName p_class, const StringName p_property) { +StringName ClassDB::get_property_getter(StringName p_class, const StringName &p_property) { ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; @@ -1385,37 +1395,60 @@ void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p } HashMap<StringName, HashMap<StringName, Variant> > ClassDB::default_values; +Set<StringName> ClassDB::default_values_cached; -Variant ClassDB::class_get_default_property_value(const StringName &p_class, const StringName &p_property) { +Variant ClassDB::class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid) { - if (!default_values.has(p_class)) { + if (!default_values_cached.has(p_class)) { - default_values[p_class] = HashMap<StringName, Variant>(); + if (!default_values.has(p_class)) { + default_values[p_class] = HashMap<StringName, Variant>(); + } - if (ClassDB::can_instance(p_class)) { + Object *c = NULL; + bool cleanup_c = false; + + if (Engine::get_singleton()->has_singleton(p_class)) { + c = Engine::get_singleton()->get_singleton_object(p_class); + cleanup_c = false; + } else if (ClassDB::can_instance(p_class)) { + c = ClassDB::instance(p_class); + cleanup_c = true; + } + + if (c) { - Object *c = ClassDB::instance(p_class); List<PropertyInfo> plist; c->get_property_list(&plist); for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { if (E->get().usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) { - Variant v = c->get(E->get().name); - default_values[p_class][E->get().name] = v; + if (!default_values[p_class].has(E->get().name)) { + Variant v = c->get(E->get().name); + default_values[p_class][E->get().name] = v; + } } } - memdelete(c); + + if (cleanup_c) { + memdelete(c); + } } + + default_values_cached.insert(p_class); } if (!default_values.has(p_class)) { + if (r_valid != NULL) *r_valid = false; return Variant(); } if (!default_values[p_class].has(p_property)) { + if (r_valid != NULL) *r_valid = false; return Variant(); } + if (r_valid != NULL) *r_valid = true; return default_values[p_class][p_property]; } @@ -1426,6 +1459,12 @@ void ClassDB::init() { lock = RWLock::create(); } +void ClassDB::cleanup_defaults() { + + default_values.clear(); + default_values_cached.clear(); +} + void ClassDB::cleanup() { //OBJTYPE_LOCK; hah not here @@ -1445,7 +1484,6 @@ void ClassDB::cleanup() { classes.clear(); resource_base_extensions.clear(); compat_classes.clear(); - default_values.clear(); memdelete(lock); } diff --git a/core/class_db.h b/core/class_db.h index efa1a46866..3d9a695f02 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -162,6 +162,7 @@ public: static void _add_class2(const StringName &p_class, const StringName &p_inherits); static HashMap<StringName, HashMap<StringName, Variant> > default_values; + static Set<StringName> default_values_cached; public: // DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!! @@ -329,14 +330,15 @@ public: static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = ""); static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1); + static void set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default); static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = NULL); static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = NULL); static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value); static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false); static int get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL); static Variant::Type get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL); - static StringName get_property_setter(StringName p_class, const StringName p_property); - static StringName get_property_getter(StringName p_class, const StringName p_property); + static StringName get_property_setter(StringName p_class, const StringName &p_property); + static StringName get_property_getter(StringName p_class, const StringName &p_property); static bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false); static void set_method_flags(StringName p_class, StringName p_method, int p_flags); @@ -355,7 +357,7 @@ public: static void get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance = false); static void get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance = false); - static Variant class_get_default_property_value(const StringName &p_class, const StringName &p_property); + static Variant class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid = NULL); static StringName get_category(const StringName &p_node); @@ -373,6 +375,7 @@ public: static void set_current_api(APIType p_api); static APIType get_current_api(); + static void cleanup_defaults(); static void cleanup(); }; diff --git a/core/color.cpp b/core/color.cpp index efd2941b47..1843532124 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -388,9 +388,8 @@ bool Color::html_is_valid(const String &p_color) { return false; } - int a = 255; if (alpha) { - a = _parse_col(color, 0); + int a = _parse_col(color, 0); if (a < 0) { return false; } @@ -525,7 +524,7 @@ Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const { float Color::gray() const { ERR_EXPLAIN("Color.gray() is deprecated and will be removed in a future version. Use Color.get_v() for a better grayscale approximation."); - WARN_DEPRECATED + WARN_DEPRECATED; return (r + g + b) / 3.0; } diff --git a/core/color.h b/core/color.h index b2148e1357..77f95b5dc9 100644 --- a/core/color.h +++ b/core/color.h @@ -195,7 +195,7 @@ struct Color { static Color named(const String &p_name); String to_html(bool p_alpha = true) const; Color from_hsv(float p_h, float p_s, float p_v, float p_a) const; - static Color from_rgbe9995(uint32_t p_color); + static Color from_rgbe9995(uint32_t p_rgbe); _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys operator String() const; diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h index 59eabd8786..3789eda5db 100644 --- a/core/command_queue_mt.h +++ b/core/command_queue_mt.h @@ -346,7 +346,7 @@ class CommandQueueMT { } return NULL; } - } else if (write_ptr >= dealloc_ptr) { + } else { // ahead of dealloc_ptr, check that there is room if ((COMMAND_MEM_SIZE - write_ptr) < alloc_size + sizeof(uint32_t)) { @@ -406,8 +406,10 @@ class CommandQueueMT { tryagain: // tried to read an empty queue - if (read_ptr == write_ptr) + if (read_ptr == write_ptr) { + if (p_lock) unlock(); return false; + } uint32_t size_ptr = read_ptr; uint32_t size = *(uint32_t *)&command_mem[read_ptr] >> 1; diff --git a/core/engine.cpp b/core/engine.cpp index 9607dedb3c..0dd0459403 100644 --- a/core/engine.cpp +++ b/core/engine.cpp @@ -38,6 +38,7 @@ void Engine::set_iterations_per_second(int p_ips) { + ERR_FAIL_COND(p_ips <= 0); ips = p_ips; } int Engine::get_iterations_per_second() const { @@ -196,8 +197,10 @@ void Engine::add_singleton(const Singleton &p_singleton) { Object *Engine::get_singleton_object(const String &p_name) const { const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name); - ERR_EXPLAIN("Failed to retrieve non-existent singleton '" + p_name + "'"); - ERR_FAIL_COND_V(!E, NULL); + if (!E) { + ERR_EXPLAIN("Failed to retrieve non-existent singleton '" + p_name + "'"); + ERR_FAIL_V(NULL); + } return E->get(); }; @@ -224,6 +227,7 @@ Engine::Engine() { frames_drawn = 0; ips = 60; physics_jitter_fix = 0.5; + _physics_interpolation_fraction = 0.0f; _frame_delay = 0; _fps = 1; _target_fps = 0; diff --git a/core/engine.h b/core/engine.h index 15665fee29..192e8e67a0 100644 --- a/core/engine.h +++ b/core/engine.h @@ -63,6 +63,7 @@ private: float _time_scale; bool _pixel_snap; uint64_t _physics_frames; + float _physics_interpolation_fraction; uint64_t _idle_frames; bool _in_physics; @@ -95,6 +96,7 @@ public: bool is_in_physics_frame() const { return _in_physics; } uint64_t get_idle_frame_ticks() const { return _frame_ticks; } float get_idle_frame_step() const { return _frame_step; } + float get_physics_interpolation_fraction() const { return _physics_interpolation_fraction; } void set_time_scale(float p_scale); float get_time_scale() const; diff --git a/core/error_list.h b/core/error_list.h index 304861da4e..dc5a5e68dd 100644 --- a/core/error_list.h +++ b/core/error_list.h @@ -39,7 +39,7 @@ */ enum Error { - OK, + OK, // (0) FAILED, ///< Generic fail error ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable ERR_UNCONFIGURED, ///< The object being used hasn't been properly set up yet @@ -69,12 +69,12 @@ enum Error { ERR_CONNECTION_ERROR, ERR_CANT_ACQUIRE_RESOURCE, ERR_CANT_FORK, - ERR_INVALID_DATA, ///< Data passed is invalid (30) + ERR_INVALID_DATA, ///< Data passed is invalid (30) ERR_INVALID_PARAMETER, ///< Parameter passed is invalid ERR_ALREADY_EXISTS, ///< When adding, item already exists - ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist + ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, if item does not exist ERR_DATABASE_CANT_READ, ///< database is full - ERR_DATABASE_CANT_WRITE, ///< database is full (35) + ERR_DATABASE_CANT_WRITE, ///< database is full (35) ERR_COMPILATION_FAILED, ERR_METHOD_NOT_FOUND, ERR_LINK_FAILED, diff --git a/core/error_macros.h b/core/error_macros.h index f72e987e23..69874e280b 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -136,8 +136,8 @@ extern bool _err_error_exists; 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 \ - _err_error_exists = false; \ + } \ + _err_error_exists = false; \ } while (0); // (*) /** An index has failed if m_index<0 or m_index >=m_size, the function exits. @@ -150,8 +150,8 @@ extern bool _err_error_exists; 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 \ - _err_error_exists = false; \ + } \ + _err_error_exists = false; \ } while (0); // (*) /** An index has failed if m_index >=m_size, the function exits. @@ -164,8 +164,8 @@ extern bool _err_error_exists; 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 \ - _err_error_exists = false; \ + } \ + _err_error_exists = false; \ } while (0); // (*) /** Use this one if there is no sensible fallback, that is, the error is unrecoverable. @@ -188,8 +188,8 @@ extern bool _err_error_exists; if (unlikely(!m_param)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \ return; \ - } else \ - _err_error_exists = false; \ + } \ + _err_error_exists = false; \ } #define ERR_FAIL_NULL_V(m_param, m_retval) \ @@ -197,8 +197,8 @@ extern bool _err_error_exists; if (unlikely(!m_param)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \ return m_retval; \ - } else \ - _err_error_exists = false; \ + } \ + _err_error_exists = false; \ } /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). @@ -210,8 +210,8 @@ extern bool _err_error_exists; if (unlikely(m_cond)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true."); \ return; \ - } else \ - _err_error_exists = false; \ + } \ + _err_error_exists = false; \ } /** Use this one if there is no sensible fallback, that is, the error is unrecoverable. @@ -236,8 +236,8 @@ extern bool _err_error_exists; 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 \ - _err_error_exists = false; \ + } \ + _err_error_exists = false; \ } /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). @@ -249,8 +249,8 @@ extern bool _err_error_exists; if (unlikely(m_cond)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Continuing..:"); \ continue; \ - } else \ - _err_error_exists = false; \ + } \ + _err_error_exists = false; \ } /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). @@ -262,8 +262,8 @@ extern bool _err_error_exists; if (unlikely(m_cond)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \ break; \ - } else \ - _err_error_exists = false; \ + } \ + _err_error_exists = false; \ } /** Print an error string and return diff --git a/core/global_constants.cpp b/core/global_constants.cpp index fb90403226..5bfdc8ab8f 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -425,6 +425,16 @@ void register_global_constants() { BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_X); BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_Y); + BIND_GLOBAL_ENUM_CONSTANT(JOY_VR_GRIP); + BIND_GLOBAL_ENUM_CONSTANT(JOY_VR_PAD); + BIND_GLOBAL_ENUM_CONSTANT(JOY_VR_TRIGGER); + + BIND_GLOBAL_ENUM_CONSTANT(JOY_OCULUS_AX); + BIND_GLOBAL_ENUM_CONSTANT(JOY_OCULUS_BY); + BIND_GLOBAL_ENUM_CONSTANT(JOY_OCULUS_MENU); + + BIND_GLOBAL_ENUM_CONSTANT(JOY_OPENVR_MENU); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SELECT); BIND_GLOBAL_ENUM_CONSTANT(JOY_START); BIND_GLOBAL_ENUM_CONSTANT(JOY_DPAD_UP); @@ -459,6 +469,12 @@ void register_global_constants() { BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_L2); BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_R2); + BIND_GLOBAL_ENUM_CONSTANT(JOY_VR_ANALOG_TRIGGER); + BIND_GLOBAL_ENUM_CONSTANT(JOY_VR_ANALOG_GRIP); + + BIND_GLOBAL_ENUM_CONSTANT(JOY_OPENVR_TOUCHPADX); + BIND_GLOBAL_ENUM_CONSTANT(JOY_OPENVR_TOUCHPADY); + // midi BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_OFF); BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_ON); @@ -470,47 +486,55 @@ void register_global_constants() { // error list - BIND_GLOBAL_ENUM_CONSTANT(OK); - BIND_GLOBAL_ENUM_CONSTANT(FAILED); ///< Generic fail error - BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAVAILABLE); ///< What is requested is unsupported/unavailable - BIND_GLOBAL_ENUM_CONSTANT(ERR_UNCONFIGURED); ///< The object being used hasn't been properly set up yet - BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAUTHORIZED); ///< Missing credentials for requested resource - BIND_GLOBAL_ENUM_CONSTANT(ERR_PARAMETER_RANGE_ERROR); ///< Parameter given out of range - BIND_GLOBAL_ENUM_CONSTANT(ERR_OUT_OF_MEMORY); ///< Out of memory + BIND_GLOBAL_ENUM_CONSTANT(OK); // (0) + BIND_GLOBAL_ENUM_CONSTANT(FAILED); + BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAVAILABLE); + BIND_GLOBAL_ENUM_CONSTANT(ERR_UNCONFIGURED); + BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAUTHORIZED); + BIND_GLOBAL_ENUM_CONSTANT(ERR_PARAMETER_RANGE_ERROR); // (5) + BIND_GLOBAL_ENUM_CONSTANT(ERR_OUT_OF_MEMORY); BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_NOT_FOUND); BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_BAD_DRIVE); BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_BAD_PATH); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_NO_PERMISSION); + BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_NO_PERMISSION); // (10) BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_ALREADY_IN_USE); BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CANT_OPEN); BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CANT_WRITE); BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CANT_READ); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_UNRECOGNIZED); + BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_UNRECOGNIZED); // (15) BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CORRUPT); BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_MISSING_DEPENDENCIES); BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_EOF); - BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_OPEN); ///< Can't open a resource/socket/file - BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_CREATE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_PARSE_ERROR); + BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_OPEN); + BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_CREATE); // (20) BIND_GLOBAL_ENUM_CONSTANT(ERR_QUERY_FAILED); BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_IN_USE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_LOCKED); ///< resource is locked + BIND_GLOBAL_ENUM_CONSTANT(ERR_LOCKED); BIND_GLOBAL_ENUM_CONSTANT(ERR_TIMEOUT); + BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_CONNECT); // (25) + BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_RESOLVE); + BIND_GLOBAL_ENUM_CONSTANT(ERR_CONNECTION_ERROR); BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_ACQUIRE_RESOURCE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DATA); ///< Data passed is invalid - BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_PARAMETER); ///< Parameter passed is invalid - BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_EXISTS); ///< When adding ), item already exists - BIND_GLOBAL_ENUM_CONSTANT(ERR_DOES_NOT_EXIST); ///< When retrieving/erasing ), it item does not exist - BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_READ); ///< database is full - BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_WRITE); ///< database is full + BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_FORK); + BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DATA); // (30) + BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_PARAMETER); + BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_EXISTS); + BIND_GLOBAL_ENUM_CONSTANT(ERR_DOES_NOT_EXIST); + BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_READ); + BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_WRITE); // (35) BIND_GLOBAL_ENUM_CONSTANT(ERR_COMPILATION_FAILED); BIND_GLOBAL_ENUM_CONSTANT(ERR_METHOD_NOT_FOUND); BIND_GLOBAL_ENUM_CONSTANT(ERR_LINK_FAILED); BIND_GLOBAL_ENUM_CONSTANT(ERR_SCRIPT_FAILED); - BIND_GLOBAL_ENUM_CONSTANT(ERR_CYCLIC_LINK); + BIND_GLOBAL_ENUM_CONSTANT(ERR_CYCLIC_LINK); // (40) + BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DECLARATION); + BIND_GLOBAL_ENUM_CONSTANT(ERR_DUPLICATE_SYMBOL); + BIND_GLOBAL_ENUM_CONSTANT(ERR_PARSE_ERROR); BIND_GLOBAL_ENUM_CONSTANT(ERR_BUSY); - BIND_GLOBAL_ENUM_CONSTANT(ERR_HELP); ///< user requested help!! - BIND_GLOBAL_ENUM_CONSTANT(ERR_BUG); ///< a bug in the software certainly happened ), due to a double check failing or unexpected behavior. + BIND_GLOBAL_ENUM_CONSTANT(ERR_SKIP); // (45) + BIND_GLOBAL_ENUM_CONSTANT(ERR_HELP); + BIND_GLOBAL_ENUM_CONSTANT(ERR_BUG); + BIND_GLOBAL_ENUM_CONSTANT(ERR_PRINTER_ON_FIRE); BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_NONE); BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_RANGE); diff --git a/core/hash_map.h b/core/hash_map.h index 44459a3080..1513d7a65b 100644 --- a/core/hash_map.h +++ b/core/hash_map.h @@ -162,20 +162,21 @@ private: new_hash_table[i] = 0; } - for (int i = 0; i < (1 << hash_table_power); i++) { + if (hash_table) { + for (int i = 0; i < (1 << hash_table_power); i++) { - while (hash_table[i]) { + while (hash_table[i]) { - Element *se = hash_table[i]; - hash_table[i] = se->next; - int new_pos = se->hash & ((1 << new_hash_table_power) - 1); - se->next = new_hash_table[new_pos]; - new_hash_table[new_pos] = se; + Element *se = hash_table[i]; + hash_table[i] = se->next; + int new_pos = se->hash & ((1 << new_hash_table_power) - 1); + se->next = new_hash_table[new_pos]; + new_hash_table[new_pos] = se; + } } - } - if (hash_table) memdelete_arr(hash_table); + } hash_table = new_hash_table; hash_table_power = new_hash_table_power; } @@ -207,7 +208,10 @@ private: /* if element doesn't exist, create it */ Element *e = memnew(Element); - ERR_FAIL_COND_V(!e, NULL); /* out of memory */ + if (!e) { + ERR_EXPLAIN("Out of memory"); + ERR_FAIL_V(NULL); + } uint32_t hash = Hasher::hash(p_key); uint32_t index = hash & ((1 << hash_table_power) - 1); e->next = hash_table[index]; @@ -494,8 +498,10 @@ public: } else { /* get the next key */ const Element *e = get_element(*p_key); - ERR_FAIL_COND_V(!e, NULL); /* invalid key supplied */ - + if (!e) { + ERR_EXPLAIN("Invalid key supplied") + ERR_FAIL_V(NULL); + } if (e->next) { /* if there is a "next" in the list, return that */ return &e->next->pair.key; diff --git a/core/image.cpp b/core/image.cpp index 30af724de9..a88395204a 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -495,8 +495,8 @@ 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 = PoolVector<uint8_t>::Read(); - w = PoolVector<uint8_t>::Write(); + r.release(); + w.release(); bool gen_mipmaps = mipmaps; @@ -749,7 +749,7 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict float scale_factor = MAX(x_scale, 1); // A larger kernel is required only when downscaling int32_t half_kernel = LANCZOS_TYPE * scale_factor; - float *kernel = memnew_arr(float, half_kernel * 2 - 1); + float *kernel = memnew_arr(float, half_kernel * 2); for (int32_t buffer_x = 0; buffer_x < dst_width; buffer_x++) { @@ -800,7 +800,7 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict float scale_factor = MAX(y_scale, 1); int32_t half_kernel = LANCZOS_TYPE * scale_factor; - float *kernel = memnew_arr(float, half_kernel * 2 - 1); + float *kernel = memnew_arr(float, half_kernel * 2); for (int32_t dst_y = 0; dst_y < dst_height; dst_y++) { @@ -1091,8 +1091,8 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { } break; } - r = PoolVector<uint8_t>::Read(); - w = PoolVector<uint8_t>::Write(); + r.release(); + w.release(); if (interpolate_mipmaps) { dst._copy_internals_from(dst2); @@ -1372,6 +1372,7 @@ void Image::shrink_x2() { int new_size = data.size() - ofs; new_img.resize(new_size); + ERR_FAIL_COND(new_img.size() == 0); { PoolVector<uint8_t>::Write w = new_img.write(); @@ -1391,6 +1392,7 @@ void Image::shrink_x2() { ERR_FAIL_COND(!_can_modify(format)); int ps = get_format_pixel_size(format); new_img.resize((width / 2) * (height / 2) * ps); + ERR_FAIL_COND(new_img.size() == 0); { PoolVector<uint8_t>::Write w = new_img.write(); @@ -1464,7 +1466,10 @@ Error Image::generate_mipmaps(bool p_renormalize) { ERR_FAIL_V(ERR_UNAVAILABLE); } - ERR_FAIL_COND_V(width == 0 || height == 0, ERR_UNCONFIGURED); + if (width == 0 || height == 0) { + ERR_EXPLAIN("Cannot generate mipmaps with width or height equal to 0."); + ERR_FAIL_V(ERR_UNCONFIGURED); + } int mmcount; @@ -2389,7 +2394,7 @@ void Image::lock() { void Image::unlock() { - write_lock = PoolVector<uint8_t>::Write(); + write_lock.release(); } Color Image::get_pixelv(const Point2 &p_src) const { @@ -2402,7 +2407,7 @@ Color Image::get_pixel(int p_x, int p_y) const { #ifdef DEBUG_ENABLED if (!ptr) { ERR_EXPLAIN("Image must be locked with 'lock()' before using get_pixel()"); - ERR_FAIL_COND_V(!ptr, Color()); + ERR_FAIL_V(Color()); } ERR_FAIL_INDEX_V(p_x, width, Color()); @@ -2532,7 +2537,7 @@ Color Image::get_pixel(int p_x, int p_y) const { } void Image::set_pixelv(const Point2 &p_dst, const Color &p_color) { - return set_pixel(p_dst.x, p_dst.y, 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) { @@ -2541,7 +2546,7 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) { #ifdef DEBUG_ENABLED if (!ptr) { ERR_EXPLAIN("Image must be locked with 'lock()' before using set_pixel()"); - ERR_FAIL_COND(!ptr); + ERR_FAIL(); } ERR_FAIL_INDEX(p_x, width); diff --git a/core/image.h b/core/image.h index 752ef20208..cc796789cd 100644 --- a/core/image.h +++ b/core/image.h @@ -350,7 +350,7 @@ public: Color get_pixelv(const Point2 &p_src) const; Color get_pixel(int p_x, int p_y) const; - void set_pixelv(const Point2 &p_dest, const Color &p_color); + void set_pixelv(const Point2 &p_dst, const Color &p_color); void set_pixel(int p_x, int p_y, const Color &p_color); void copy_internals_from(const Ref<Image> &p_image) { diff --git a/core/input_map.cpp b/core/input_map.cpp index 15f68f9c2a..04911787a8 100644 --- a/core/input_map.cpp +++ b/core/input_map.cpp @@ -194,7 +194,7 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str Map<StringName, Action>::Element *E = input_map.find(p_action); if (!E) { ERR_EXPLAIN("Request for nonexistent InputMap action: " + String(p_action)); - ERR_FAIL_COND_V(!E, false); + ERR_FAIL_V(false); } Ref<InputEventAction> input_event_action = p_event; @@ -202,7 +202,7 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str if (p_pressed != NULL) *p_pressed = input_event_action->is_pressed(); if (p_strength != NULL) - *p_strength = (*p_pressed) ? 1.0f : 0.0f; + *p_strength = (*p_pressed) ? input_event_action->get_strength() : 0.0f; return input_event_action->get_action() == p_action; } diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 414742deeb..f7fb72c089 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -30,7 +30,7 @@ #include "config_file.h" -#include "core/os/file_access.h" +#include "core/io/file_access_encrypted.h" #include "core/os/keyboard.h" #include "core/variant_parser.h" @@ -137,6 +137,48 @@ Error ConfigFile::save(const String &p_path) { return err; } + return _internal_save(file); +} + +Error ConfigFile::save_encrypted(const String &p_path, const Vector<uint8_t> &p_key) { + + Error err; + FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE, &err); + + if (err) + return err; + + FileAccessEncrypted *fae = memnew(FileAccessEncrypted); + err = fae->open_and_parse(f, p_key, FileAccessEncrypted::MODE_WRITE_AES256); + if (err) { + memdelete(fae); + memdelete(f); + return err; + } + return _internal_save(fae); +} + +Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass) { + + Error err; + FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE, &err); + + if (err) + return err; + + FileAccessEncrypted *fae = memnew(FileAccessEncrypted); + err = fae->open_and_parse_password(f, p_pass, FileAccessEncrypted::MODE_WRITE_AES256); + if (err) { + memdelete(fae); + memdelete(f); + return err; + } + + return _internal_save(fae); +} + +Error ConfigFile::_internal_save(FileAccess *file) { + for (OrderedHashMap<String, OrderedHashMap<String, Variant> >::Element E = values.front(); E; E = E.next()) { if (E != values.front()) @@ -164,6 +206,48 @@ Error ConfigFile::load(const String &p_path) { if (!f) return ERR_CANT_OPEN; + return _internal_load(p_path, f); +} + +Error ConfigFile::load_encrypted(const String &p_path, const Vector<uint8_t> &p_key) { + + Error err; + FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); + + if (err) + return err; + + FileAccessEncrypted *fae = memnew(FileAccessEncrypted); + err = fae->open_and_parse(f, p_key, FileAccessEncrypted::MODE_READ); + if (err) { + memdelete(fae); + memdelete(f); + return err; + } + return _internal_load(p_path, fae); +} + +Error ConfigFile::load_encrypted_pass(const String &p_path, const String &p_pass) { + + Error err; + FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); + + if (err) + return err; + + FileAccessEncrypted *fae = memnew(FileAccessEncrypted); + err = fae->open_and_parse_password(f, p_pass, FileAccessEncrypted::MODE_READ); + if (err) { + memdelete(fae); + memdelete(f); + return err; + } + + return _internal_load(p_path, fae); +} + +Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) { + VariantParser::StreamFile stream; stream.f = f; @@ -182,7 +266,7 @@ Error ConfigFile::load(const String &p_path) { next_tag.fields.clear(); next_tag.name = String(); - err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true); + Error err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true); if (err == ERR_FILE_EOF) { memdelete(f); return OK; @@ -198,10 +282,6 @@ Error ConfigFile::load(const String &p_path) { section = next_tag.name; } } - - memdelete(f); - - return OK; } void ConfigFile::_bind_methods() { @@ -219,6 +299,12 @@ void ConfigFile::_bind_methods() { ClassDB::bind_method(D_METHOD("load", "path"), &ConfigFile::load); ClassDB::bind_method(D_METHOD("save", "path"), &ConfigFile::save); + + ClassDB::bind_method(D_METHOD("load_encrypted", "path", "key"), &ConfigFile::load_encrypted); + ClassDB::bind_method(D_METHOD("load_encrypted_pass", "path", "pass"), &ConfigFile::load_encrypted_pass); + + ClassDB::bind_method(D_METHOD("save_encrypted", "path", "key"), &ConfigFile::save_encrypted); + ClassDB::bind_method(D_METHOD("save_encrypted_pass", "path", "pass"), &ConfigFile::save_encrypted_pass); } ConfigFile::ConfigFile() { diff --git a/core/io/config_file.h b/core/io/config_file.h index 36e5c0ca7d..3ab6fef868 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -32,6 +32,7 @@ #define CONFIG_FILE_H #include "core/ordered_hash_map.h" +#include "core/os/file_access.h" #include "core/reference.h" class ConfigFile : public Reference { @@ -42,6 +43,8 @@ class ConfigFile : public Reference { PoolStringArray _get_sections() const; PoolStringArray _get_section_keys(const String &p_section) const; + Error _internal_load(const String &p_path, FileAccess *f); + Error _internal_save(FileAccess *file); protected: static void _bind_methods(); @@ -61,6 +64,12 @@ public: Error save(const String &p_path); Error load(const String &p_path); + 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); + + Error save_encrypted(const String &p_path, const Vector<uint8_t> &p_key); + Error save_encrypted_pass(const String &p_path, const String &p_pass); + ConfigFile(); }; diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp index 83ff532aa4..15523a49a9 100644 --- a/core/io/file_access_buffered.cpp +++ b/core/io/file_access_buffered.cpp @@ -35,79 +35,79 @@ Error FileAccessBuffered::set_error(Error p_error) const { return (last_error = p_error); -}; +} void FileAccessBuffered::set_cache_size(int p_size) { cache_size = p_size; -}; +} int FileAccessBuffered::get_cache_size() { return cache_size; -}; +} int FileAccessBuffered::cache_data_left() const { if (file.offset >= file.size) { return 0; - }; + } if (cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size()) { return read_data_block(file.offset, cache_size); + } - } else { - - return cache.buffer.size() - (file.offset - cache.offset); - }; - - return 0; -}; + return cache.buffer.size() - (file.offset - cache.offset); +} void FileAccessBuffered::seek(size_t p_position) { file.offset = p_position; -}; +} void FileAccessBuffered::seek_end(int64_t p_position) { file.offset = file.size + p_position; -}; +} size_t FileAccessBuffered::get_position() const { return file.offset; -}; +} size_t FileAccessBuffered::get_len() const { return file.size; -}; +} bool FileAccessBuffered::eof_reached() const { return file.offset > file.size; -}; +} uint8_t FileAccessBuffered::get_8() const { - - ERR_FAIL_COND_V(!file.open, 0); + if (!file.open) { + ERR_EXPLAIN("Can't get data, when file is not opened."); + ERR_FAIL_V(0); + } uint8_t byte = 0; if (cache_data_left() >= 1) { byte = cache.buffer[file.offset - cache.offset]; - }; + } ++file.offset; return byte; -}; +} int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { - - ERR_FAIL_COND_V(!file.open, -1); + if (!file.open) { + ERR_EXPLAIN("Can't get buffer, when file is not opened."); + ERR_FAIL_V(-1); + } if (p_length > cache_size) { @@ -124,16 +124,16 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { p_length -= size; file.offset += size; total_read += size; - }; + } int err = read_data_block(file.offset, p_length, p_dest); if (err >= 0) { total_read += err; file.offset += err; - }; + } return total_read; - }; + } int to_read = p_length; int total_read = 0; @@ -141,14 +141,12 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { int left = cache_data_left(); if (left == 0) { - if (to_read > 0) { - file.offset += to_read; - }; + file.offset += to_read; return total_read; - }; + } if (left < 0) { return left; - }; + } int r = MIN(left, to_read); //PoolVector<uint8_t>::Read read = cache.buffer.read(); @@ -158,25 +156,25 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { file.offset += r; total_read += r; to_read -= r; - }; + } return p_length; -}; +} bool FileAccessBuffered::is_open() const { return file.open; -}; +} Error FileAccessBuffered::get_error() const { return last_error; -}; +} FileAccessBuffered::FileAccessBuffered() { cache_size = DEFAULT_CACHE_SIZE; -}; +} FileAccessBuffered::~FileAccessBuffered() { } diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h index 24b40cbce8..6e806e7b3f 100644 --- a/core/io/file_access_buffered_fa.h +++ b/core/io/file_access_buffered_fa.h @@ -40,7 +40,10 @@ class FileAccessBufferedFA : public FileAccessBuffered { int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const { - ERR_FAIL_COND_V(!f.is_open(), -1); + if (!f.is_open()) { + ERR_EXPLAIN("Can't read data block, when file is not opened."); + ERR_FAIL_V(-1); + } ((T *)&f)->seek(p_offset); diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 3cf6908961..ccee6aeb15 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -30,13 +30,11 @@ #include "file_access_encrypted.h" +#include "core/math/crypto_core.h" #include "core/os/copymem.h" #include "core/print_string.h" #include "core/variant.h" -#include "thirdparty/misc/aes256.h" -#include "thirdparty/misc/md5.h" - #include <stdio.h> #define COMP_MAGIC 0x43454447 @@ -83,24 +81,21 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8 uint32_t blen = p_base->get_buffer(data.ptrw(), ds); ERR_FAIL_COND_V(blen != ds, ERR_FILE_CORRUPT); - aes256_context ctx; - aes256_init(&ctx, key.ptrw()); + CryptoCore::AESContext ctx; + ctx.set_decode_key(key.ptrw(), 256); for (size_t i = 0; i < ds; i += 16) { - aes256_decrypt_ecb(&ctx, &data.write[i]); + ctx.decrypt_ecb(&data.write[i], &data.write[i]); } - aes256_done(&ctx); - data.resize(length); - MD5_CTX md5; - MD5Init(&md5); - MD5Update(&md5, (uint8_t *)data.ptr(), data.size()); - MD5Final(&md5); + unsigned char hash[16]; + ERR_FAIL_COND_V(CryptoCore::md5(data.ptr(), data.size(), hash) != OK, ERR_BUG); - ERR_FAIL_COND_V(String::md5(md5.digest) != String::md5(md5d), ERR_FILE_CORRUPT); + ERR_EXPLAIN("The MD5 sum of the decrypted file does not match the expected value. It could be that the file is corrupt, or that the provided decryption key is invalid."); + ERR_FAIL_COND_V(String::md5(hash) != String::md5(md5d), ERR_FILE_CORRUPT); file = p_base; } @@ -139,10 +134,8 @@ void FileAccessEncrypted::close() { len += 16 - (len % 16); } - MD5_CTX md5; - MD5Init(&md5); - MD5Update(&md5, (uint8_t *)data.ptr(), data.size()); - MD5Final(&md5); + unsigned char hash[16]; + ERR_FAIL_COND(CryptoCore::md5(data.ptr(), data.size(), hash) != OK); // Bug? compressed.resize(len); zeromem(compressed.ptrw(), len); @@ -150,20 +143,18 @@ void FileAccessEncrypted::close() { compressed.write[i] = data[i]; } - aes256_context ctx; - aes256_init(&ctx, key.ptrw()); + CryptoCore::AESContext ctx; + ctx.set_encode_key(key.ptrw(), 256); for (size_t i = 0; i < len; i += 16) { - aes256_encrypt_ecb(&ctx, &compressed.write[i]); + ctx.encrypt_ecb(&compressed.write[i], &compressed.write[i]); } - aes256_done(&ctx); - file->store_32(COMP_MAGIC); file->store_32(mode); - file->store_buffer(md5.digest, 16); + file->store_buffer(hash, 16); file->store_64(data.size()); file->store_buffer(compressed.ptr(), compressed.size()); @@ -307,8 +298,8 @@ uint32_t FileAccessEncrypted::_get_unix_permissions(const String &p_file) { } Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t p_permissions) { - - return FAILED; + ERR_PRINT("Setting UNIX permissions on encrypted files is not implemented yet"); + return ERR_UNAVAILABLE; } FileAccessEncrypted::FileAccessEncrypted() { diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index 722e62c54e..d1c7f5c334 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -118,7 +118,10 @@ void FileAccessNetworkClient::_thread_func() { FileAccessNetwork *fa = NULL; if (response != FileAccessNetwork::RESPONSE_DATA) { - ERR_FAIL_COND(!accesses.has(id)); + if (!accesses.has(id)) { + unlock_mutex(); + ERR_FAIL_COND(!accesses.has(id)); + } } if (accesses.has(id)) @@ -432,7 +435,6 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { _queue_page(page + j); } - buff = pages.write[page].buffer.ptrw(); //queue pages buffer_mutex->unlock(); } @@ -498,13 +500,13 @@ uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) { } uint32_t FileAccessNetwork::_get_unix_permissions(const String &p_file) { - //could be implemented, not sure if worth it + ERR_PRINT("Getting UNIX permissions from network drives is not implemented yet"); return 0; } Error FileAccessNetwork::_set_unix_permissions(const String &p_file, uint32_t p_permissions) { - - return FAILED; + ERR_PRINT("Setting UNIX permissions on network drives is not implemented yet"); + return ERR_UNAVAILABLE; } void FileAccessNetwork::configure() { diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index d38d09c6bb..ca66b34e17 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -144,7 +144,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) { uint32_t magic = f->get_32(); if (magic != 0x43504447) { - //maybe at he end.... self contained exe + //maybe at the end.... self contained exe f->seek_end(); f->seek(f->get_position() - 4); magic = f->get_32(); diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index ce2054db36..170bef4430 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -346,6 +346,12 @@ Error HTTPClient::poll() { } else { // We are already handshaking, which means we can use your already active SSL connection ssl = static_cast<Ref<StreamPeerSSL> >(connection); + if (ssl.is_null()) { + close(); + status = STATUS_SSL_HANDSHAKE_ERROR; + return ERR_CANT_CONNECT; + } + ssl->poll(); // Try to finish the handshake } @@ -476,8 +482,6 @@ Error HTTPClient::poll() { return OK; } } - // Wait for response - return OK; } break; case STATUS_DISCONNECTED: { return ERR_UNCONFIGURED; @@ -769,7 +773,7 @@ Dictionary HTTPClient::_get_response_headers_as_dictionary() { get_response_headers(&rh); Dictionary ret; for (const List<String>::Element *E = rh.front(); E; E = E->next()) { - String s = E->get(); + const String &s = E->get(); int sp = s.find(":"); if (sp == -1) continue; diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index a5a0738140..a759e615c7 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -65,6 +65,9 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c if (!loader[i]->recognize(extension)) 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); + } if (err != ERR_FILE_UNRECOGNIZED) { diff --git a/core/io/image_loader.h b/core/io/image_loader.h index 95c562b7a9..ae4b72a534 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -88,7 +88,6 @@ public: }; class ResourceFormatLoaderImage : public ResourceFormatLoader { - GDCLASS(ResourceFormatLoaderImage, ResourceFormatLoader) public: virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 420e48f839..3d87131b51 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -234,6 +234,41 @@ Array IP::_get_local_addresses() const { return addresses; } +Array IP::_get_local_interfaces() const { + + Array results; + Map<String, Interface_Info> interfaces; + get_local_interfaces(&interfaces); + for (Map<String, Interface_Info>::Element *E = interfaces.front(); E; E = E->next()) { + Interface_Info &c = E->get(); + Dictionary rc; + rc["name"] = c.name; + rc["friendly"] = c.name_friendly; + rc["index"] = c.index; + + Array ips; + for (const List<IP_Address>::Element *F = c.ip_addresses.front(); F; F = F->next()) { + ips.push_front(F->get()); + } + rc["addresses"] = ips; + + results.push_front(rc); + } + + return results; +} + +void IP::get_local_addresses(List<IP_Address> *r_addresses) const { + + Map<String, Interface_Info> interfaces; + get_local_interfaces(&interfaces); + for (Map<String, Interface_Info>::Element *E = interfaces.front(); E; E = E->next()) { + for (const List<IP_Address>::Element *F = E->get().ip_addresses.front(); F; F = F->next()) { + r_addresses->push_front(F->get()); + } + } +} + void IP::_bind_methods() { ClassDB::bind_method(D_METHOD("resolve_hostname", "host", "ip_type"), &IP::resolve_hostname, DEFVAL(IP::TYPE_ANY)); @@ -242,6 +277,7 @@ void IP::_bind_methods() { ClassDB::bind_method(D_METHOD("get_resolve_item_address", "id"), &IP::get_resolve_item_address); ClassDB::bind_method(D_METHOD("erase_resolve_item", "id"), &IP::erase_resolve_item); ClassDB::bind_method(D_METHOD("get_local_addresses"), &IP::_get_local_addresses); + ClassDB::bind_method(D_METHOD("get_local_interfaces"), &IP::_get_local_interfaces); ClassDB::bind_method(D_METHOD("clear_cache", "hostname"), &IP::clear_cache, DEFVAL("")); BIND_ENUM_CONSTANT(RESOLVER_STATUS_NONE); diff --git a/core/io/ip.h b/core/io/ip.h index ead71ebb54..59b18ef986 100644 --- a/core/io/ip.h +++ b/core/io/ip.h @@ -73,16 +73,25 @@ protected: virtual IP_Address _resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY) = 0; Array _get_local_addresses() const; + Array _get_local_interfaces() const; static IP *(*_create)(); public: + struct Interface_Info { + String name; + String name_friendly; + String index; + List<IP_Address> ip_addresses; + }; + IP_Address resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY); // async resolver hostname ResolverID resolve_hostname_queue_item(const String &p_hostname, Type p_type = TYPE_ANY); ResolverStatus get_resolve_item_status(ResolverID p_id) const; IP_Address get_resolve_item_address(ResolverID p_id) const; - virtual void get_local_addresses(List<IP_Address> *r_addresses) const = 0; + virtual void get_local_addresses(List<IP_Address> *r_addresses) const; + virtual void get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const = 0; void erase_resolve_item(ResolverID p_id); void clear_cache(const String &p_hostname = ""); diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 763a5fbb9a..9305afac5f 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -40,6 +40,9 @@ IP_Address::operator Variant() const { IP_Address::operator String() const { + if (wildcard) + return "*"; + if (!valid) return ""; diff --git a/core/io/json.cpp b/core/io/json.cpp index c211ca2ed4..4e729cb355 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -347,8 +347,6 @@ Error JSON::_parse_value(Variant &value, Token &token, const CharType *p_str, in r_err_str = "Expected value, got " + String(tk_name[token.type]) + "."; return ERR_PARSE_ERROR; } - - return ERR_PARSE_ERROR; } Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index d1b6b82cf0..dc5581ea01 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -37,13 +37,11 @@ #include <limits.h> #include <stdio.h> -#define _S(a) ((int32_t)a) -#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(_S(b) < 0 || _S(a) < 0 || _S(a) > INT_MAX - _S(b), err) -#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(_S(a) < 0 || _S(b) <= 0 || _S(a) > INT_MAX / _S(b), err) - void EncodedObjectAsID::_bind_methods() { ClassDB::bind_method(D_METHOD("set_object_id", "id"), &EncodedObjectAsID::set_object_id); ClassDB::bind_method(D_METHOD("get_object_id"), &EncodedObjectAsID::get_object_id); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "object_id"), "set_object_id", "get_object_id"); } void EncodedObjectAsID::set_object_id(ObjectID p_id) { @@ -59,6 +57,10 @@ EncodedObjectAsID::EncodedObjectAsID() : id(0) { } +#define _S(a) ((int32_t)a) +#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(_S(b) < 0 || _S(a) < 0 || _S(a) > INT_MAX - _S(b), err) +#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(_S(a) < 0 || _S(b) <= 0 || _S(a) > INT_MAX / _S(b), err) + #define ENCODE_MASK 0xFF #define ENCODE_FLAG_64 1 << 16 #define ENCODE_FLAG_OBJECT_AS_ID 1 << 16 @@ -103,10 +105,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int const uint8_t *buf = p_buffer; int len = p_len; - if (len < 4) { - - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); - } + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); uint32_t type = decode_uint32(buf); @@ -559,8 +558,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int w[i] = buf[i]; } - - w = PoolVector<uint8_t>::Write(); } r_variant = data; @@ -591,8 +588,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int w[i] = decode_uint32(&buf[i * 4]); } - - w = PoolVector<int>::Write(); } r_variant = Variant(data); if (r_len) { @@ -619,8 +614,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int w[i] = decode_float(&buf[i * 4]); } - - w = PoolVector<float>::Write(); } r_variant = data; @@ -684,8 +677,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (r_len) (*r_len) += adv; - len -= adv; - buf += adv; } r_variant = varray; @@ -722,8 +713,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (r_len) (*r_len) += adv; - len -= adv; - buf += adv; } r_variant = varray; @@ -761,8 +750,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (r_len) (*r_len) += adv; - len -= adv; - buf += adv; } r_variant = carray; @@ -1095,7 +1082,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo if (!obj) { if (buf) { encode_uint32(0, buf); - buf += 4; } r_len += 4; diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 2779837190..33dc4dbde4 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -874,6 +874,7 @@ void MultiplayerAPI::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer"); + ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false); ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id"))); diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h index 779dd043bd..5258dde5d7 100644 --- a/core/io/multiplayer_api.h +++ b/core/io/multiplayer_api.h @@ -77,7 +77,7 @@ protected: 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_from); + bool _send_confirm_path(NodePath p_path, PathSentCache *psc, int p_target); public: enum NetworkCommands { diff --git a/core/io/net_socket.h b/core/io/net_socket.h index 94e7ef6f75..3bc1369487 100644 --- a/core/io/net_socket.h +++ b/core/io/net_socket.h @@ -74,6 +74,8 @@ public: virtual void set_ipv6_only_enabled(bool p_enabled) = 0; virtual void set_tcp_no_delay_enabled(bool p_enabled) = 0; virtual void set_reuse_address_enabled(bool p_enabled) = 0; + virtual Error join_multicast_group(const IP_Address &p_multi_address, String p_if_name) = 0; + virtual Error leave_multicast_group(const IP_Address &p_multi_address, String p_if_name) = 0; }; #endif // NET_SOCKET_H diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index 5912b8df94..7e9471c053 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -37,6 +37,27 @@ void PacketPeerUDP::set_blocking_mode(bool p_enable) { blocking = p_enable; } +Error PacketPeerUDP::join_multicast_group(IP_Address p_multi_address, String p_if_name) { + + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(!p_multi_address.is_valid(), ERR_INVALID_PARAMETER); + + if (!_sock->is_open()) { + IP::Type ip_type = p_multi_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + Error err = _sock->open(NetSocket::TYPE_UDP, ip_type); + ERR_FAIL_COND_V(err != OK, err); + _sock->set_blocking_enabled(false); + } + return _sock->join_multicast_group(p_multi_address, p_if_name); +} + +Error PacketPeerUDP::leave_multicast_group(IP_Address p_multi_address, String p_if_name) { + + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(!_sock->is_open(), ERR_UNCONFIGURED); + return _sock->leave_multicast_group(p_multi_address, p_if_name); +} + String PacketPeerUDP::_get_packet_ip() const { return get_packet_address(); @@ -237,6 +258,8 @@ void PacketPeerUDP::_bind_methods() { 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); + ClassDB::bind_method(D_METHOD("join_multicast_group", "multicast_address", "interface_name"), &PacketPeerUDP::join_multicast_group); + ClassDB::bind_method(D_METHOD("leave_multicast_group", "multicast_address", "interface_name"), &PacketPeerUDP::leave_multicast_group); } PacketPeerUDP::PacketPeerUDP() : diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 0593137604..068bd5cd5a 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -77,6 +77,8 @@ public: Error get_packet(const uint8_t **r_buffer, int &r_buffer_size); int get_available_packet_count() const; int get_max_packet_size() const; + Error join_multicast_group(IP_Address p_multi_address, String p_if_name); + Error leave_multicast_group(IP_Address p_multi_address, String p_if_name); PacketPeerUDP(); ~PacketPeerUDP(); diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index 8920bbfb81..c16d89d695 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -63,10 +63,11 @@ void PCKPacker::_bind_methods() { Error PCKPacker::pck_start(const String &p_file, int p_alignment) { file = FileAccess::open(p_file, FileAccess::WRITE); - if (file == NULL) { - return ERR_CANT_CREATE; - }; + if (!file) { + ERR_EXPLAIN("Can't open file to write: " + String(p_file)); + ERR_FAIL_V(ERR_CANT_CREATE); + } alignment = p_alignment; @@ -109,10 +110,7 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src) { Error PCKPacker::flush(bool p_verbose) { - if (!file) { - ERR_FAIL_COND_V(!file, ERR_INVALID_PARAMETER); - return ERR_INVALID_PARAMETER; - }; + ERR_FAIL_COND_V(!file, ERR_INVALID_PARAMETER); // write the index diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index f25abc4aab..861e34e415 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -410,7 +410,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { PoolVector<uint8_t>::Write w = array.write(); f->get_buffer(w.ptr(), len); _advance_padding(len); - w = PoolVector<uint8_t>::Write(); + w.release(); r_v = array; } break; @@ -432,7 +432,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } #endif - w = PoolVector<int>::Write(); + w.release(); r_v = array; } break; case VARIANT_REAL_ARRAY: { @@ -454,7 +454,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { #endif - w = PoolVector<real_t>::Write(); + w.release(); r_v = array; } break; case VARIANT_STRING_ARRAY: { @@ -465,7 +465,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { PoolVector<String>::Write w = array.write(); for (uint32_t i = 0; i < len; i++) w[i] = get_unicode_string(); - w = PoolVector<String>::Write(); + w.release(); r_v = array; } break; @@ -493,7 +493,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { ERR_EXPLAIN("Vector2 size is NOT 8!"); ERR_FAIL_V(ERR_UNAVAILABLE); } - w = PoolVector<Vector2>::Write(); + w.release(); r_v = array; } break; @@ -521,7 +521,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { ERR_EXPLAIN("Vector3 size is NOT 12!"); ERR_FAIL_V(ERR_UNAVAILABLE); } - w = PoolVector<Vector3>::Write(); + w.release(); r_v = array; } break; @@ -549,7 +549,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { ERR_EXPLAIN("Color size is NOT 16!"); ERR_FAIL_V(ERR_UNAVAILABLE); } - w = PoolVector<Color>::Write(); + w.release(); r_v = array; } break; #ifndef DISABLE_DEPRECATED @@ -584,7 +584,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { PoolVector<uint8_t>::Write w = imgdata.write(); f->get_buffer(w.ptr(), datalen); _advance_padding(datalen); - w = PoolVector<uint8_t>::Write(); + w.release(); Ref<Image> image; image.instance(); @@ -597,7 +597,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { data.resize(f->get_32()); PoolVector<uint8_t>::Write w = data.write(); f->get_buffer(w.ptr(), data.size()); - w = PoolVector<uint8_t>::Write(); + w.release(); Ref<Image> image; @@ -720,7 +720,7 @@ Error ResourceInteractiveLoaderBinary::poll() { error = ERR_FILE_CORRUPT; memdelete(obj); //bye ERR_EXPLAIN(local_path + ":Resource type in resource field not a resource, type is: " + obj->get_class()); - ERR_FAIL_COND_V(!r, ERR_FILE_CORRUPT); + ERR_FAIL_V(ERR_FILE_CORRUPT); } RES res = RES(r); @@ -991,10 +991,7 @@ Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(cons Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); - if (err != OK) { - - ERR_FAIL_COND_V(err != OK, Ref<ResourceInteractiveLoader>()); - } + ERR_FAIL_COND_V(err != OK, Ref<ResourceInteractiveLoader>()); Ref<ResourceInteractiveLoaderBinary> ria = memnew(ResourceInteractiveLoaderBinary); String path = p_original_path != "" ? p_original_path : p_path; @@ -1129,9 +1126,8 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons Error err; f = FileAccess::open(p_path, FileAccess::READ, &err); - if (err != OK) { - ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN); - } + + ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN); Ref<ResourceInteractiveLoaderBinary> ria = memnew(ResourceInteractiveLoaderBinary); ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); @@ -1698,7 +1694,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant int len = varray.size(); for (int i = 0; i < len; i++) { - Variant v = varray.get(i); + const Variant &v = varray.get(i); _find_resources(v); } diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index a4894e4033..27777c8e8b 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -100,7 +100,6 @@ public: }; class ResourceFormatLoaderBinary : public ResourceFormatLoader { - GDCLASS(ResourceFormatLoaderBinary, ResourceFormatLoader) public: virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; @@ -162,7 +161,6 @@ public: }; class ResourceFormatSaverBinary : public ResourceFormatSaver { - GDCLASS(ResourceFormatSaverBinary, ResourceFormatSaver) public: static ResourceFormatSaverBinary *singleton; virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 4a58d37ca5..63d7ba547c 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -161,7 +161,8 @@ void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extension void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const { if (p_type == "") { - return get_recognized_extensions(p_extensions); + get_recognized_extensions(p_extensions); + return; } Set<String> found; @@ -347,7 +348,7 @@ void ResourceFormatImporter::get_dependencies(const String &p_path, List<String> return; } - return ResourceLoader::get_dependencies(pat.path, p_dependencies, p_add_types); + ResourceLoader::get_dependencies(pat.path, p_dependencies, p_add_types); } Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String &p_name) const { diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index 2e01989564..9cf298a7f5 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -37,8 +37,6 @@ class ResourceImporter; class ResourceFormatImporter : public ResourceFormatLoader { - GDCLASS(ResourceFormatImporter, ResourceFormatLoader) - struct PathAndType { String path; String type; @@ -96,7 +94,8 @@ public: class ResourceImporter : public Reference { - GDCLASS(ResourceImporter, Reference) + GDCLASS(ResourceImporter, Reference); + public: virtual String get_importer_name() const = 0; virtual String get_visible_name() const = 0; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 56d3b8b133..a29b9d1ddb 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -207,8 +207,6 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa ERR_FAIL_COND_V(err != OK, RES()); } - - return RES(); } void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { @@ -283,7 +281,6 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c ERR_EXPLAIN("No loader found for resource: " + p_path); } ERR_FAIL_V(RES()); - return RES(); } bool ResourceLoader::_add_to_loading_map(const String &p_path) { @@ -543,7 +540,6 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_ ERR_EXPLAIN("No loader found for resource: " + path); } ERR_FAIL_V(Ref<ResourceInteractiveLoader>()); - return Ref<ResourceInteractiveLoader>(); } void ResourceLoader::add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front) { diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 9e7020be7c..70e7bdc224 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -62,7 +62,7 @@ public: class ResourceFormatLoader : public Reference { - GDCLASS(ResourceFormatLoader, Reference) + GDCLASS(ResourceFormatLoader, Reference); protected: static void _bind_methods(); diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h index 7df3bfb1f8..0fba47a5e8 100644 --- a/core/io/resource_saver.h +++ b/core/io/resource_saver.h @@ -38,7 +38,7 @@ */ class ResourceFormatSaver : public Reference { - GDCLASS(ResourceFormatSaver, Reference) + GDCLASS(ResourceFormatSaver, Reference); protected: static void _bind_methods(); diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index 6ad24a5f3a..acf72dbba5 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -79,7 +79,7 @@ Array StreamPeer::_get_data(int p_bytes) { PoolVector<uint8_t>::Write w = data.write(); Error err = get_data(&w[0], p_bytes); - w = PoolVector<uint8_t>::Write(); + w.release(); ret.push_back(err); ret.push_back(data); return ret; @@ -101,7 +101,7 @@ Array StreamPeer::_get_partial_data(int p_bytes) { PoolVector<uint8_t>::Write w = data.write(); int received; Error err = get_partial_data(&w[0], p_bytes, received); - w = PoolVector<uint8_t>::Write(); + w.release(); if (err != OK) { data.resize(0); diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp index 254ae84bf5..ccce48ccd7 100644 --- a/core/io/stream_peer_ssl.cpp +++ b/core/io/stream_peer_ssl.cpp @@ -39,7 +39,9 @@ StreamPeerSSL *(*StreamPeerSSL::_create)() = NULL; StreamPeerSSL *StreamPeerSSL::create() { - return _create(); + if (_create) + return _create(); + return NULL; } StreamPeerSSL::LoadCertsFromMemory StreamPeerSSL::load_certs_func = NULL; diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 45f3e46e35..310bb12bc0 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -30,6 +30,8 @@ #include "stream_peer_tcp.h" +#include "core/project_settings.h" + Error StreamPeerTCP::_poll_connection() { ERR_FAIL_COND_V(status != STATUS_CONNECTING || !_sock.is_valid() || !_sock->is_open(), FAILED); @@ -40,6 +42,12 @@ Error StreamPeerTCP::_poll_connection() { status = STATUS_CONNECTED; return OK; } else if (err == ERR_BUSY) { + // Check for connect timeout + if (OS::get_singleton()->get_ticks_msec() > timeout) { + disconnect_from_host(); + status = STATUS_ERROR; + return ERR_CONNECTION_ERROR; + } // Still trying to connect return OK; } @@ -54,6 +62,7 @@ void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint _sock = p_sock; _sock->set_blocking_enabled(false); + timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000); status = STATUS_CONNECTING; peer_host = p_host; @@ -74,6 +83,7 @@ Error StreamPeerTCP::connect_to_host(const IP_Address &p_host, uint16_t p_port) _sock->set_blocking_enabled(false); + timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000); err = _sock->connect_to_host(p_host, p_port); if (err == OK) { @@ -217,6 +227,11 @@ Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool to_read -= read; total_read += read; + + if (!p_block) { + r_received = total_read; + return OK; + } } } @@ -276,6 +291,7 @@ void StreamPeerTCP::disconnect_from_host() { if (_sock.is_valid() && _sock->is_open()) _sock->close(); + timeout = 0; status = STATUS_NONE; peer_host = IP_Address(); peer_port = 0; @@ -351,8 +367,8 @@ void StreamPeerTCP::_bind_methods() { StreamPeerTCP::StreamPeerTCP() : _sock(Ref<NetSocket>(NetSocket::create())), + timeout(0), status(STATUS_NONE), - peer_host(IP_Address()), peer_port(0) { } diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index 1ca39375aa..321fb3a6c8 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -52,6 +52,7 @@ public: protected: Ref<NetSocket> _sock; + uint64_t timeout; Status status; IP_Address peer_host; uint16_t peer_port; diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 6599c4eb5b..a2756164bc 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -34,6 +34,7 @@ void TCP_Server::_bind_methods() { ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*")); ClassDB::bind_method(D_METHOD("is_connection_available"), &TCP_Server::is_connection_available); + ClassDB::bind_method(D_METHOD("is_listening"), &TCP_Server::is_listening); ClassDB::bind_method(D_METHOD("take_connection"), &TCP_Server::take_connection); ClassDB::bind_method(D_METHOD("stop"), &TCP_Server::stop); } @@ -75,6 +76,12 @@ Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) { return OK; } +bool TCP_Server::is_listening() const { + ERR_FAIL_COND_V(!_sock.is_valid(), false); + + return _sock->is_open(); +} + bool TCP_Server::is_connection_available() const { ERR_FAIL_COND_V(!_sock.is_valid(), false); @@ -83,11 +90,7 @@ bool TCP_Server::is_connection_available() const { return false; Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0); - if (err != OK) { - return false; - } - - return true; + return (err == OK); } Ref<StreamPeerTCP> TCP_Server::take_connection() { diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index 538db175ad..ef64044599 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -50,6 +50,7 @@ protected: 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<StreamPeerTCP> take_connection(); diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h index d5fd264385..9d9c5d16ee 100644 --- a/core/io/translation_loader_po.h +++ b/core/io/translation_loader_po.h @@ -36,7 +36,6 @@ #include "core/translation.h" class TranslationLoaderPO : public ResourceFormatLoader { - GDCLASS(TranslationLoaderPO, ResourceFormatLoader) public: static RES load_translation(FileAccess *f, Error *r_error, const String &p_path = String()); virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index 4638ddcc09..82527d3f38 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -348,7 +348,7 @@ uint64_t XMLParser::get_node_offset() const { Error XMLParser::seek(uint64_t p_pos) { - ERR_FAIL_COND_V(!data, ERR_FILE_EOF) + ERR_FAIL_COND_V(!data, ERR_FILE_EOF); ERR_FAIL_COND_V(p_pos >= length, ERR_FILE_EOF); P = data + p_pos; @@ -486,9 +486,7 @@ Error XMLParser::open(const String &p_path) { Error err; FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &err); - if (err) { - ERR_FAIL_COND_V(err != OK, err); - } + ERR_FAIL_COND_V(err != OK, err); length = file->get_len(); ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT); diff --git a/core/list.h b/core/list.h index 103a82a31d..d1b528562d 100644 --- a/core/list.h +++ b/core/list.h @@ -602,9 +602,6 @@ public: Element *next = current->next_ptr; - //disconnect - current->next_ptr = NULL; - if (from != current) { current->prev_ptr = NULL; diff --git a/core/make_binders.py b/core/make_binders.py index 5c1c66cab6..24901c42a1 100644 --- a/core/make_binders.py +++ b/core/make_binders.py @@ -191,6 +191,96 @@ MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$ """ +template_typed_free_func = """ +#ifdef TYPED_METHOD_BIND +template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> +class FunctionBind$argc$$ifret R$$ifconst C$ : public MethodBind { +public: + + $ifret R$ $ifnoret void$ (*method) ($ifconst const$ T *$ifargs , $$arg, P@$); +#ifdef DEBUG_METHODS_ENABLED + virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$ + $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA; + $ + return GodotTypeInfo::METADATA_NONE; + } + Variant::Type _get_argument_type(int p_argument) const { + $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$ + $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE; + $ + return Variant::NIL; + } + virtual PropertyInfo _gen_argument_type_info(int p_argument) const { + $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$ + $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info(); + $ + return PropertyInfo(); + } +#endif + virtual String get_instance_class() const { + return T::get_class_static(); + } + + virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Variant::CallError& r_error) { + + T *instance=Object::cast_to<T>(p_object); + r_error.error=Variant::CallError::CALL_OK; +#ifdef DEBUG_METHODS_ENABLED + + ERR_FAIL_COND_V(!instance,Variant()); + if (p_arg_count>get_argument_count()) { + r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument=get_argument_count(); + return Variant(); + + } + if (p_arg_count<(get_argument_count()-get_default_argument_count())) { + + r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument=get_argument_count()-get_default_argument_count(); + return Variant(); + } + $arg CHECK_ARG(@); + $ +#endif + $ifret Variant ret = $(method)(instance$ifargs , $$arg, _VC(@)$); + $ifret return Variant(ret);$ + $ifnoret return Variant();$ + } + +#ifdef PTRCALL_ENABLED + virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) { + + T *instance=Object::cast_to<T>(p_object); + $ifret PtrToArg<R>::encode( $ (method)(instance$ifargs , $$arg, PtrToArg<P@>::convert(p_args[@-1])$) $ifret ,r_ret)$ ; + } +#endif + FunctionBind$argc$$ifret R$$ifconst C$ () { +#ifdef DEBUG_METHODS_ENABLED + _set_const($ifconst true$$ifnoconst false$); + _generate_argument_types($argc$); +#else + set_argument_count($argc$); +#endif + + $ifret _set_returns(true); $ + }; +}; + +template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> +MethodBind* create_method_bind($ifret R$ $ifnoret void$ (*p_method)($ifconst const$ T *$ifargs , $$arg, P@$) ) { + + FunctionBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$> * a = memnew( (FunctionBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$>) ); + a->method=p_method; + return a; +} +#endif +""" + + + def make_version(template, nargs, argmax, const, ret): intext = template @@ -259,6 +349,9 @@ def run(target, source, env): versions_ext = 6 text = "" text_ext = "" + text_free_func = "#ifndef METHOD_BIND_FREE_FUNC_H\n#define METHOD_BIND_FREE_FUNC_H\n" + text_free_func += "\n//including this header file allows method binding to use free functions\n" + text_free_func += "//note that the free function must have a pointer to an instance of the class as its first parameter\n" for i in range(0, versions + 1): @@ -276,12 +369,22 @@ def run(target, source, env): else: text += t + text_free_func += make_version(template_typed_free_func, i, versions, False, False) + text_free_func += make_version(template_typed_free_func, i, versions, False, True) + text_free_func += make_version(template_typed_free_func, i, versions, True, False) + text_free_func += make_version(template_typed_free_func, i, versions, True, True) + + text_free_func += "#endif" + with open(target[0], "w") as f: f.write(text) with open(target[1], "w") as f: f.write(text_ext) + with open(target[2], "w") as f: + f.write(text_free_func) + if __name__ == '__main__': from platform_methods import subprocess_main diff --git a/core/math/SCsub b/core/math/SCsub index 1c5f954470..0995298a4b 100644 --- a/core/math/SCsub +++ b/core/math/SCsub @@ -2,4 +2,37 @@ Import('env') -env.add_source_files(env.core_sources, "*.cpp") +env_math = env.Clone() # Maybe make one specific for crypto? + +is_builtin = env["builtin_mbedtls"] +has_module = env["module_mbedtls_enabled"] + +if is_builtin or not has_module: + # Use our headers for builtin or if the module is not going to be compiled. + # We decided not to depend on system mbedtls just for these few files that can + # be easily extracted. + env_math.Prepend(CPPPATH=["#thirdparty/mbedtls/include"]) + +# MbedTLS core functions (for CryptoCore). +# If the mbedtls module is compiled we don't need to add the .c files with our +# custom config since they will be built by the module itself. +# Only if the module is not enabled, we must compile here the required sources +# to make a "light" build with only the necessary mbedtls files. +if not has_module: + env_thirdparty = env_math.Clone() + env_thirdparty.disable_warnings() + # Custom config file + env_thirdparty.Append(CPPDEFINES=[('MBEDTLS_CONFIG_FILE', '\\"thirdparty/mbedtls/include/godot_core_mbedtls_config.h\\"')]) + thirdparty_mbedtls_dir = "#thirdparty/mbedtls/library/" + thirdparty_mbedtls_sources = [ + "aes.c", + "base64.c", + "md5.c", + "sha1.c", + "sha256.c", + "godot_core_mbedtls_platform.c" + ] + thirdparty_mbedtls_sources = [thirdparty_mbedtls_dir + file for file in thirdparty_mbedtls_sources] + env_thirdparty.add_source_files(env.core_sources, thirdparty_mbedtls_sources) + +env_math.add_source_files(env.core_sources, "*.cpp") diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 3d71e66f80..b61119d8df 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -99,14 +99,22 @@ void AStar::remove_point(int p_id) { Point *p = points[p_id]; - Map<int, Point *>::Element *PE = points.front(); - while (PE) { - for (Set<Point *>::Element *E = PE->get()->neighbours.front(); E; E = E->next()) { - Segment s(p_id, E->get()->id); - segments.erase(s); - E->get()->neighbours.erase(p); - } - PE = PE->next(); + for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) { + + Segment s(p_id, E->get()->id); + segments.erase(s); + + E->get()->neighbours.erase(p); + E->get()->unlinked_neighbours.erase(p); + } + + for (Set<Point *>::Element *E = p->unlinked_neighbours.front(); E; E = E->next()) { + + Segment s(p_id, E->get()->id); + segments.erase(s); + + E->get()->neighbours.erase(p); + E->get()->unlinked_neighbours.erase(p); } memdelete(p); @@ -125,6 +133,8 @@ void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) { if (bidirectional) b->neighbours.insert(a); + else + b->unlinked_neighbours.insert(a); Segment s(p_id, p_with_id); if (s.from == p_id) { @@ -147,7 +157,9 @@ void AStar::disconnect_points(int p_id, int p_with_id) { Point *a = points[p_id]; Point *b = points[p_with_id]; a->neighbours.erase(b); + a->unlinked_neighbours.erase(b); b->neighbours.erase(a); + b->unlinked_neighbours.erase(a); } bool AStar::has_point(int p_id) const { @@ -204,6 +216,8 @@ int AStar::get_closest_point(const Vector3 &p_point) const { for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) { + if (!E->get()->enabled) + continue; //Disabled points should not be considered real_t d = p_point.distance_squared_to(E->get()->pos); if (closest_id < 0 || d < closest_dist) { closest_dist = d; @@ -222,6 +236,10 @@ Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const { for (const Set<Segment>::Element *E = segments.front(); E; E = E->next()) { + if (!(E->get().from_point->enabled && E->get().to_point->enabled)) { + continue; + } + Vector3 segment[2] = { E->get().from_point->pos, E->get().to_point->pos, @@ -423,10 +441,16 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { } void AStar::set_point_disabled(int p_id, bool p_disabled) { + + ERR_FAIL_COND(!points.has(p_id)); + points[p_id]->enabled = !p_disabled; } bool AStar::is_point_disabled(int p_id) const { + + ERR_FAIL_COND_V(!points.has(p_id), false); + return !points[p_id]->enabled; } @@ -440,13 +464,12 @@ void AStar::_bind_methods() { ClassDB::bind_method(D_METHOD("set_point_weight_scale", "id", "weight_scale"), &AStar::set_point_weight_scale); ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar::remove_point); ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar::has_point); + ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar::get_point_connections); ClassDB::bind_method(D_METHOD("get_points"), &AStar::get_points); ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar::set_point_disabled, DEFVAL(true)); ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar::is_point_disabled); - ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar::get_point_connections); - ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar::connect_points, DEFVAL(true)); ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id"), &AStar::disconnect_points); ClassDB::bind_method(D_METHOD("are_points_connected", "id", "to_id"), &AStar::are_points_connected); @@ -473,3 +496,135 @@ AStar::~AStar() { pass = 1; clear(); } + +///////////////////////////////////////////////////////////// + +int AStar2D::get_available_point_id() const { + return astar.get_available_point_id(); +} + +void AStar2D::add_point(int p_id, const Vector2 &p_pos, real_t p_weight_scale) { + astar.add_point(p_id, Vector3(p_pos.x, p_pos.y, 0), p_weight_scale); +} + +Vector2 AStar2D::get_point_position(int p_id) const { + Vector3 p = astar.get_point_position(p_id); + return Vector2(p.x, p.y); +} + +void AStar2D::set_point_position(int p_id, const Vector2 &p_pos) { + astar.set_point_position(p_id, Vector3(p_pos.x, p_pos.y, 0)); +} + +real_t AStar2D::get_point_weight_scale(int p_id) const { + return astar.get_point_weight_scale(p_id); +} + +void AStar2D::set_point_weight_scale(int p_id, real_t p_weight_scale) { + astar.set_point_weight_scale(p_id, p_weight_scale); +} + +void AStar2D::remove_point(int p_id) { + astar.remove_point(p_id); +} + +bool AStar2D::has_point(int p_id) const { + return astar.has_point(p_id); +} + +PoolVector<int> AStar2D::get_point_connections(int p_id) { + return astar.get_point_connections(p_id); +} + +Array AStar2D::get_points() { + return astar.get_points(); +} + +void AStar2D::set_point_disabled(int p_id, bool p_disabled) { + astar.set_point_disabled(p_id, p_disabled); +} + +bool AStar2D::is_point_disabled(int p_id) const { + return astar.is_point_disabled(p_id); +} + +void AStar2D::connect_points(int p_id, int p_with_id, bool p_bidirectional) { + astar.connect_points(p_id, p_with_id, p_bidirectional); +} + +void AStar2D::disconnect_points(int p_id, int p_with_id) { + astar.disconnect_points(p_id, p_with_id); +} + +bool AStar2D::are_points_connected(int p_id, int p_with_id) const { + return astar.are_points_connected(p_id, p_with_id); +} + +void AStar2D::clear() { + astar.clear(); +} + +int AStar2D::get_closest_point(const Vector2 &p_point) const { + return astar.get_closest_point(Vector3(p_point.x, p_point.y, 0)); +} + +Vector2 AStar2D::get_closest_position_in_segment(const Vector2 &p_point) const { + Vector3 p = astar.get_closest_position_in_segment(Vector3(p_point.x, p_point.y, 0)); + return Vector2(p.x, p.y); +} + +PoolVector<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); + int size = pv.size(); + PoolVector2Array path; + path.resize(size); + { + PoolVector<Vector3>::Read r = pv.read(); + PoolVector<Vector2>::Write w = path.write(); + for (int i = 0; i < size; i++) { + Vector3 p = r[i]; + w[i] = Vector2(p.x, p.y); + } + } + return path; +} + +PoolVector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) { + return astar.get_id_path(p_from_id, p_to_id); +} + +void AStar2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_available_point_id"), &AStar2D::get_available_point_id); + ClassDB::bind_method(D_METHOD("add_point", "id", "position", "weight_scale"), &AStar2D::add_point, DEFVAL(1.0)); + ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStar2D::get_point_position); + ClassDB::bind_method(D_METHOD("set_point_position", "id", "position"), &AStar2D::set_point_position); + ClassDB::bind_method(D_METHOD("get_point_weight_scale", "id"), &AStar2D::get_point_weight_scale); + ClassDB::bind_method(D_METHOD("set_point_weight_scale", "id", "weight_scale"), &AStar2D::set_point_weight_scale); + ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar2D::remove_point); + ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar2D::has_point); + ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar2D::get_point_connections); + ClassDB::bind_method(D_METHOD("get_points"), &AStar2D::get_points); + + ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar2D::set_point_disabled, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar2D::is_point_disabled); + + ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar2D::connect_points, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id"), &AStar2D::disconnect_points); + ClassDB::bind_method(D_METHOD("are_points_connected", "id", "to_id"), &AStar2D::are_points_connected); + + ClassDB::bind_method(D_METHOD("clear"), &AStar2D::clear); + + ClassDB::bind_method(D_METHOD("get_closest_point", "to_position"), &AStar2D::get_closest_point); + ClassDB::bind_method(D_METHOD("get_closest_position_in_segment", "to_position"), &AStar2D::get_closest_position_in_segment); + + ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar2D::get_point_path); + ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStar2D::get_id_path); +} + +AStar2D::AStar2D() { +} + +AStar2D::~AStar2D() { +} diff --git a/core/math/a_star.h b/core/math/a_star.h index fac8a9d312..ec333efc1d 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -42,7 +42,7 @@ class AStar : public Reference { - GDCLASS(AStar, Reference) + GDCLASS(AStar, Reference); uint64_t pass; @@ -54,6 +54,7 @@ class AStar : public Reference { bool enabled; Set<Point *> neighbours; + Set<Point *> unlinked_neighbours; // Used for pathfinding Point *prev_point; @@ -142,4 +143,43 @@ public: ~AStar(); }; +class AStar2D : public Reference { + GDCLASS(AStar2D, Reference); + AStar astar; + +protected: + static void _bind_methods(); + +public: + int get_available_point_id() const; + + void add_point(int p_id, const Vector2 &p_pos, real_t p_weight_scale = 1); + Vector2 get_point_position(int p_id) const; + void set_point_position(int p_id, const Vector2 &p_pos); + real_t get_point_weight_scale(int p_id) const; + 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); + Array get_points(); + + void set_point_disabled(int p_id, bool p_disabled = true); + bool is_point_disabled(int p_id) const; + + void connect_points(int p_id, int p_with_id, bool p_bidirectional = true); + void disconnect_points(int p_id, int p_with_id); + bool are_points_connected(int p_id, int p_with_id) const; + + void clear(); + + int get_closest_point(const Vector2 &p_point) 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); + + AStar2D(); + ~AStar2D(); +}; + #endif // ASTAR_H diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 1540bc8fe1..400f342018 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -852,7 +852,7 @@ void Basis::set_quat_scale(const Quat &p_quat, const Vector3 &p_scale) { rotate(p_quat); } -void Basis::set_diagonal(const Vector3 p_diag) { +void Basis::set_diagonal(const Vector3 &p_diag) { elements[0][0] = p_diag.x; elements[0][1] = 0; elements[0][2] = 0; diff --git a/core/math/basis.h b/core/math/basis.h index 75037c2c52..d3adad3d90 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -153,7 +153,7 @@ public: int get_orthogonal_index() const; void set_orthogonal_index(int p_index); - void set_diagonal(const Vector3 p_diag); + void set_diagonal(const Vector3 &p_diag); bool is_orthogonal() const; bool is_diagonal() const; diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp index d7e6e82cd9..a12f9fee2e 100644 --- a/core/math/bsp_tree.cpp +++ b/core/math/bsp_tree.cpp @@ -142,7 +142,7 @@ int BSP_Tree::_get_points_inside(int p_node, const Vector3 *p_points, int *p_ind } return _get_points_inside(node->over, p_points, p_indices, p_center, p_half_extents, p_indices_count); - } else if (dist_min <= 0) { //all points behind plane + } else { //all points behind plane if (node->under == UNDER_LEAF) { @@ -150,8 +150,6 @@ int BSP_Tree::_get_points_inside(int p_node, const Vector3 *p_points, int *p_ind } return _get_points_inside(node->under, p_points, p_indices, p_center, p_half_extents, p_indices_count); } - - return 0; } int BSP_Tree::get_points_inside(const Vector3 *p_points, int p_point_count) const { @@ -271,8 +269,6 @@ bool BSP_Tree::point_is_inside(const Vector3 &p_point) const { ERR_FAIL_COND_V(idx < MAX_NODES && idx >= node_count, false); #endif } - - return false; } static int _bsp_find_best_half_plane(const Face3 *p_faces, const Vector<int> &p_indices, real_t p_tolerance) { diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index f615cc8c65..8b3b6c82f3 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -507,21 +507,21 @@ void CameraMatrix::set_light_bias() { real_t *m = &matrix[0][0]; - m[0] = 0.5, - m[1] = 0.0, - m[2] = 0.0, - m[3] = 0.0, - m[4] = 0.0, - m[5] = 0.5, - 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.5, - m[13] = 0.5, - m[14] = 0.5, + m[0] = 0.5; + m[1] = 0.0; + m[2] = 0.0; + m[3] = 0.0; + m[4] = 0.0; + m[5] = 0.5; + 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.5; + m[13] = 0.5; + m[14] = 0.5; m[15] = 1.0; } @@ -529,21 +529,21 @@ void CameraMatrix::set_light_atlas_rect(const Rect2 &p_rect) { real_t *m = &matrix[0][0]; - m[0] = p_rect.size.width, - m[1] = 0.0, - m[2] = 0.0, - m[3] = 0.0, - m[4] = 0.0, - m[5] = p_rect.size.height, - m[6] = 0.0, - m[7] = 0.0, - m[8] = 0.0, - m[9] = 0.0, - m[10] = 1.0, - m[11] = 0.0, - m[12] = p_rect.position.x, - m[13] = p_rect.position.y, - m[14] = 0.0, + m[0] = p_rect.size.width; + m[1] = 0.0; + m[2] = 0.0; + m[3] = 0.0; + m[4] = 0.0; + m[5] = p_rect.size.height; + m[6] = 0.0; + m[7] = 0.0; + m[8] = 0.0; + m[9] = 0.0; + m[10] = 1.0; + m[11] = 0.0; + m[12] = p_rect.position.x; + m[13] = p_rect.position.y; + m[14] = 0.0; m[15] = 1.0; } diff --git a/core/math/crypto_core.cpp b/core/math/crypto_core.cpp new file mode 100644 index 0000000000..d7ba54e469 --- /dev/null +++ b/core/math/crypto_core.cpp @@ -0,0 +1,157 @@ +/*************************************************************************/ +/* crypto_core.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 "crypto_core.h" + +#include <mbedtls/aes.h> +#include <mbedtls/base64.h> +#include <mbedtls/md5.h> +#include <mbedtls/sha1.h> +#include <mbedtls/sha256.h> + +// MD5 +CryptoCore::MD5Context::MD5Context() { + ctx = memalloc(sizeof(mbedtls_md5_context)); + mbedtls_md5_init((mbedtls_md5_context *)ctx); +} + +CryptoCore::MD5Context::~MD5Context() { + mbedtls_md5_free((mbedtls_md5_context *)ctx); + memfree((mbedtls_md5_context *)ctx); +} + +Error CryptoCore::MD5Context::start() { + int ret = mbedtls_md5_starts_ret((mbedtls_md5_context *)ctx); + return ret ? FAILED : OK; +} + +Error CryptoCore::MD5Context::update(uint8_t *p_src, size_t p_len) { + int ret = mbedtls_md5_update_ret((mbedtls_md5_context *)ctx, p_src, p_len); + return ret ? FAILED : OK; +} + +Error CryptoCore::MD5Context::finish(unsigned char r_hash[16]) { + int ret = mbedtls_md5_finish_ret((mbedtls_md5_context *)ctx, r_hash); + return ret ? FAILED : OK; +} + +// SHA256 +CryptoCore::SHA256Context::SHA256Context() { + ctx = memalloc(sizeof(mbedtls_sha256_context)); + mbedtls_sha256_init((mbedtls_sha256_context *)ctx); +} + +CryptoCore::SHA256Context::~SHA256Context() { + mbedtls_sha256_free((mbedtls_sha256_context *)ctx); + memfree((mbedtls_sha256_context *)ctx); +} + +Error CryptoCore::SHA256Context::start() { + int ret = mbedtls_sha256_starts_ret((mbedtls_sha256_context *)ctx, 0); + return ret ? FAILED : OK; +} + +Error CryptoCore::SHA256Context::update(uint8_t *p_src, size_t p_len) { + int ret = mbedtls_sha256_update_ret((mbedtls_sha256_context *)ctx, p_src, p_len); + return ret ? FAILED : OK; +} + +Error CryptoCore::SHA256Context::finish(unsigned char r_hash[16]) { + int ret = mbedtls_sha256_finish_ret((mbedtls_sha256_context *)ctx, r_hash); + return ret ? FAILED : OK; +} + +// AES256 +CryptoCore::AESContext::AESContext() { + ctx = memalloc(sizeof(mbedtls_aes_context)); + mbedtls_aes_init((mbedtls_aes_context *)ctx); +} + +CryptoCore::AESContext::~AESContext() { + mbedtls_aes_free((mbedtls_aes_context *)ctx); + memfree((mbedtls_aes_context *)ctx); +} + +Error CryptoCore::AESContext::set_encode_key(const uint8_t *p_key, size_t p_bits) { + int ret = mbedtls_aes_setkey_enc((mbedtls_aes_context *)ctx, p_key, p_bits); + return ret ? FAILED : OK; +} + +Error CryptoCore::AESContext::set_decode_key(const uint8_t *p_key, size_t p_bits) { + int ret = mbedtls_aes_setkey_dec((mbedtls_aes_context *)ctx, p_key, p_bits); + return ret ? FAILED : OK; +} + +Error CryptoCore::AESContext::encrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]) { + int ret = mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, MBEDTLS_AES_ENCRYPT, p_src, r_dst); + return ret ? FAILED : OK; +} + +Error CryptoCore::AESContext::decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]) { + int ret = mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_src, r_dst); + return ret ? FAILED : OK; +} + +// 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; + b64buff.resize(b64len); + PoolVector<uint8_t>::Write w64 = b64buff.write(); + size_t strlen = 0; + int ret = b64_encode(&w64[0], b64len, &strlen, p_src, p_src_len); + w64[strlen] = 0; + return ret ? String() : (const char *)&w64[0]; +} + +Error CryptoCore::b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len) { + int ret = mbedtls_base64_encode(r_dst, p_dst_len, r_len, p_src, p_src_len); + return ret ? FAILED : OK; +} + +Error CryptoCore::b64_decode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len) { + int ret = mbedtls_base64_decode(r_dst, p_dst_len, r_len, p_src, p_src_len); + return ret ? FAILED : OK; +} + +Error CryptoCore::md5(const uint8_t *p_src, int p_src_len, unsigned char r_hash[16]) { + int ret = mbedtls_md5_ret(p_src, p_src_len, r_hash); + return ret ? FAILED : OK; +} + +Error CryptoCore::sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]) { + int ret = mbedtls_sha1_ret(p_src, p_src_len, r_hash); + return ret ? FAILED : OK; +} + +Error CryptoCore::sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]) { + int ret = mbedtls_sha256_ret(p_src, p_src_len, r_hash, 0); + return ret ? FAILED : OK; +} diff --git a/core/math/crypto_core.h b/core/math/crypto_core.h new file mode 100644 index 0000000000..e28cb5a792 --- /dev/null +++ b/core/math/crypto_core.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* crypto_core.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 CRYPTO_CORE_H +#define CRYPTO_CORE_H + +#include "core/reference.h" + +class CryptoCore { + +public: + class MD5Context { + + private: + void *ctx; // To include, or not to include... + + public: + MD5Context(); + ~MD5Context(); + + Error start(); + Error update(uint8_t *p_src, size_t p_len); + Error finish(unsigned char r_hash[16]); + }; + + class SHA256Context { + + private: + void *ctx; // To include, or not to include... + + public: + SHA256Context(); + ~SHA256Context(); + + Error start(); + Error update(uint8_t *p_src, size_t p_len); + Error finish(unsigned char r_hash[16]); + }; + + class AESContext { + + private: + void *ctx; // To include, or not to include... + + public: + AESContext(); + ~AESContext(); + + Error set_encode_key(const uint8_t *p_key, size_t p_bits); + Error set_decode_key(const uint8_t *p_key, size_t p_bits); + Error encrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]); + Error decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]); + }; + + static String b64_encode_str(const uint8_t *p_src, int p_src_len); + static Error b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len); + static Error b64_decode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len); + + static Error md5(const uint8_t *p_src, int p_src_len, unsigned char r_hash[16]); + static Error sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]); + static Error sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]); +}; +#endif // CRYPTO_CORE_H diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 079c9b524f..2786229cf3 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -52,6 +52,7 @@ const char *Expression::func_name[Expression::FUNC_MAX] = { "sqrt", "fmod", "fposmod", + "posmod", "floor", "ceil", "round", @@ -70,6 +71,7 @@ const char *Expression::func_name[Expression::FUNC_MAX] = { "inverse_lerp", "range_lerp", "smoothstep", + "move_toward", "dectime", "randomize", "randi", @@ -174,6 +176,7 @@ int Expression::get_func_argument_count(BuiltinFunc p_func) { case MATH_ATAN2: case MATH_FMOD: case MATH_FPOSMOD: + case MATH_POSMOD: case MATH_POW: case MATH_EASE: case MATH_STEPIFY: @@ -189,6 +192,7 @@ int Expression::get_func_argument_count(BuiltinFunc p_func) { case MATH_LERP: case MATH_INVERSE_LERP: case MATH_SMOOTHSTEP: + case MATH_MOVE_TOWARD: case MATH_DECTIME: case MATH_WRAP: case MATH_WRAPF: @@ -281,6 +285,12 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant VALIDATE_ARG_NUM(1); *r_return = Math::fposmod((double)*p_inputs[0], (double)*p_inputs[1]); } break; + case MATH_POSMOD: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return = Math::posmod((int)*p_inputs[0], (int)*p_inputs[1]); + } break; case MATH_FLOOR: { VALIDATE_ARG_NUM(0); @@ -407,6 +417,13 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant VALIDATE_ARG_NUM(2); *r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; + case MATH_MOVE_TOWARD: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); + } break; case MATH_DECTIME: { VALIDATE_ARG_NUM(0); @@ -1785,7 +1802,7 @@ Expression::ENode *Expression::_parse_expression() { if (next_op == -1) { _set_error("Yet another parser bug...."); - ERR_FAIL_COND_V(next_op == -1, NULL); + ERR_FAIL_V(NULL); } // OK! create operator.. diff --git a/core/math/expression.h b/core/math/expression.h index f20619f0b6..03a2bb70e6 100644 --- a/core/math/expression.h +++ b/core/math/expression.h @@ -34,7 +34,8 @@ #include "core/reference.h" class Expression : public Reference { - GDCLASS(Expression, Reference) + GDCLASS(Expression, Reference); + public: enum BuiltinFunc { MATH_SIN, @@ -50,6 +51,7 @@ public: MATH_SQRT, MATH_FMOD, MATH_FPOSMOD, + MATH_POSMOD, MATH_FLOOR, MATH_CEIL, MATH_ROUND, @@ -68,6 +70,7 @@ public: MATH_INVERSE_LERP, MATH_RANGE_LERP, MATH_SMOOTHSTEP, + MATH_MOVE_TOWARD, MATH_DECTIME, MATH_RANDOMIZE, MATH_RAND, diff --git a/core/math/geometry.h b/core/math/geometry.h index 0e144e491f..e4f3ff799e 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -455,16 +455,15 @@ public: Vector3 p = p_point - p_segment[0]; Vector3 n = p_segment[1] - p_segment[0]; - real_t l = n.length(); - if (l < 1e-10) + real_t l2 = n.length_squared(); + if (l2 < 1e-20) return p_segment[0]; // both points are the same, just give any - n /= l; - real_t d = n.dot(p); + real_t d = n.dot(p) / l2; if (d <= 0.0) return p_segment[0]; // before first point - else if (d >= l) + else if (d >= 1.0) return p_segment[1]; // after first point else return p_segment[0] + n * d; // inside @@ -474,12 +473,11 @@ public: Vector3 p = p_point - p_segment[0]; Vector3 n = p_segment[1] - p_segment[0]; - real_t l = n.length(); - if (l < 1e-10) + real_t l2 = n.length_squared(); + if (l2 < 1e-20) return p_segment[0]; // both points are the same, just give any - n /= l; - real_t d = n.dot(p); + real_t d = n.dot(p) / l2; return p_segment[0] + n * d; // inside } @@ -488,16 +486,15 @@ public: Vector2 p = p_point - p_segment[0]; Vector2 n = p_segment[1] - p_segment[0]; - real_t l = n.length(); - if (l < 1e-10) + real_t l2 = n.length_squared(); + if (l2 < 1e-20) return p_segment[0]; // both points are the same, just give any - n /= l; - real_t d = n.dot(p); + real_t d = n.dot(p) / l2; if (d <= 0.0) return p_segment[0]; // before first point - else if (d >= l) + else if (d >= 1.0) return p_segment[1]; // after first point else return p_segment[0] + n * d; // inside @@ -521,12 +518,11 @@ public: Vector2 p = p_point - p_segment[0]; Vector2 n = p_segment[1] - p_segment[0]; - real_t l = n.length(); - if (l < 1e-10) + real_t l2 = n.length_squared(); + if (l2 < 1e-20) return p_segment[0]; // both points are the same, just give any - n /= l; - real_t d = n.dot(p); + real_t d = n.dot(p) / l2; return p_segment[0] + n * d; // inside } diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 5b5fd8e283..7a2e74a413 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -161,8 +161,6 @@ uint32_t Math::larger_prime(uint32_t p_val) { return primes[idx]; idx++; } - - return 0; } double Math::random(double from, double to) { diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 82b5b56c01..b6398712e4 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -198,6 +198,13 @@ public: value += 0.0; return value; } + static _ALWAYS_INLINE_ int posmod(int p_x, int p_y) { + int value = p_x % p_y; + if ((value < 0 && p_y > 0) || (value > 0 && p_y < 0)) { + value += p_y; + } + return value; + } static _ALWAYS_INLINE_ double deg2rad(double p_y) { return p_y * Math_PI / 180.0; } static _ALWAYS_INLINE_ float deg2rad(float p_y) { return p_y * Math_PI / 180.0; } @@ -224,6 +231,8 @@ public: float x = CLAMP((p_weight - p_from) / (p_to - p_from), 0.0f, 1.0f); return x * x * (3.0f - 2.0f * x); } + static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; } + static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; } static _ALWAYS_INLINE_ double linear2db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; } static _ALWAYS_INLINE_ float linear2db(float p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; } diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp index 6add00c1d8..54a88d5cd8 100644 --- a/core/math/random_number_generator.cpp +++ b/core/math/random_number_generator.cpp @@ -30,8 +30,7 @@ #include "random_number_generator.h" -RandomNumberGenerator::RandomNumberGenerator() : - randbase() {} +RandomNumberGenerator::RandomNumberGenerator() {} void RandomNumberGenerator::_bind_methods() { ClassDB::bind_method(D_METHOD("set_seed", "seed"), &RandomNumberGenerator::set_seed); diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h index 6b6bcdd2cd..9b54ea9b2e 100644 --- a/core/math/random_number_generator.h +++ b/core/math/random_number_generator.h @@ -47,7 +47,7 @@ public: _FORCE_INLINE_ uint64_t get_seed() { return randbase.get_seed(); } - _FORCE_INLINE_ void randomize() { return randbase.randomize(); } + _FORCE_INLINE_ void randomize() { randbase.randomize(); } _FORCE_INLINE_ uint32_t randi() { return randbase.rand(); } @@ -59,7 +59,10 @@ public: _FORCE_INLINE_ int randi_range(int from, int to) { unsigned int ret = randbase.rand(); - return ret % (to - from + 1) + from; + if (to < from) + return ret % (from - to + 1) + to; + else + return ret % (to - from + 1) + from; } RandomNumberGenerator(); diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp index 8351bd138e..00c0af515d 100644 --- a/core/math/random_pcg.cpp +++ b/core/math/random_pcg.cpp @@ -43,13 +43,9 @@ void RandomPCG::randomize() { } double RandomPCG::random(double p_from, double p_to) { - unsigned int r = rand(); - double ret = (double)r / (double)RANDOM_MAX; - return (ret) * (p_to - p_from) + p_from; + return randd() * (p_to - p_from) + p_from; } float RandomPCG::random(float p_from, float p_to) { - unsigned int r = rand(); - float ret = (float)r / (float)RANDOM_MAX; - return (ret) * (p_to - p_from) + p_from; + return randf() * (p_to - p_from) + p_from; } diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index 0d1b311c0d..aa25914638 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -37,6 +37,28 @@ #include "thirdparty/misc/pcg.h" +#if defined(__GNUC__) || (_llvm_has_builtin(__builtin_clz)) +#define CLZ32(x) __builtin_clz(x) +#elif defined(_MSC_VER) +#include "intrin.h" +static int __bsr_clz32(uint32_t x) { + unsigned long index; + _BitScanReverse(&index, x); + return 31 - index; +} +#define CLZ32(x) __bsr_clz32(x) +#else +#endif + +#if defined(__GNUC__) || (_llvm_has_builtin(__builtin_ldexp) && _llvm_has_builtin(__builtin_ldexpf)) +#define LDEXP(s, e) __builtin_ldexp(s, e) +#define LDEXPF(s, e) __builtin_ldexpf(s, e) +#else +#include "math.h" +#define LDEXP(s, e) ldexp(s, e) +#define LDEXPF(s, e) ldexp(s, e) +#endif + class RandomPCG { pcg32_random_t pcg; uint64_t current_seed; // seed with this to get the same state @@ -60,8 +82,44 @@ public: current_seed = pcg.state; return pcg32_random_r(&pcg); } - _FORCE_INLINE_ double randd() { return (double)rand() / (double)RANDOM_MAX; } - _FORCE_INLINE_ float randf() { return (float)rand() / (float)RANDOM_MAX; } + + // Obtaining floating point numbers in [0, 1] range with "good enough" uniformity. + // These functions sample the output of rand() as the fraction part of an infinite binary number, + // with some tricks applied to reduce ops and branching: + // 1. Instead of shifting to the first 1 and connecting random bits, we simply set the MSB and LSB to 1. + // Provided that the RNG is actually uniform bit by bit, this should have the exact same effect. + // 2. In order to compensate for exponent info loss, we count zeros from another random number, + // and just add that to the initial offset. + // This has the same probability as counting and shifting an actual bit stream: 2^-n for n zeroes. + // For all numbers above 2^-96 (2^-64 for floats), the functions should be uniform. + // However, all numbers below that threshold are floored to 0. + // The thresholds are chosen to minimize rand() calls while keeping the numbers within a totally subjective quality standard. + // If clz or ldexp isn't available, fall back to bit truncation for performance, sacrificing uniformity. + _FORCE_INLINE_ double randd() { +#if defined(CLZ32) + uint32_t proto_exp_offset = rand(); + if (unlikely(proto_exp_offset == 0)) { + return 0; + } + uint64_t significand = (((uint64_t)rand()) << 32) | rand() | 0x8000000000000001U; + return LDEXP((double)significand, -64 - CLZ32(proto_exp_offset)); +#else +#pragma message("RandomPCG::randd - intrinsic clz is not available, falling back to bit truncation") + return (double)(((((uint64_t)rand()) << 32) | rand()) & 0x1FFFFFFFFFFFFFU) / (double)0x1FFFFFFFFFFFFFU; +#endif + } + _FORCE_INLINE_ float randf() { +#if defined(CLZ32) + uint32_t proto_exp_offset = rand(); + if (unlikely(proto_exp_offset == 0)) { + return 0; + } + return LDEXPF((float)(rand() | 0x80000001), -32 - CLZ32(proto_exp_offset)); +#else +#pragma message("RandomPCG::randf - intrinsic clz is not available, falling back to bit truncation") + return (float)(rand() & 0xFFFFFF) / (float)0xFFFFFF; +#endif + } _FORCE_INLINE_ double randfn(double p_mean, double p_deviation) { return p_mean + p_deviation * (cos(Math_TAU * randd()) * sqrt(-2.0 * log(randd()))); // Box-Muller transform diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index 83784a1fa7..546981be44 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -182,7 +182,7 @@ void TriangleMesh::create(const PoolVector<Vector3> &p_faces) { int max_alloc = fc; _create_bvh(bw.ptr(), bwp.ptr(), 0, fc, 1, max_depth, max_alloc); - bw = PoolVector<BVH>::Write(); //clearup + bw.release(); //clearup bvh.resize(max_alloc); //resize back valid = true; @@ -751,7 +751,7 @@ PoolVector<Face3> TriangleMesh::get_faces() const { } } - w = PoolVector<Face3>::Write(); + w.release(); return faces; } diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h index ee7bf0f6b5..8b01080852 100644 --- a/core/math/triangle_mesh.h +++ b/core/math/triangle_mesh.h @@ -97,7 +97,7 @@ public: PoolVector<Triangle> get_triangles() const { return triangles; } PoolVector<Vector3> get_vertices() const { return vertices; } - void get_indices(PoolVector<int> *p_triangles_indices) const; + void get_indices(PoolVector<int> *r_triangles_indices) const; void create(const PoolVector<Vector3> &p_faces); TriangleMesh(); diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 5c1ea5943d..779a28be66 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -164,6 +164,13 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c return out; } +Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const { + Vector2 v = *this; + Vector2 vd = p_to - v; + real_t len = vd.length(); + return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta; +} + // slide returns the component of the vector along the given plane, specified by its normal vector. Vector2 Vector2::slide(const Vector2 &p_normal) const { #ifdef MATH_CHECKS diff --git a/core/math/vector2.h b/core/math/vector2.h index a0c6024c9f..78a1641c1e 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -79,6 +79,7 @@ struct Vector2 { _FORCE_INLINE_ Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const; _FORCE_INLINE_ Vector2 slerp(const Vector2 &p_b, real_t p_t) const; Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const; + Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const; Vector2 slide(const Vector2 &p_normal) const; Vector2 bounce(const Vector2 &p_normal) const; diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 1c28934422..73927821cf 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -127,6 +127,13 @@ Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, c return out; } +Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const { + Vector3 v = *this; + Vector3 vd = p_to - v; + real_t len = vd.length(); + return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta; +} + Vector3::operator String() const { return (rtos(x) + ", " + rtos(y) + ", " + rtos(z)); diff --git a/core/math/vector3.h b/core/math/vector3.h index 21fc09653f..45bdfee487 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -94,6 +94,7 @@ struct Vector3 { _FORCE_INLINE_ Vector3 slerp(const Vector3 &p_b, real_t p_t) const; Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const; Vector3 cubic_interpolaten(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const; + Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const; _FORCE_INLINE_ Vector3 cross(const Vector3 &p_b) const; _FORCE_INLINE_ real_t dot(const Vector3 &p_b) const; @@ -218,12 +219,8 @@ Vector3 Vector3::linear_interpolate(const Vector3 &p_b, real_t p_t) const { } Vector3 Vector3::slerp(const Vector3 &p_b, real_t p_t) const { -#ifdef MATH_CHECKS - ERR_FAIL_COND_V(!is_normalized(), Vector3()); -#endif - real_t theta = angle_to(p_b); - return rotated(cross(p_b), theta * p_t); + return rotated(cross(p_b).normalized(), theta * p_t); } real_t Vector3::distance_to(const Vector3 &p_b) const { diff --git a/core/node_path.cpp b/core/node_path.cpp index 07ff765516..a4b7cbe2eb 100644 --- a/core/node_path.cpp +++ b/core/node_path.cpp @@ -357,7 +357,7 @@ NodePath::NodePath(const String &p_path) { String path = p_path; Vector<StringName> subpath; - int absolute = (path[0] == '/') ? 1 : 0; + bool absolute = (path[0] == '/'); bool last_is_slash = true; bool has_slashes = false; int slices = 0; @@ -387,7 +387,7 @@ NodePath::NodePath(const String &p_path) { path = path.substr(0, subpath_pos); } - for (int i = absolute; i < path.length(); i++) { + for (int i = (int)absolute; i < path.length(); i++) { if (path[i] == '/') { @@ -407,7 +407,7 @@ NodePath::NodePath(const String &p_path) { data = memnew(Data); data->refcount.init(); - data->absolute = absolute ? true : false; + data->absolute = absolute; data->has_slashes = has_slashes; data->subpath = subpath; data->hash_cache_valid = false; @@ -416,10 +416,10 @@ NodePath::NodePath(const String &p_path) { return; data->path.resize(slices); last_is_slash = true; - int from = absolute; + int from = (int)absolute; int slice = 0; - for (int i = absolute; i < path.length() + 1; i++) { + for (int i = (int)absolute; i < path.length() + 1; i++) { if (path[i] == '/' || path[i] == 0) { diff --git a/core/object.cpp b/core/object.cpp index 64f55f08a9..67ab27c190 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -474,7 +474,6 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid if (r_valid) *r_valid = false; - return; } Variant Object::get(const StringName &p_name, bool *r_valid) const { @@ -636,9 +635,12 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons #endif p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT)); } - if (!metadata.empty()) { - p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - } + +#ifdef TOOLS_ENABLED + p_list->push_back(PropertyInfo(Variant::NIL, "Metadata", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); +#endif + p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT)); + if (script_instance && !p_reversed) { p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); script_instance->get_property_list(p_list); @@ -743,13 +745,11 @@ void Object::call_multilevel(const StringName &p_method, const Variant **p_args, if (Object::cast_to<Reference>(this)) { ERR_EXPLAIN("Can't 'free' a reference."); ERR_FAIL(); - return; } if (_lock_index.get() > 1) { ERR_EXPLAIN("Object is locked and can't be freed."); ERR_FAIL(); - return; } #endif @@ -810,11 +810,7 @@ bool Object::has_method(const StringName &p_method) const { MethodBind *method = ClassDB::get_method(get_class_name(), p_method); - if (method) { - return true; - } - - return false; + return method != NULL; } Variant Object::getvar(const Variant &p_key, bool *r_valid) const { @@ -1472,7 +1468,7 @@ Error Object::connect(const StringName &p_signal, Object *p_to_object, const Str if (!signal_is_valid) { ERR_EXPLAIN("In Object of type '" + String(get_class()) + "': Attempt to connect nonexistent signal '" + p_signal + "' to method '" + p_to_object->get_class() + "." + p_to_method + "'"); - ERR_FAIL_COND_V(!signal_is_valid, ERR_INVALID_PARAMETER); + ERR_FAIL_V(ERR_INVALID_PARAMETER); } signal_map[p_signal] = Signal(); s = &signal_map[p_signal]; @@ -1485,7 +1481,7 @@ Error Object::connect(const StringName &p_signal, Object *p_to_object, const Str return OK; } else { ERR_EXPLAIN("Signal '" + p_signal + "' is already connected to given method '" + p_to_method + "' in that object."); - ERR_FAIL_COND_V(s->slot_map.has(target), ERR_INVALID_PARAMETER); + ERR_FAIL_V(ERR_INVALID_PARAMETER); } } @@ -1522,7 +1518,7 @@ bool Object::is_connected(const StringName &p_signal, Object *p_to_object, const return false; ERR_EXPLAIN("Nonexistent signal: " + p_signal); - ERR_FAIL_COND_V(!s, false); + ERR_FAIL_V(false); } Signal::Target target(p_to_object->get_instance_id(), p_to_method); @@ -1542,11 +1538,11 @@ void Object::_disconnect(const StringName &p_signal, Object *p_to_object, const Signal *s = signal_map.getptr(p_signal); if (!s) { ERR_EXPLAIN("Nonexistent signal: " + p_signal); - ERR_FAIL_COND(!s); + ERR_FAIL(); } if (s->lock > 0) { ERR_EXPLAIN("Attempt to disconnect signal '" + p_signal + "' while emitting (locks: " + itos(s->lock) + ")"); - ERR_FAIL_COND(s->lock > 0); + ERR_FAIL(); } Signal::Target target(p_to_object->get_instance_id(), p_to_method); @@ -1689,7 +1685,7 @@ void Object::clear_internal_resource_paths() { void Object::_bind_methods() { ClassDB::bind_method(D_METHOD("get_class"), &Object::get_class); - ClassDB::bind_method(D_METHOD("is_class", "type"), &Object::is_class); + ClassDB::bind_method(D_METHOD("is_class", "class"), &Object::is_class); ClassDB::bind_method(D_METHOD("set", "property", "value"), &Object::_set_bind); ClassDB::bind_method(D_METHOD("get", "property"), &Object::_get_bind); ClassDB::bind_method(D_METHOD("set_indexed", "property", "value"), &Object::_set_indexed_bind); @@ -1709,14 +1705,8 @@ void Object::_bind_methods() { ClassDB::bind_method(D_METHOD("has_meta", "name"), &Object::has_meta); ClassDB::bind_method(D_METHOD("get_meta_list"), &Object::_get_meta_list_bind); - //todo reimplement this per language so all 5 arguments can be called - - //ClassDB::bind_method(D_METHOD("call","method","arg1","arg2","arg3","arg4"),&Object::_call_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant())); - //ClassDB::bind_method(D_METHOD("call_deferred","method","arg1","arg2","arg3","arg4"),&Object::_call_deferred_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("add_user_signal", "signal", "arguments"), &Object::_add_user_signal, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("has_user_signal", "signal"), &Object::_has_user_signal); - //ClassDB::bind_method(D_METHOD("emit_signal","signal","arguments"),&Object::_emit_signal,DEFVAL(Array())); { MethodInfo mi; diff --git a/core/object.h b/core/object.h index 4394c1c3da..1e0b22c086 100644 --- a/core/object.h +++ b/core/object.h @@ -130,6 +130,7 @@ enum PropertyUsageFlags { #define ADD_SIGNAL(m_signal) ClassDB::add_signal(get_class_static(), m_signal) #define ADD_PROPERTY(m_property, m_setter, m_getter) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter)) #define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index) +#define ADD_PROPERTY_DEFAULT(m_property, m_default) ClassDB::set_property_default_value(get_class_static(), m_property, m_default) #define ADD_GROUP(m_name, m_prefix) ClassDB::add_property_group(get_class_static(), m_name, m_prefix) struct PropertyInfo { diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index d81c30f33a..0cdb5b41b7 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -43,8 +43,6 @@ String DirAccess::_get_root_path() const { case ACCESS_USERDATA: return OS::get_singleton()->get_user_data_dir(); default: return ""; } - - return ""; } String DirAccess::_get_root_string() const { @@ -54,8 +52,6 @@ String DirAccess::_get_root_string() const { case ACCESS_USERDATA: return "user://"; default: return ""; } - - return ""; } int DirAccess::get_current_drive() { @@ -373,12 +369,12 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag if (current_is_dir()) dirs.push_back(n); else { - String rel_path = n; + const String &rel_path = n; if (!n.is_rel_path()) { list_dir_end(); return ERR_BUG; } - Error err = copy(get_current_dir() + "/" + n, p_to + rel_path, p_chmod_flags); + Error err = copy(get_current_dir().plus_file(n), p_to + rel_path, p_chmod_flags); if (err) { list_dir_end(); return err; diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 079f51bada..7509050b2b 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -32,12 +32,10 @@ #include "core/io/file_access_pack.h" #include "core/io/marshalls.h" +#include "core/math/crypto_core.h" #include "core/os/os.h" #include "core/project_settings.h" -#include "thirdparty/misc/md5.h" -#include "thirdparty/misc/sha256.h" - FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = { 0, 0 }; FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = NULL; @@ -600,9 +598,9 @@ Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_err if (!f) { if (r_error) { // if error requested, do not throw error return Vector<uint8_t>(); - } else { - ERR_FAIL_COND_V(!f, Vector<uint8_t>()); } + ERR_EXPLAIN("Can't open file from path: " + String(p_path)); + ERR_FAIL_V(Vector<uint8_t>()); } Vector<uint8_t> data; data.resize(f->get_len()); @@ -621,9 +619,9 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) { if (err != OK) { if (r_error) { return String(); - } else { - ERR_FAIL_COND_V(err != OK, String()); } + ERR_EXPLAIN("Can't get file as string from path: " + String(p_path)); + ERR_FAIL_V(String()); } String ret; @@ -637,8 +635,8 @@ String FileAccess::get_md5(const String &p_file) { if (!f) return String(); - MD5_CTX md5; - MD5Init(&md5); + CryptoCore::MD5Context ctx; + ctx.start(); unsigned char step[32768]; @@ -647,24 +645,24 @@ String FileAccess::get_md5(const String &p_file) { int br = f->get_buffer(step, 32768); if (br > 0) { - MD5Update(&md5, step, br); + ctx.update(step, br); } if (br < 4096) break; } - MD5Final(&md5); - - String ret = String::md5(md5.digest); + unsigned char hash[16]; + ctx.finish(hash); memdelete(f); - return ret; + + return String::md5(hash); } String FileAccess::get_multiple_md5(const Vector<String> &p_file) { - MD5_CTX md5; - MD5Init(&md5); + CryptoCore::MD5Context ctx; + ctx.start(); for (int i = 0; i < p_file.size(); i++) { FileAccess *f = FileAccess::open(p_file[i], READ); @@ -677,7 +675,7 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) { int br = f->get_buffer(step, 32768); if (br > 0) { - MD5Update(&md5, step, br); + ctx.update(step, br); } if (br < 4096) break; @@ -685,11 +683,10 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) { memdelete(f); } - MD5Final(&md5); - - String ret = String::md5(md5.digest); + unsigned char hash[16]; + ctx.finish(hash); - return ret; + return String::md5(hash); } String FileAccess::get_sha256(const String &p_file) { @@ -698,8 +695,8 @@ String FileAccess::get_sha256(const String &p_file) { if (!f) return String(); - sha256_context sha256; - sha256_init(&sha256); + CryptoCore::SHA256Context ctx; + ctx.start(); unsigned char step[32768]; @@ -708,15 +705,14 @@ String FileAccess::get_sha256(const String &p_file) { int br = f->get_buffer(step, 32768); if (br > 0) { - sha256_hash(&sha256, step, br); + ctx.update(step, br); } if (br < 4096) break; } unsigned char hash[32]; - - sha256_done(&sha256, hash); + ctx.finish(hash); memdelete(f); return String::hex_encode_buffer(hash, 32); diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index a072017353..a40a50cfce 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -314,7 +314,7 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed if (p_pressed != NULL) *p_pressed = key->is_pressed(); if (p_strength != NULL) - *p_strength = (*p_pressed) ? 1.0f : 0.0f; + *p_strength = (p_pressed != NULL && *p_pressed) ? 1.0f : 0.0f; } return match; } @@ -483,7 +483,7 @@ bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p if (p_pressed != NULL) *p_pressed = mb->is_pressed(); if (p_strength != NULL) - *p_strength = (*p_pressed) ? 1.0f : 0.0f; + *p_strength = (p_pressed != NULL && *p_pressed) ? 1.0f : 0.0f; } return match; @@ -795,7 +795,7 @@ bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool * if (p_pressed != NULL) *p_pressed = jb->is_pressed(); if (p_strength != NULL) - *p_strength = (*p_pressed) ? 1.0f : 0.0f; + *p_strength = (p_pressed != NULL && *p_pressed) ? 1.0f : 0.0f; } return match; @@ -1010,6 +1010,14 @@ bool InputEventAction::is_pressed() const { return pressed; } +void InputEventAction::set_strength(float p_strength) { + strength = CLAMP(p_strength, 0.0f, 1.0f); +} + +float InputEventAction::get_strength() const { + return strength; +} + bool InputEventAction::shortcut_match(const Ref<InputEvent> &p_event) const { if (p_event.is_null()) return false; @@ -1033,7 +1041,7 @@ bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pres if (p_pressed != NULL) *p_pressed = act->pressed; if (p_strength != NULL) - *p_strength = (*p_pressed) ? 1.0f : 0.0f; + *p_strength = (p_pressed != NULL && *p_pressed) ? 1.0f : 0.0f; } return match; } @@ -1051,14 +1059,19 @@ void InputEventAction::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventAction::set_pressed); //ClassDB::bind_method(D_METHOD("is_pressed"), &InputEventAction::is_pressed); + ClassDB::bind_method(D_METHOD("set_strength", "strength"), &InputEventAction::set_strength); + ClassDB::bind_method(D_METHOD("get_strength"), &InputEventAction::get_strength); + // ClassDB::bind_method(D_METHOD("is_action", "name"), &InputEventAction::is_action); ADD_PROPERTY(PropertyInfo(Variant::STRING, "action"), "set_action", "get_action"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_strength", "get_strength"); } InputEventAction::InputEventAction() { pressed = false; + strength = 1.0f; } ///////////////////////////// diff --git a/core/os/input_event.h b/core/os/input_event.h index ba01516519..4f5762e756 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -117,6 +117,16 @@ enum JoystickList { JOY_WII_MINUS = JOY_BUTTON_10, JOY_WII_PLUS = JOY_BUTTON_11, + JOY_VR_GRIP = JOY_BUTTON_2, + JOY_VR_PAD = JOY_BUTTON_14, + JOY_VR_TRIGGER = JOY_BUTTON_15, + + JOY_OCULUS_AX = JOY_BUTTON_7, + JOY_OCULUS_BY = JOY_BUTTON_1, + JOY_OCULUS_MENU = JOY_BUTTON_3, + + JOY_OPENVR_MENU = JOY_BUTTON_1, + // end of history JOY_AXIS_0 = 0, @@ -139,6 +149,12 @@ enum JoystickList { JOY_ANALOG_L2 = JOY_AXIS_6, JOY_ANALOG_R2 = JOY_AXIS_7, + + JOY_VR_ANALOG_TRIGGER = JOY_AXIS_2, + JOY_VR_ANALOG_GRIP = JOY_AXIS_4, + + JOY_OPENVR_TOUCHPADX = JOY_AXIS_0, + JOY_OPENVR_TOUCHPADY = JOY_AXIS_1, }; enum MidiMessageList { @@ -157,7 +173,7 @@ enum MidiMessageList { */ class InputEvent : public Resource { - GDCLASS(InputEvent, Resource) + GDCLASS(InputEvent, Resource); int device; @@ -194,7 +210,7 @@ public: }; class InputEventWithModifiers : public InputEvent { - GDCLASS(InputEventWithModifiers, InputEvent) + GDCLASS(InputEventWithModifiers, InputEvent); bool shift; bool alt; @@ -240,7 +256,7 @@ public: class InputEventKey : public InputEventWithModifiers { - GDCLASS(InputEventKey, InputEventWithModifiers) + GDCLASS(InputEventKey, InputEventWithModifiers); bool pressed; /// otherwise release @@ -279,7 +295,7 @@ public: class InputEventMouse : public InputEventWithModifiers { - GDCLASS(InputEventMouse, InputEventWithModifiers) + GDCLASS(InputEventMouse, InputEventWithModifiers); int button_mask; @@ -304,7 +320,7 @@ public: class InputEventMouseButton : public InputEventMouse { - GDCLASS(InputEventMouseButton, InputEventMouse) + GDCLASS(InputEventMouseButton, InputEventMouse); float factor; int button_index; @@ -338,7 +354,7 @@ public: class InputEventMouseMotion : public InputEventMouse { - GDCLASS(InputEventMouseMotion, InputEventMouse) + GDCLASS(InputEventMouseMotion, InputEventMouse); Vector2 relative; Vector2 speed; @@ -362,7 +378,7 @@ public: class InputEventJoypadMotion : public InputEvent { - GDCLASS(InputEventJoypadMotion, InputEvent) + GDCLASS(InputEventJoypadMotion, InputEvent); int axis; ///< Joypad axis float axis_value; ///< -1 to 1 @@ -387,7 +403,7 @@ public: }; class InputEventJoypadButton : public InputEvent { - GDCLASS(InputEventJoypadButton, InputEvent) + GDCLASS(InputEventJoypadButton, InputEvent); int button_index; bool pressed; @@ -415,7 +431,7 @@ public: }; class InputEventScreenTouch : public InputEvent { - GDCLASS(InputEventScreenTouch, InputEvent) + GDCLASS(InputEventScreenTouch, InputEvent); int index; Vector2 pos; bool pressed; @@ -441,7 +457,7 @@ public: class InputEventScreenDrag : public InputEvent { - GDCLASS(InputEventScreenDrag, InputEvent) + GDCLASS(InputEventScreenDrag, InputEvent); int index; Vector2 pos; Vector2 relative; @@ -471,10 +487,11 @@ public: class InputEventAction : public InputEvent { - GDCLASS(InputEventAction, InputEvent) + GDCLASS(InputEventAction, InputEvent); StringName action; bool pressed; + float strength; protected: static void _bind_methods(); @@ -486,6 +503,9 @@ public: void set_pressed(bool p_pressed); virtual bool is_pressed() const; + void set_strength(float p_strength); + float get_strength() const; + virtual bool is_action(const StringName &p_action) const; virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const; @@ -499,7 +519,7 @@ public: class InputEventGesture : public InputEventWithModifiers { - GDCLASS(InputEventGesture, InputEventWithModifiers) + GDCLASS(InputEventGesture, InputEventWithModifiers); Vector2 pos; @@ -513,7 +533,7 @@ public: class InputEventMagnifyGesture : public InputEventGesture { - GDCLASS(InputEventMagnifyGesture, InputEventGesture) + GDCLASS(InputEventMagnifyGesture, InputEventGesture); real_t factor; protected: @@ -531,7 +551,7 @@ public: class InputEventPanGesture : public InputEventGesture { - GDCLASS(InputEventPanGesture, InputEventGesture) + GDCLASS(InputEventPanGesture, InputEventGesture); Vector2 delta; protected: @@ -548,7 +568,7 @@ public: }; class InputEventMIDI : public InputEvent { - GDCLASS(InputEventMIDI, InputEvent) + GDCLASS(InputEventMIDI, InputEvent); int channel; int message; diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index 895ce14ae9..9946ced2f3 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -44,9 +44,9 @@ void MainLoop::_bind_methods() { BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); BIND_VMETHOD(MethodInfo("_input_text", PropertyInfo(Variant::STRING, "text"))); BIND_VMETHOD(MethodInfo("_initialize")); - BIND_VMETHOD(MethodInfo("_iteration", PropertyInfo(Variant::REAL, "delta"))); - BIND_VMETHOD(MethodInfo("_idle", PropertyInfo(Variant::REAL, "delta"))); - BIND_VMETHOD(MethodInfo("_drop_files", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen"))); + 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("_finalize")); BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER); diff --git a/core/os/memory.h b/core/os/memory.h index f3ca9fc614..e073b11e76 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -66,7 +66,7 @@ public: class DefaultAllocator { public: _FORCE_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory, false); } - _FORCE_INLINE_ static void free(void *p_ptr) { return Memory::free_static(p_ptr, false); } + _FORCE_INLINE_ static void free(void *p_ptr) { Memory::free_static(p_ptr, false); } }; void *operator new(size_t p_size, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool diff --git a/core/os/os.cpp b/core/os/os.cpp index 1a3c9ac5f8..925154af7d 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -51,6 +51,35 @@ uint32_t OS::get_ticks_msec() const { return get_ticks_usec() / 1000; } +String OS::get_iso_date_time(bool local) const { + OS::Date date = get_date(local); + OS::Time time = get_time(local); + + String timezone; + if (!local) { + TimeZoneInfo zone = get_time_zone_info(); + if (zone.bias >= 0) { + timezone = "+"; + } + timezone = timezone + itos(zone.bias / 60).pad_zeros(2) + itos(zone.bias % 60).pad_zeros(2); + } else { + timezone = "Z"; + } + + return itos(date.year).pad_zeros(2) + + "-" + + itos(date.month).pad_zeros(2) + + "-" + + itos(date.day).pad_zeros(2) + + "T" + + itos(time.hour).pad_zeros(2) + + ":" + + itos(time.min).pad_zeros(2) + + ":" + + itos(time.sec).pad_zeros(2) + + timezone; +} + uint64_t OS::get_splash_tick_msec() const { return _msec_splash; } @@ -239,7 +268,8 @@ void OS::print_all_resources(String p_to_file) { _OSPRF = FileAccess::open(p_to_file, FileAccess::WRITE, &err); if (err != OK) { _OSPRF = NULL; - ERR_FAIL_COND(err != OK); + ERR_EXPLAIN("Can't print all resources to file: " + String(p_to_file)); + ERR_FAIL(); } } @@ -759,6 +789,8 @@ OS::OS() { } OS::~OS() { + if (last_error) + memfree(last_error); memdelete(_logger); singleton = NULL; } diff --git a/core/os/os.h b/core/os/os.h index 4f6a539e78..2224d3b006 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -104,7 +104,6 @@ public: bool maximized; bool always_on_top; bool use_vsync; - bool layered_splash; bool layered; float get_aspect() const { return (float)width / (float)height; } VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false) { @@ -117,7 +116,6 @@ public: always_on_top = p_always_on_top; use_vsync = p_use_vsync; layered = false; - layered_splash = false; } }; @@ -207,8 +205,12 @@ public: virtual int get_screen_dpi(int p_screen = -1) const { return 72; } virtual Point2 get_window_position() const { return Vector2(); } virtual void set_window_position(const Point2 &p_position) {} + virtual Size2 get_max_window_size() const { return Size2(); }; + virtual Size2 get_min_window_size() const { return Size2(); }; virtual Size2 get_window_size() const = 0; virtual Size2 get_real_window_size() const { return get_window_size(); } + virtual void set_min_window_size(const Size2 p_size) {} + virtual void set_max_window_size(const Size2 p_size) {} virtual void set_window_size(const Size2 p_size) {} virtual void set_window_fullscreen(bool p_enabled) {} virtual bool is_window_fullscreen() const { return true; } @@ -220,6 +222,8 @@ public: virtual bool is_window_maximized() const { return true; } virtual void set_window_always_on_top(bool p_enabled) {} virtual bool is_window_always_on_top() const { return false; } + virtual void set_console_visible(bool p_enabled) {} + virtual bool is_console_visible() const { return false; } virtual void request_attention() {} virtual void center_window(); @@ -332,6 +336,7 @@ public: virtual Date get_date(bool local = false) const = 0; virtual Time get_time(bool local = false) const = 0; virtual TimeZoneInfo get_time_zone_info() const = 0; + virtual String get_iso_date_time(bool local = false) const; virtual uint64_t get_unix_time() const; virtual uint64_t get_system_time_secs() const; virtual uint64_t get_system_time_msecs() const; diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp index fa60be64a7..54bf12b314 100644 --- a/core/packed_data_container.cpp +++ b/core/packed_data_container.cpp @@ -224,7 +224,8 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd string_cache[s] = tmpdata.size(); - }; //fallthrough + FALLTHROUGH; + }; case Variant::NIL: case Variant::BOOL: case Variant::INT: diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp index a283d8db1d..094352b5cc 100644 --- a/core/pool_allocator.cpp +++ b/core/pool_allocator.cpp @@ -206,8 +206,8 @@ PoolAllocator::ID PoolAllocator::alloc(int p_size) { if (!find_hole(&new_entry_indices_pos, size_to_alloc)) { mt_unlock(); - ERR_PRINT("memory can't be compacted further"); - return POOL_ALLOCATOR_INVALID_ID; + ERR_EXPLAIN("Memory can't be compacted further"); + ERR_FAIL_V(POOL_ALLOCATOR_INVALID_ID); } } @@ -217,7 +217,8 @@ PoolAllocator::ID PoolAllocator::alloc(int p_size) { if (!found_free_entry) { mt_unlock(); - ERR_FAIL_COND_V(!found_free_entry, POOL_ALLOCATOR_INVALID_ID); + ERR_EXPLAIN("No free entry found in PoolAllocator"); + ERR_FAIL_V(POOL_ALLOCATOR_INVALID_ID); } /* move all entry indices up, make room for this one */ @@ -500,9 +501,7 @@ void *PoolAllocator::get(ID p_mem) { if (!needs_locking) { Entry *e = get_entry(p_mem); - if (!e) { - ERR_FAIL_COND_V(!e, NULL); - }; + ERR_FAIL_COND_V(!e, NULL); return &pool[e->pos]; } diff --git a/core/pool_vector.h b/core/pool_vector.h index 102a620f17..98a52c6938 100644 --- a/core/pool_vector.h +++ b/core/pool_vector.h @@ -301,6 +301,10 @@ public: virtual ~Access() { _unref(); } + + void release() { + _unref(); + } }; class Read : public Access { @@ -411,8 +415,8 @@ public: p_to = size() + p_to; } - CRASH_BAD_INDEX(p_from, size()); - CRASH_BAD_INDEX(p_to, size()); + 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; @@ -484,9 +488,7 @@ T PoolVector<T>::get(int p_index) const { template <class T> void PoolVector<T>::set(int p_index, const T &p_val) { - if (p_index < 0 || p_index >= size()) { - ERR_FAIL_COND(p_index < 0 || p_index >= size()); - } + ERR_FAIL_INDEX(p_index, size()); Write w = write(); w[p_index] = p_val; @@ -511,6 +513,8 @@ const T PoolVector<T>::operator[](int p_index) const { template <class T> Error PoolVector<T>::resize(int p_size) { + ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER); + if (alloc == NULL) { if (p_size == 0) diff --git a/core/print_string.cpp b/core/print_string.cpp index d91d49f53b..3271744af3 100644 --- a/core/print_string.cpp +++ b/core/print_string.cpp @@ -68,8 +68,8 @@ void remove_print_handler(PrintHandlerList *p_handler) { } //OS::get_singleton()->print("print handler list is %p\n",print_handler_list); - ERR_FAIL_COND(l == NULL); _global_unlock(); + ERR_FAIL_COND(l == NULL); } void print_line(String p_string) { diff --git a/core/project_settings.cpp b/core/project_settings.cpp index c86d1567dd..c1d4967f55 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -75,11 +75,23 @@ String ProjectSettings::localize_path(const String &p_path) const { memdelete(dir); - if (!cwd.begins_with(resource_path)) { + // Ensure that we end with a '/'. + // This is important to ensure that we do not wrongly localize the resource path + // in an absolute path that just happens to contain this string but points to a + // different folder (e.g. "/my/project" as resource_path would be contained in + // "/my/project_data", even though the latter is not part of res://. + // `plus_file("")` is an easy way to ensure we have a trailing '/'. + const String res_path = resource_path.plus_file(""); + + // DirAccess::get_current_dir() is not guaranteed to return a path that with a trailing '/', + // so we must make sure we have it as well in order to compare with 'res_path'. + cwd = cwd.plus_file(""); + + if (!cwd.begins_with(res_path)) { return p_path; }; - return cwd.replace_first(resource_path, "res:/"); + return cwd.replace_first(res_path, "res://"); } else { memdelete(dir); @@ -335,17 +347,17 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b return err; } - // Attempt with exec_name.pck - // (This is the usual case when distributing a Godot game.) - - // Based on the OS, it can be the exec path + '.pck' (Linux w/o extension, macOS in .app bundle) - // or the exec path's basename + '.pck' (Windows). - // We need to test both possibilities as extensions for Linux binaries are optional - // (so both 'mygame.bin' and 'mygame' should be able to find 'mygame.pck'). - String exec_path = OS::get_singleton()->get_executable_path(); if (exec_path != "") { + // Attempt with exec_name.pck + // (This is the usual case when distributing a Godot game.) + + // Based on the OS, it can be the exec path + '.pck' (Linux w/o extension, macOS in .app bundle) + // or the exec path's basename + '.pck' (Windows). + // We need to test both possibilities as extensions for Linux binaries are optional + // (so both 'mygame.bin' and 'mygame' should be able to find 'mygame.pck'). + bool found = false; String exec_dir = exec_path.get_base_dir(); @@ -367,6 +379,14 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b } } + // Attempt with PCK bundled into executable + + if (!found) { + if (_load_resource_pack(exec_path)) { + found = true; + } + } + // If we opened our package, try and load our project if (found) { Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); @@ -467,7 +487,7 @@ void ProjectSettings::set_registering_order(bool p_enable) { registering_order = p_enable; } -Error ProjectSettings::_load_settings_binary(const String p_path) { +Error ProjectSettings::_load_settings_binary(const String &p_path) { Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -481,7 +501,7 @@ Error ProjectSettings::_load_settings_binary(const String p_path) { memdelete(f); ERR_EXPLAIN("Corrupted header in binary project.binary (not ECFG)"); - ERR_FAIL_V(ERR_FILE_CORRUPT;) + ERR_FAIL_V(ERR_FILE_CORRUPT); } uint32_t count = f->get_32(); @@ -510,7 +530,7 @@ Error ProjectSettings::_load_settings_binary(const String p_path) { return OK; } -Error ProjectSettings::_load_settings_text(const String p_path) { +Error ProjectSettings::_load_settings_text(const String &p_path) { Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -558,7 +578,7 @@ Error ProjectSettings::_load_settings_text(const String p_path) { if (config_version > CONFIG_VERSION) { memdelete(f); ERR_EXPLAIN(vformat("Can't open project at '%s', its `config_version` (%d) is from a more recent and incompatible version of the engine. Expected config version: %d.", p_path, config_version, CONFIG_VERSION)); - ERR_FAIL_COND_V(config_version > CONFIG_VERSION, ERR_FILE_CANT_OPEN); + ERR_FAIL_V(ERR_FILE_CANT_OPEN); } } else { if (section == String()) { @@ -571,13 +591,9 @@ Error ProjectSettings::_load_settings_text(const String p_path) { section = next_tag.name; } } - - memdelete(f); - - return OK; } -Error ProjectSettings::_load_settings_text_or_binary(const String p_text_path, const String p_bin_path) { +Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path, const String &p_bin_path) { // Attempt first to load the text-based project.godot file Error err_text = _load_settings_text(p_text_path); @@ -632,7 +648,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str if (err != OK) { ERR_EXPLAIN("Couldn't save project.binary at " + p_file); - ERR_FAIL_COND_V(err, err) + ERR_FAIL_COND_V(err, err); } uint8_t hdr[4] = { 'E', 'C', 'F', 'G' }; @@ -724,7 +740,7 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin if (err) { ERR_EXPLAIN("Couldn't save project.godot - " + p_file); - ERR_FAIL_COND_V(err, err) + ERR_FAIL_COND_V(err, err); } file->store_line("; Engine configuration file."); @@ -859,8 +875,6 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust ERR_EXPLAIN("Unknown config file format: " + p_path); ERR_FAIL_V(ERR_FILE_UNRECOGNIZED); } - - return OK; } Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed) { @@ -1007,6 +1021,15 @@ 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(); + 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"); + action = Dictionary(); action["deadzone"] = Variant(0.5f); events = Array(); diff --git a/core/project_settings.h b/core/project_settings.h index 0ff18ab3f5..d7651417d5 100644 --- a/core/project_settings.h +++ b/core/project_settings.h @@ -97,9 +97,9 @@ protected: static ProjectSettings *singleton; - Error _load_settings_text(const String p_path); - Error _load_settings_binary(const String p_path); - Error _load_settings_text_or_binary(const String p_text_path, const String p_bin_path); + Error _load_settings_text(const String &p_path); + Error _load_settings_binary(const String &p_path); + Error _load_settings_text_or_binary(const String &p_text_path, const String &p_bin_path); Error _save_settings_text(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String()); Error _save_settings_binary(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String()); diff --git a/core/reference.cpp b/core/reference.cpp index 7b5145184a..1984af9a34 100644 --- a/core/reference.cpp +++ b/core/reference.cpp @@ -70,7 +70,7 @@ bool Reference::reference() { if (get_script_instance()) { get_script_instance()->refcount_incremented(); } - if (instance_binding_count > 0) { + if (instance_binding_count > 0 && !ScriptServer::are_languages_finished()) { for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) { if (_script_instance_bindings[i]) { ScriptServer::get_language(i)->refcount_incremented_instance_binding(this); @@ -91,7 +91,7 @@ bool Reference::unreference() { bool script_ret = get_script_instance()->refcount_decremented(); die = die && script_ret; } - if (instance_binding_count > 0) { + if (instance_binding_count > 0 && !ScriptServer::are_languages_finished()) { for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) { if (_script_instance_bindings[i]) { bool script_ret = ScriptServer::get_language(i)->refcount_decremented_instance_binding(this); diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 97c96b4018..e442546124 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -184,11 +184,14 @@ void register_core_types() { ClassDB::register_class<PackedDataContainer>(); ClassDB::register_virtual_class<PackedDataContainerRef>(); ClassDB::register_class<AStar>(); + ClassDB::register_class<AStar2D>(); ClassDB::register_class<EncodedObjectAsID>(); ClassDB::register_class<RandomNumberGenerator>(); ClassDB::register_class<JSONParseResult>(); + ClassDB::register_virtual_class<ResourceImporter>(); + ip = IP::create(); _geometry = memnew(_Geometry); @@ -204,6 +207,8 @@ void register_core_types() { void register_core_settings() { //since in register core types, globals may not e present + GLOBAL_DEF("network/limits/tcp/connect_timeout_seconds", (30)); + ProjectSettings::get_singleton()->set_custom_property_info("network/limits/tcp/connect_timeout_seconds", PropertyInfo(Variant::INT, "network/limits/tcp/connect_timeout_seconds", PROPERTY_HINT_RANGE, "1,1800,1")); GLOBAL_DEF_RST("network/limits/packet_peer_stream/max_buffer_po2", (16)); ProjectSettings::get_singleton()->set_custom_property_info("network/limits/packet_peer_stream/max_buffer_po2", PropertyInfo(Variant::INT, "network/limits/packet_peer_stream/max_buffer_po2", PROPERTY_HINT_RANGE, "0,64,1,or_greater")); } @@ -272,6 +277,7 @@ void unregister_core_types() { ResourceLoader::finalize(); + ClassDB::cleanup_defaults(); ObjectDB::cleanup(); unregister_variant_methods(); diff --git a/core/safe_refcount.h b/core/safe_refcount.h index f6b8f80271..54f540b0c7 100644 --- a/core/safe_refcount.h +++ b/core/safe_refcount.h @@ -189,11 +189,7 @@ public: _ALWAYS_INLINE_ bool unref() { // true if must be disposed of - if (atomic_decrement(&count) == 0) { - return true; - } - - return false; + return atomic_decrement(&count) == 0; } _ALWAYS_INLINE_ uint32_t get() const { // nothrow diff --git a/core/script_language.h b/core/script_language.h index b2dab666c4..87f103bb33 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -200,6 +200,35 @@ public: virtual ~ScriptInstance(); }; +struct ScriptCodeCompletionOption { + enum Kind { + KIND_CLASS, + KIND_FUNCTION, + KIND_SIGNAL, + KIND_VARIABLE, + KIND_MEMBER, + KIND_ENUM, + KIND_CONSTANT, + KIND_NODE_PATH, + KIND_FILE_PATH, + KIND_PLAIN_TEXT, + }; + Kind kind; + String display; + String insert_text; + RES icon; + + ScriptCodeCompletionOption() { + kind = KIND_PLAIN_TEXT; + } + + ScriptCodeCompletionOption(const String &p_text, Kind p_kind) { + display = p_text; + insert_text = p_text; + kind = p_kind; + } +}; + class ScriptCodeCompletionCache { static ScriptCodeCompletionCache *singleton; @@ -250,7 +279,7 @@ public: 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; } - virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; } + virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; } struct LookupResult { enum Type { @@ -269,7 +298,7 @@ public: int location; }; - virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result) { return ERR_UNAVAILABLE; } + virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) { return ERR_UNAVAILABLE; } virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const = 0; virtual void add_global_constant(const StringName &p_variable, const Variant &p_value) = 0; diff --git a/core/sort_array.h b/core/sort_array.h index 0f258aec3e..8660ee3333 100644 --- a/core/sort_array.h +++ b/core/sort_array.h @@ -179,14 +179,14 @@ public: while (true) { while (compare(p_array[p_first], p_pivot)) { if (Validate) { - ERR_BAD_COMPARE(p_first == unmodified_last - 1) + ERR_BAD_COMPARE(p_first == unmodified_last - 1); } p_first++; } p_last--; while (compare(p_pivot, p_array[p_last])) { if (Validate) { - ERR_BAD_COMPARE(p_last == unmodified_first) + ERR_BAD_COMPARE(p_last == unmodified_first); } p_last--; } @@ -259,7 +259,7 @@ public: int next = p_last - 1; while (compare(p_value, p_array[next])) { if (Validate) { - ERR_BAD_COMPARE(next == 0) + ERR_BAD_COMPARE(next == 0); } p_array[p_last] = p_array[next]; p_last = next; diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index f7ca6d3bde..f0c2b8eb9b 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -336,6 +336,7 @@ bool UndoRedo::redo() { _process_operation_list(actions.write[current_action].do_ops.front()); version++; + emit_signal("version_changed"); return true; } @@ -348,6 +349,8 @@ bool UndoRedo::undo() { _process_operation_list(actions.write[current_action].undo_ops.front()); current_action--; version--; + emit_signal("version_changed"); + return true; } @@ -359,18 +362,30 @@ void UndoRedo::clear_history(bool p_increase_version) { while (actions.size()) _pop_history_tail(); - if (p_increase_version) + if (p_increase_version) { version++; + emit_signal("version_changed"); + } } String UndoRedo::get_current_action_name() const { ERR_FAIL_COND_V(action_level > 0, ""); if (current_action < 0) - return ""; //nothing to redo + return ""; return actions[current_action].name; } +bool UndoRedo::has_undo() { + + return current_action >= 0; +} + +bool UndoRedo::has_redo() { + + return (current_action + 1) < actions.size(); +} + uint64_t UndoRedo::get_version() const { return version; @@ -523,10 +538,14 @@ void UndoRedo::_bind_methods() { ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference); ClassDB::bind_method(D_METHOD("clear_history", "increase_version"), &UndoRedo::clear_history, DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name); + ClassDB::bind_method(D_METHOD("has_undo"), &UndoRedo::has_undo); + ClassDB::bind_method(D_METHOD("has_redo"), &UndoRedo::has_redo); ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version); ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo); ClassDB::bind_method(D_METHOD("undo"), &UndoRedo::undo); + ADD_SIGNAL(MethodInfo("version_changed")); + BIND_ENUM_CONSTANT(MERGE_DISABLE); BIND_ENUM_CONSTANT(MERGE_ENDS); BIND_ENUM_CONSTANT(MERGE_ALL); diff --git a/core/undo_redo.h b/core/undo_redo.h index e2cc6c659b..276d00d9af 100644 --- a/core/undo_redo.h +++ b/core/undo_redo.h @@ -118,6 +118,9 @@ public: String get_current_action_name() const; void clear_history(bool p_increase_version = true); + bool has_undo(); + bool has_redo(); + uint64_t get_version() const; void set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud); diff --git a/core/ustring.cpp b/core/ustring.cpp index 78feddb229..75e3b6f22e 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -31,6 +31,7 @@ #include "ustring.h" #include "core/color.h" +#include "core/math/crypto_core.h" #include "core/math/math_funcs.h" #include "core/os/memory.h" #include "core/print_string.h" @@ -38,9 +39,6 @@ #include "core/ucaps.h" #include "core/variant.h" -#include "thirdparty/misc/md5.h" -#include "thirdparty/misc/sha256.h" - #include <wchar.h> #ifndef NO_USE_STDLIB @@ -481,8 +479,6 @@ signed char String::nocasecmp_to(const String &p_str) const { this_str++; that_str++; } - - return 0; //should never reach anyway } signed char String::casecmp_to(const String &p_str) const { @@ -513,8 +509,6 @@ signed char String::casecmp_to(const String &p_str) const { this_str++; that_str++; } - - return 0; //should never reach anyway } signed char String::naturalnocasecmp_to(const String &p_str) const { @@ -731,8 +725,6 @@ String String::get_slicec(CharType p_splitter, int p_slice) const { i++; } - - return String(); //no find! } Vector<String> String::split_spaces() const { @@ -786,7 +778,7 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p if (p_allow_empty || (end > from)) { if (p_maxsplit <= 0) ret.push_back(substr(from, end - from)); - else if (p_maxsplit > 0) { + else { // Put rest of the string and leave cycle. if (p_maxsplit == ret.size()) { @@ -1725,6 +1717,45 @@ int64_t String::hex_to_int64(bool p_with_prefix) const { return hex * sign; } +int64_t String::bin_to_int64(bool p_with_prefix) const { + + if (p_with_prefix && length() < 3) + return 0; + + const CharType *s = ptr(); + + int64_t sign = s[0] == '-' ? -1 : 1; + + if (sign < 0) { + s++; + } + + if (p_with_prefix) { + if (s[0] != '0' || s[1] != 'b') + return 0; + s += 2; + } + + int64_t binary = 0; + + while (*s) { + + CharType c = LOWERCASE(*s); + int64_t n; + if (c == '0' || c == '1') { + n = c - '0'; + } else { + return 0; + } + + binary *= 2; + binary += n; + s++; + } + + return binary * sign; +} + int String::to_int() const { if (length() == 0) @@ -2221,54 +2252,63 @@ uint64_t String::hash64() const { String String::md5_text() const { CharString cs = utf8(); - MD5_CTX ctx; - MD5Init(&ctx); - MD5Update(&ctx, (unsigned char *)cs.ptr(), cs.length()); - MD5Final(&ctx); - return String::md5(ctx.digest); + unsigned char hash[16]; + CryptoCore::md5((unsigned char *)cs.ptr(), cs.length(), hash); + return String::hex_encode_buffer(hash, 16); +} + +String String::sha1_text() const { + CharString cs = utf8(); + unsigned char hash[20]; + CryptoCore::sha1((unsigned char *)cs.ptr(), cs.length(), hash); + return String::hex_encode_buffer(hash, 20); } String String::sha256_text() const { CharString cs = utf8(); unsigned char hash[32]; - sha256_context ctx; - sha256_init(&ctx); - sha256_hash(&ctx, (unsigned char *)cs.ptr(), cs.length()); - sha256_done(&ctx, hash); + CryptoCore::sha256((unsigned char *)cs.ptr(), cs.length(), hash); return String::hex_encode_buffer(hash, 32); } Vector<uint8_t> String::md5_buffer() const { CharString cs = utf8(); - MD5_CTX ctx; - MD5Init(&ctx); - MD5Update(&ctx, (unsigned char *)cs.ptr(), cs.length()); - MD5Final(&ctx); + unsigned char hash[16]; + CryptoCore::md5((unsigned char *)cs.ptr(), cs.length(), hash); Vector<uint8_t> ret; ret.resize(16); for (int i = 0; i < 16; i++) { - ret.write[i] = ctx.digest[i]; - }; - + ret.write[i] = hash[i]; + } return ret; }; +Vector<uint8_t> String::sha1_buffer() const { + CharString cs = utf8(); + unsigned char hash[20]; + CryptoCore::sha1((unsigned char *)cs.ptr(), cs.length(), hash); + + Vector<uint8_t> ret; + ret.resize(20); + for (int i = 0; i < 20; i++) { + ret.write[i] = hash[i]; + } + + return ret; +} + Vector<uint8_t> String::sha256_buffer() const { CharString cs = utf8(); unsigned char hash[32]; - sha256_context ctx; - sha256_init(&ctx); - sha256_hash(&ctx, (unsigned char *)cs.ptr(), cs.length()); - sha256_done(&ctx, hash); + CryptoCore::sha256((unsigned char *)cs.ptr(), cs.length(), hash); Vector<uint8_t> ret; ret.resize(32); for (int i = 0; i < 32; i++) { ret.write[i] = hash[i]; } - return ret; } @@ -2292,6 +2332,9 @@ String String::insert(int p_at_pos, const String &p_string) const { } String String::substr(int p_from, int p_chars) const { + if (p_chars == -1) + p_chars = length() - p_from; + if (empty() || p_from < 0 || p_from >= length() || p_chars <= 0) return ""; @@ -2917,26 +2960,12 @@ String String::replace(const char *p_key, const char *p_with) const { String String::replace_first(const String &p_key, const String &p_with) const { - String new_string; - int search_from = 0; - int result = 0; - - while ((result = find(p_key, search_from)) >= 0) { - - new_string += substr(search_from, result - search_from); - new_string += p_with; - search_from = result + p_key.length(); - break; - } - - if (search_from == 0) { - - return *this; + int pos = find(p_key); + if (pos >= 0) { + return substr(0, pos) + p_with + substr(pos + p_key.length(), length()); } - new_string += substr(search_from, length() - search_from); - - return new_string; + return *this; } String String::replacen(const String &p_key, const String &p_with) const { @@ -3063,29 +3092,16 @@ String String::strip_edges(bool left, bool right) const { String String::strip_escapes() const { - int len = length(); - int beg = 0, end = len; - + String new_string; for (int i = 0; i < length(); i++) { - if (operator[](i) <= 31) - beg++; - else - break; - } - - for (int i = (int)(length() - 1); i >= 0; i--) { - - if (operator[](i) <= 31) - end--; - else - break; + // Escape characters on first page of the ASCII table, before 32 (Space). + if (operator[](i) < 32) + continue; + new_string += operator[](i); } - if (beg == 0 && end == len) - return *this; - - return substr(beg, end - beg); + return new_string; } String String::lstrip(const String &p_chars) const { @@ -3209,7 +3225,7 @@ static int _humanize_digits(int p_num) { String String::humanize_size(size_t p_size) { uint64_t _div = 1; - static const char *prefix[] = { " Bytes", " KB", " MB", " GB", "TB", " PB", "HB", "" }; + static const char *prefix[] = { " Bytes", " KB", " MB", " GB", " TB", " PB", " EB", "" }; int prefix_idx = 0; while (p_size > (_div * 1024) && prefix[prefix_idx][0]) { @@ -3220,7 +3236,7 @@ String String::humanize_size(size_t p_size) { int digits = prefix_idx > 0 ? _humanize_digits(p_size / _div) : 0; double divisor = prefix_idx > 0 ? _div : 1; - return String::num(p_size / divisor, digits) + prefix[prefix_idx]; + return String::num(p_size / divisor).pad_decimals(digits) + prefix[prefix_idx]; } bool String::is_abs_path() const { @@ -3322,7 +3338,7 @@ String String::http_unescape() const { if ((ord1 >= '0' && ord1 <= '9') || (ord1 >= 'A' && ord1 <= 'Z')) { CharType ord2 = ord_at(i + 2); if ((ord2 >= '0' && ord2 <= '9') || (ord2 >= 'A' && ord2 <= 'Z')) { - char bytes[2] = { (char)ord1, (char)ord2 }; + char bytes[3] = { (char)ord1, (char)ord2, 0 }; res += (char)strtol(bytes, NULL, 16); i += 2; } @@ -3784,11 +3800,7 @@ bool String::is_valid_filename() const { return false; } - if (find(":") != -1 || find("/") != -1 || find("\\") != -1 || find("?") != -1 || find("*") != -1 || find("\"") != -1 || find("|") != -1 || find("%") != -1 || find("<") != -1 || find(">") != -1) { - return false; - } else { - return true; - } + return !(find(":") != -1 || find("/") != -1 || find("\\") != -1 || find("?") != -1 || find("*") != -1 || find("\"") != -1 || find("|") != -1 || find("%") != -1 || find("<") != -1 || find(">") != -1); } bool String::is_valid_ip_address() const { @@ -3926,7 +3938,6 @@ String String::percent_decode() const { uint8_t a = LOWERCASE(cs[i + 1]); uint8_t b = LOWERCASE(cs[i + 2]); - c = 0; if (a >= '0' && a <= '9') c = (a - '0') << 4; else if (a >= 'a' && a <= 'f') diff --git a/core/ustring.h b/core/ustring.h index e2e62874d6..8a52c53238 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -201,7 +201,7 @@ public: } /* complex helpers */ - String substr(int p_from, int p_chars) const; + String substr(int p_from, int p_chars = -1) const; int find(const String &p_str, int p_from = 0) const; ///< return <0 if failed int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed int find_char(const CharType &p_char, int p_from = 0) const; ///< return <0 if failed @@ -251,6 +251,7 @@ public: int to_int() const; int64_t hex_to_int64(bool p_with_prefix = true) const; + int64_t bin_to_int64(bool p_with_prefix = true) const; int64_t to_int64() const; static int to_int(const char *p_str, int p_len = -1); static double to_double(const char *p_str); @@ -304,8 +305,10 @@ public: uint32_t hash() const; /* hash the string */ uint64_t hash64() const; /* hash the string */ String md5_text() const; + String sha1_text() const; String sha256_text() const; Vector<uint8_t> md5_buffer() const; + Vector<uint8_t> sha1_buffer() const; Vector<uint8_t> sha256_buffer() const; _FORCE_INLINE_ bool empty() const { return length() == 0; } @@ -403,8 +406,6 @@ _FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) { l_ptr++; r_ptr++; } - - CRASH_COND(true); // unreachable } /* end of namespace */ @@ -414,16 +415,16 @@ _FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) { //gets parsed String TTR(const String &); -//use for c strings -#define TTRC(m_value) m_value +//use for C strings +#define TTRC(m_value) (m_value) //use to avoid parsing (for use later with C strings) #define TTRGET(m_value) TTR(m_value) #else -#define TTR(m_val) (String()) -#define TTRCDEF(m_value) (m_value) +#define TTR(m_value) (String()) #define TTRC(m_value) (m_value) +#define TTRGET(m_value) (m_value) #endif diff --git a/core/variant.cpp b/core/variant.cpp index 6eadf59fce..fe9623d068 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -709,7 +709,7 @@ bool Variant::is_zero() const { // atomic types case BOOL: { - return _data._bool == false; + return !(_data._bool); } break; case INT: { @@ -1171,8 +1171,6 @@ Variant::operator signed int() const { return 0; } } - - return 0; } Variant::operator unsigned int() const { @@ -1188,8 +1186,6 @@ Variant::operator unsigned int() const { return 0; } } - - return 0; } Variant::operator int64_t() const { @@ -1206,8 +1202,6 @@ Variant::operator int64_t() const { return 0; } } - - return 0; } /* @@ -1244,8 +1238,6 @@ Variant::operator uint64_t() const { return 0; } } - - return 0; } #ifdef NEED_LONG_INT @@ -1300,8 +1292,6 @@ Variant::operator signed short() const { return 0; } } - - return 0; } Variant::operator unsigned short() const { @@ -1317,8 +1307,6 @@ Variant::operator unsigned short() const { return 0; } } - - return 0; } Variant::operator signed char() const { @@ -1334,8 +1322,6 @@ Variant::operator signed char() const { return 0; } } - - return 0; } Variant::operator unsigned char() const { @@ -1351,8 +1337,6 @@ Variant::operator unsigned char() const { return 0; } } - - return 0; } Variant::operator CharType() const { @@ -1374,8 +1358,6 @@ Variant::operator float() const { return 0; } } - - return 0; } Variant::operator double() const { @@ -1391,8 +1373,6 @@ Variant::operator double() const { return 0; } } - - return true; } Variant::operator StringName() const { @@ -2438,9 +2418,6 @@ Variant::Variant(const PoolVector<Face3> &p_face_array) { for (int j = 0; j < 3; j++) w[i * 3 + j] = r[i].vertex[j]; } - - r = PoolVector<Face3>::Read(); - w = PoolVector<Vector3>::Write(); } type = NIL; diff --git a/core/variant.h b/core/variant.h index 5151262f27..a8e99c13f1 100644 --- a/core/variant.h +++ b/core/variant.h @@ -248,8 +248,8 @@ public: Variant(unsigned short p_short); Variant(signed char p_char); // real one Variant(unsigned char p_char); - Variant(int64_t p_char); // real one - Variant(uint64_t p_char); + Variant(int64_t p_int); // real one + Variant(uint64_t p_int); Variant(float p_float); Variant(double p_double); Variant(const String &p_string); @@ -262,11 +262,11 @@ public: Variant(const Plane &p_plane); Variant(const ::AABB &p_aabb); Variant(const Quat &p_quat); - Variant(const Basis &p_transform); + Variant(const Basis &p_matrix); Variant(const Transform2D &p_transform); Variant(const Transform &p_transform); Variant(const Color &p_color); - Variant(const NodePath &p_path); + Variant(const NodePath &p_node_path); Variant(const RefPtr &p_resource); Variant(const RID &p_rid); Variant(const Object *p_object); @@ -283,17 +283,17 @@ public: Variant(const PoolVector<Face3> &p_face_array); Variant(const Vector<Variant> &p_array); - 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<StringName> &p_string_array); - Variant(const Vector<Vector3> &p_vector3_array); - Variant(const Vector<Color> &p_color_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_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 f9f73b4e51..3fdd18a630 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -33,10 +33,10 @@ #include "core/color_names.inc" #include "core/core_string_names.h" #include "core/io/compression.h" +#include "core/math/crypto_core.h" #include "core/object.h" #include "core/os/os.h" #include "core/script_language.h" -#include "thirdparty/misc/sha256.h" typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args); typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args); @@ -265,6 +265,7 @@ struct _VariantCall { VCALL_LOCALMEM1R(String, right); VCALL_LOCALMEM0R(String, dedent); VCALL_LOCALMEM2R(String, strip_edges); + VCALL_LOCALMEM0R(String, strip_escapes); VCALL_LOCALMEM1R(String, lstrip); VCALL_LOCALMEM1R(String, rstrip); VCALL_LOCALMEM0R(String, get_extension); @@ -274,8 +275,10 @@ struct _VariantCall { VCALL_LOCALMEM2(String, erase); VCALL_LOCALMEM0R(String, hash); VCALL_LOCALMEM0R(String, md5_text); + VCALL_LOCALMEM0R(String, sha1_text); VCALL_LOCALMEM0R(String, sha256_text); VCALL_LOCALMEM0R(String, md5_buffer); + VCALL_LOCALMEM0R(String, sha1_buffer); VCALL_LOCALMEM0R(String, sha256_buffer); VCALL_LOCALMEM0R(String, empty); VCALL_LOCALMEM0R(String, is_abs_path); @@ -284,6 +287,8 @@ struct _VariantCall { VCALL_LOCALMEM0R(String, get_file); VCALL_LOCALMEM0R(String, xml_escape); VCALL_LOCALMEM0R(String, xml_unescape); + VCALL_LOCALMEM0R(String, http_escape); + VCALL_LOCALMEM0R(String, http_unescape); VCALL_LOCALMEM0R(String, c_escape); VCALL_LOCALMEM0R(String, c_unescape); VCALL_LOCALMEM0R(String, json_escape); @@ -314,7 +319,7 @@ struct _VariantCall { retval.resize(len); PoolByteArray::Write w = retval.write(); copymem(w.ptr(), charstr.ptr(), len); - w = PoolVector<uint8_t>::Write(); + w.release(); r_ret = retval; } @@ -329,7 +334,7 @@ struct _VariantCall { retval.resize(len); PoolByteArray::Write w = retval.write(); copymem(w.ptr(), charstr.ptr(), len); - w = PoolVector<uint8_t>::Write(); + w.release(); r_ret = retval; } @@ -347,6 +352,7 @@ struct _VariantCall { VCALL_LOCALMEM2R(Vector2, linear_interpolate); VCALL_LOCALMEM2R(Vector2, slerp); VCALL_LOCALMEM4R(Vector2, cubic_interpolate); + VCALL_LOCALMEM2R(Vector2, move_toward); VCALL_LOCALMEM1R(Vector2, rotated); VCALL_LOCALMEM0R(Vector2, tangent); VCALL_LOCALMEM0R(Vector2, floor); @@ -388,6 +394,7 @@ struct _VariantCall { VCALL_LOCALMEM2R(Vector3, linear_interpolate); VCALL_LOCALMEM2R(Vector3, slerp); VCALL_LOCALMEM4R(Vector3, cubic_interpolate); + VCALL_LOCALMEM2R(Vector3, move_toward); VCALL_LOCALMEM1R(Vector3, dot); VCALL_LOCALMEM1R(Vector3, cross); VCALL_LOCALMEM1R(Vector3, outer); @@ -593,10 +600,7 @@ struct _VariantCall { PoolByteArray::Read r = ba->read(); String s; unsigned char hash[32]; - sha256_context sha256; - sha256_init(&sha256); - sha256_hash(&sha256, (unsigned char *)r.ptr(), ba->size()); - sha256_done(&sha256, hash); + CryptoCore::sha256((unsigned char *)r.ptr(), ba->size(), hash); s = String::hex_encode_buffer(hash, 32); r_ret = s; } @@ -1494,7 +1498,7 @@ void register_variant_methods() { ADDFUNC1R(STRING, INT, String, casecmp_to, STRING, "to", varray()); ADDFUNC1R(STRING, INT, String, nocasecmp_to, STRING, "to", varray()); ADDFUNC0R(STRING, INT, String, length, varray()); - ADDFUNC2R(STRING, STRING, String, substr, INT, "from", INT, "len", varray()); + ADDFUNC2R(STRING, STRING, String, substr, INT, "from", INT, "len", varray(-1)); ADDFUNC2R(STRING, INT, String, find, STRING, "what", INT, "from", varray(0)); @@ -1516,9 +1520,9 @@ void register_variant_methods() { ADDFUNC2R(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", 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, "divisor", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); - ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, rsplit, STRING, "divisor", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); - ADDFUNC2R(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true)); + 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)); ADDFUNC0R(STRING, STRING, String, to_upper, varray()); ADDFUNC0R(STRING, STRING, String, to_lower, varray()); @@ -1526,6 +1530,7 @@ void register_variant_methods() { ADDFUNC1R(STRING, STRING, String, left, INT, "position", varray()); ADDFUNC1R(STRING, STRING, String, right, INT, "position", varray()); ADDFUNC2R(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true)); + ADDFUNC0R(STRING, STRING, String, strip_escapes, varray()); ADDFUNC1R(STRING, STRING, String, lstrip, STRING, "chars", varray()); ADDFUNC1R(STRING, STRING, String, rstrip, STRING, "chars", varray()); ADDFUNC0R(STRING, STRING, String, get_extension, varray()); @@ -1536,8 +1541,10 @@ void register_variant_methods() { ADDFUNC2(STRING, NIL, String, erase, INT, "position", INT, "chars", varray()); ADDFUNC0R(STRING, INT, String, hash, varray()); 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, BOOL, String, empty, varray()); ADDFUNC0R(STRING, BOOL, String, is_abs_path, varray()); @@ -1546,6 +1553,8 @@ void register_variant_methods() { ADDFUNC0R(STRING, STRING, String, get_file, varray()); ADDFUNC0R(STRING, STRING, String, xml_escape, varray()); ADDFUNC0R(STRING, STRING, String, xml_unescape, varray()); + ADDFUNC0R(STRING, STRING, String, http_escape, varray()); + ADDFUNC0R(STRING, STRING, String, http_unescape, varray()); ADDFUNC0R(STRING, STRING, String, c_escape, varray()); ADDFUNC0R(STRING, STRING, String, c_unescape, varray()); ADDFUNC0R(STRING, STRING, String, json_escape, varray()); @@ -1583,6 +1592,7 @@ void register_variant_methods() { ADDFUNC2R(VECTOR2, VECTOR2, Vector2, linear_interpolate, VECTOR2, "b", REAL, "t", varray()); ADDFUNC2R(VECTOR2, VECTOR2, Vector2, slerp, VECTOR2, "b", REAL, "t", varray()); ADDFUNC4R(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", REAL, "t", varray()); + ADDFUNC2R(VECTOR2, VECTOR2, Vector2, move_toward, VECTOR2, "to", REAL, "delta", varray()); ADDFUNC1R(VECTOR2, VECTOR2, Vector2, rotated, REAL, "phi", varray()); ADDFUNC0R(VECTOR2, VECTOR2, Vector2, tangent, varray()); ADDFUNC0R(VECTOR2, VECTOR2, Vector2, floor, varray()); @@ -1624,6 +1634,7 @@ void register_variant_methods() { ADDFUNC2R(VECTOR3, VECTOR3, Vector3, slerp, VECTOR3, "b", REAL, "t", varray()); ADDFUNC4R(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", REAL, "t", varray()); ADDFUNC1R(VECTOR3, VECTOR3, Vector3, direction_to, VECTOR3, "b", varray()); + ADDFUNC2R(VECTOR3, VECTOR3, Vector3, move_toward, VECTOR3, "to", REAL, "delta", varray()); ADDFUNC1R(VECTOR3, REAL, Vector3, dot, VECTOR3, "b", varray()); ADDFUNC1R(VECTOR3, VECTOR3, Vector3, cross, VECTOR3, "b", varray()); ADDFUNC1R(VECTOR3, BASIS, Vector3, outer, VECTOR3, "b", varray()); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index f3c9bcaa7e..d677c7776a 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -2183,7 +2183,8 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) return; } - return obj->set(p_index, p_value, r_valid); + obj->set(p_index, p_value, r_valid); + return; } } break; case DICTIONARY: { diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index d7371b0434..d5513bc2d7 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -436,8 +436,6 @@ Error VariantParser::_parse_enginecfg(Stream *p_stream, Vector<String> &strings, line++; } } - - return OK; } template <class T> @@ -799,8 +797,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } } - return OK; - } else if (id == "Resource" || id == "SubResource" || id == "ExtResource") { get_token(p_stream, token, line, r_err_str); @@ -864,8 +860,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } } - - return OK; #ifndef DISABLE_DEPRECATED } else if (id == "InputEvent") { @@ -1256,8 +1250,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, r_err_str = "Expected value, got " + String(tk_name[token.type]) + "."; return ERR_PARSE_ERROR; } - - return ERR_PARSE_ERROR; } Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { @@ -1301,8 +1293,6 @@ Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, Str array.push_back(v); need_comma = true; } - - return OK; } Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { @@ -1372,8 +1362,6 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int at_key = true; } } - - return OK; } Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser, bool p_simple_tag) { @@ -1557,8 +1545,6 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r line++; } } - - return OK; } Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str, int &r_err_line, ResourceParser *p_res_parser) { diff --git a/core/vector.h b/core/vector.h index 93ee003519..e6bb4a96fc 100644 --- a/core/vector.h +++ b/core/vector.h @@ -150,7 +150,7 @@ template <class T> bool Vector<T>::push_back(const T &p_elem) { Error err = resize(size() + 1); - ERR_FAIL_COND_V(err, true) + ERR_FAIL_COND_V(err, true); set(size() - 1, p_elem); return false; |