diff options
Diffstat (limited to 'core')
35 files changed, 274 insertions, 134 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index f5dbacd62d..98d3e77f66 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -148,7 +148,7 @@ _ResourceLoader::_ResourceLoader() { singleton = this; } -Error _ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { +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); return ResourceSaver::save(p_path, p_resource, p_flags); @@ -792,7 +792,7 @@ Dictionary _OS::get_datetime_from_unix_time(int64_t unix_time_val) const { size_t imonth = 0; - while (dayno >= MONTH_DAYS_TABLE[LEAPYEAR(year)][imonth]) { + while ((unsigned long)dayno >= MONTH_DAYS_TABLE[LEAPYEAR(year)][imonth]) { dayno -= MONTH_DAYS_TABLE[LEAPYEAR(year)][imonth]; imonth++; } @@ -1579,7 +1579,7 @@ _Geometry::_Geometry() { ///////////////////////// FILE -Error _File::open_encrypted(const String &p_path, int p_mode_flags, const Vector<uint8_t> &p_key) { +Error _File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) { Error err = open(p_path, p_mode_flags); if (err) @@ -1596,7 +1596,7 @@ Error _File::open_encrypted(const String &p_path, int p_mode_flags, const Vector return OK; } -Error _File::open_encrypted_pass(const String &p_path, int p_mode_flags, const String &p_pass) { +Error _File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass) { Error err = open(p_path, p_mode_flags); if (err) @@ -1614,7 +1614,7 @@ Error _File::open_encrypted_pass(const String &p_path, int p_mode_flags, const S return OK; } -Error _File::open_compressed(const String &p_path, int p_mode_flags, int p_compress_mode) { +Error _File::open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode) { FileAccessCompressed *fac = memnew(FileAccessCompressed); @@ -1631,7 +1631,7 @@ Error _File::open_compressed(const String &p_path, int p_mode_flags, int p_compr return OK; } -Error _File::open(const String &p_path, int p_mode_flags) { +Error _File::open(const String &p_path, ModeFlags p_mode_flags) { close(); Error err; @@ -1908,18 +1908,18 @@ bool _File::file_exists(const String &p_name) const { return FileAccess::exists(p_name); } -void _File::store_var(const Variant &p_var) { +void _File::store_var(const Variant &p_var, bool p_full_objects) { ERR_FAIL_COND(!f); int len; - Error err = encode_variant(p_var, NULL, len); + Error err = encode_variant(p_var, NULL, len, p_full_objects); ERR_FAIL_COND(err != OK); PoolVector<uint8_t> buff; buff.resize(len); PoolVector<uint8_t>::Write w = buff.write(); - err = encode_variant(p_var, &w[0], len); + err = encode_variant(p_var, &w[0], len, p_full_objects); ERR_FAIL_COND(err != OK); w = PoolVector<uint8_t>::Write(); @@ -1927,7 +1927,7 @@ void _File::store_var(const Variant &p_var) { store_buffer(buff); } -Variant _File::get_var() const { +Variant _File::get_var(bool p_allow_objects) const { ERR_FAIL_COND_V(!f, Variant()); uint32_t len = get_32(); @@ -1937,7 +1937,7 @@ Variant _File::get_var() const { PoolVector<uint8_t>::Read r = buff.read(); Variant v; - Error err = decode_variant(v, &r[0], len); + Error err = decode_variant(v, &r[0], len, NULL, p_allow_objects); ERR_FAIL_COND_V(err != OK, Variant()); return v; @@ -1980,7 +1980,7 @@ void _File::_bind_methods() { ClassDB::bind_method(D_METHOD("get_endian_swap"), &_File::get_endian_swap); ClassDB::bind_method(D_METHOD("set_endian_swap", "enable"), &_File::set_endian_swap); ClassDB::bind_method(D_METHOD("get_error"), &_File::get_error); - ClassDB::bind_method(D_METHOD("get_var"), &_File::get_var); + ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &_File::get_var, DEFVAL(false)); ClassDB::bind_method(D_METHOD("store_8", "value"), &_File::store_8); ClassDB::bind_method(D_METHOD("store_16", "value"), &_File::store_16); @@ -1993,7 +1993,7 @@ void _File::_bind_methods() { ClassDB::bind_method(D_METHOD("store_line", "line"), &_File::store_line); ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &_File::store_csv_line, DEFVAL(",")); ClassDB::bind_method(D_METHOD("store_string", "string"), &_File::store_string); - ClassDB::bind_method(D_METHOD("store_var", "value"), &_File::store_var); + ClassDB::bind_method(D_METHOD("store_var", "value", "full_objects"), &_File::store_var, DEFVAL(false)); ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &_File::store_pascal_string); ClassDB::bind_method(D_METHOD("get_pascal_string"), &_File::get_pascal_string); @@ -2223,17 +2223,17 @@ _Marshalls *_Marshalls::get_singleton() { return singleton; } -String _Marshalls::variant_to_base64(const Variant &p_var) { +String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) { int len; - Error err = encode_variant(p_var, NULL, len); + Error err = encode_variant(p_var, NULL, len, p_full_objects); ERR_FAIL_COND_V(err != OK, ""); PoolVector<uint8_t> buff; buff.resize(len); PoolVector<uint8_t>::Write w = buff.write(); - err = encode_variant(p_var, &w[0], len); + err = encode_variant(p_var, &w[0], len, p_full_objects); ERR_FAIL_COND_V(err != OK, ""); int b64len = len / 3 * 4 + 4 + 1; @@ -2249,7 +2249,7 @@ String _Marshalls::variant_to_base64(const Variant &p_var) { return ret; }; -Variant _Marshalls::base64_to_variant(const String &p_str) { +Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) { int strlen = p_str.length(); CharString cstr = p_str.ascii(); @@ -2261,7 +2261,7 @@ Variant _Marshalls::base64_to_variant(const String &p_str) { int len = base64_decode((char *)(&w[0]), (char *)cstr.get_data(), strlen); Variant v; - Error err = decode_variant(v, &w[0], len); + Error err = decode_variant(v, &w[0], len, NULL, p_allow_objects); ERR_FAIL_COND_V(err != OK, Variant()); return v; @@ -2340,8 +2340,8 @@ String _Marshalls::base64_to_utf8(const String &p_str) { void _Marshalls::_bind_methods() { - ClassDB::bind_method(D_METHOD("variant_to_base64", "variant"), &_Marshalls::variant_to_base64); - ClassDB::bind_method(D_METHOD("base64_to_variant", "base64_str"), &_Marshalls::base64_to_variant); + ClassDB::bind_method(D_METHOD("variant_to_base64", "variant", "full_objects"), &_Marshalls::variant_to_base64, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("base64_to_variant", "base64_str", "allow_objects"), &_Marshalls::base64_to_variant, DEFVAL(false)); ClassDB::bind_method(D_METHOD("raw_to_base64", "array"), &_Marshalls::raw_to_base64); ClassDB::bind_method(D_METHOD("base64_to_raw", "base64_str"), &_Marshalls::base64_to_raw); @@ -2453,12 +2453,12 @@ void _Thread::_start_func(void *ud) { } } -Error _Thread::start(Object *p_instance, const StringName &p_method, const Variant &p_userdata, int p_priority) { +Error _Thread::start(Object *p_instance, const StringName &p_method, const Variant &p_userdata, Priority p_priority) { ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_instance, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_method == StringName(), ERR_INVALID_PARAMETER); - ERR_FAIL_INDEX_V(p_priority, 3, ERR_INVALID_PARAMETER); + ERR_FAIL_INDEX_V(p_priority, PRIORITY_MAX, ERR_INVALID_PARAMETER); ret = Variant(); target_method = p_method; diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 803743bc93..2906de4a4a 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -85,7 +85,7 @@ public: static _ResourceSaver *get_singleton() { return singleton; } - Error save(const String &p_path, const RES &p_resource, uint32_t p_flags); + Error save(const String &p_path, const RES &p_resource, SaverFlags p_flags); PoolVector<String> get_recognized_extensions(const RES &p_resource); _ResourceSaver(); @@ -436,11 +436,11 @@ public: COMPRESSION_GZIP = Compression::MODE_GZIP }; - Error open_encrypted(const String &p_path, int p_mode_flags, const Vector<uint8_t> &p_key); - Error open_encrypted_pass(const String &p_path, int p_mode_flags, const String &p_pass); - Error open_compressed(const String &p_path, int p_mode_flags, int p_compress_mode = 0); + Error open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key); + Error open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass); + Error open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode = COMPRESSION_FASTLZ); - Error open(const String &p_path, int p_mode_flags); ///< open a file + Error open(const String &p_path, ModeFlags p_mode_flags); ///< open a file void close(); ///< close a file bool is_open() const; ///< true when file is open @@ -463,7 +463,7 @@ public: double get_double() const; real_t get_real() const; - Variant get_var() const; + Variant get_var(bool p_allow_objects = false) const; PoolVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes String get_line() const; @@ -500,7 +500,7 @@ public: void store_buffer(const PoolVector<uint8_t> &p_buffer); ///< store an array of bytes - void store_var(const Variant &p_var); + void store_var(const Variant &p_var, bool p_full_objects = false); bool file_exists(const String &p_name) const; ///< return true if a file exists @@ -569,8 +569,8 @@ protected: public: static _Marshalls *get_singleton(); - String variant_to_base64(const Variant &p_var); - Variant base64_to_variant(const String &p_str); + String variant_to_base64(const Variant &p_var, bool p_full_objects = false); + Variant base64_to_variant(const String &p_str, bool p_allow_objects = false); String raw_to_base64(const PoolVector<uint8_t> &p_arr); PoolVector<uint8_t> base64_to_raw(const String &p_str); @@ -632,10 +632,11 @@ public: PRIORITY_LOW, PRIORITY_NORMAL, - PRIORITY_HIGH + PRIORITY_HIGH, + PRIORITY_MAX }; - Error start(Object *p_instance, const StringName &p_method, const Variant &p_userdata = Variant(), int p_priority = PRIORITY_NORMAL); + Error start(Object *p_instance, const StringName &p_method, const Variant &p_userdata = Variant(), Priority p_priority = PRIORITY_NORMAL); String get_id() const; bool is_active() const; Variant wait_to_finish(); diff --git a/core/class_db.cpp b/core/class_db.cpp index 219bdbddd8..f7b446707d 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -249,6 +249,11 @@ void ClassDB::set_current_api(APIType p_api) { current_api = p_api; } +ClassDB::APIType ClassDB::get_current_api() { + + return current_api; +} + HashMap<StringName, ClassDB::ClassInfo> ClassDB::classes; HashMap<StringName, StringName> ClassDB::resource_base_extensions; HashMap<StringName, StringName> ClassDB::compat_classes; diff --git a/core/class_db.h b/core/class_db.h index 321682d76b..f18a7113d7 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -371,6 +371,7 @@ public: static void init(); static void set_current_api(APIType p_api); + static APIType get_current_api(); static void cleanup(); }; diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index c97b8cafac..d38d09c6bb 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -272,7 +272,7 @@ int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const { if (eof) return 0; - int64_t to_read = p_length; + uint64_t to_read = p_length; if (to_read + pos > pf.size) { eof = true; to_read = int64_t(pf.size) - int64_t(pos); diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 5087a63b68..363460311c 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -794,7 +794,7 @@ static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) { } } -Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_object_as_id) { +Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects) { uint8_t *buf = r_buffer; @@ -819,7 +819,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; case Variant::OBJECT: { - if (p_object_as_id) { + if (!p_full_objects) { flags |= ENCODE_FLAG_OBJECT_AS_ID; } } break; @@ -1086,22 +1086,8 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::OBJECT: { - if (p_object_as_id) { + if (p_full_objects) { - if (buf) { - - Object *obj = p_variant; - ObjectID id = 0; - if (obj && ObjectDB::instance_validate(obj)) { - id = obj->get_instance_id(); - } - - encode_uint64(id, buf); - } - - r_len += 8; - - } else { Object *obj = p_variant; if (!obj) { if (buf) { @@ -1139,7 +1125,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo _encode_string(E->get().name, buf, r_len); int len; - Error err = encode_variant(obj->get(E->get().name), buf, len, p_object_as_id); + Error err = encode_variant(obj->get(E->get().name), buf, len, p_full_objects); if (err) return err; ERR_FAIL_COND_V(len % 4, ERR_BUG); @@ -1148,6 +1134,19 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo buf += len; } } + } else { + if (buf) { + + Object *obj = p_variant; + ObjectID id = 0; + if (obj && ObjectDB::instance_validate(obj)) { + id = obj->get_instance_id(); + } + + encode_uint64(id, buf); + } + + r_len += 8; } } break; @@ -1180,14 +1179,14 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len++; //pad */ int len; - encode_variant(E->get(), buf, len, p_object_as_id); + encode_variant(E->get(), buf, len, p_full_objects); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; if (buf) buf += len; Variant *v = d.getptr(E->get()); ERR_FAIL_COND_V(!v, ERR_BUG); - encode_variant(*v, buf, len, p_object_as_id); + encode_variant(*v, buf, len, p_full_objects); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; if (buf) @@ -1209,7 +1208,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo for (int i = 0; i < v.size(); i++) { int len; - encode_variant(v.get(i), buf, len, p_object_as_id); + encode_variant(v.get(i), buf, len, p_full_objects); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; if (buf) diff --git a/core/io/marshalls.h b/core/io/marshalls.h index 11c4b2c98e..f361c29754 100644 --- a/core/io/marshalls.h +++ b/core/io/marshalls.h @@ -199,7 +199,7 @@ public: EncodedObjectAsID(); }; -Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len = NULL, bool p_allow_objects = true); -Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_object_as_id = false); +Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len = NULL, bool p_allow_objects = false); +Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects = false); #endif diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 7680d47620..86382939f1 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -46,7 +46,8 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas case MultiplayerAPI::RPC_MODE_MASTERSYNC: { if (is_master) r_skip_rpc = true; // I am the master, so skip remote call. - } // Do not break, fall over to other sync. + FALLTHROUGH; + } case MultiplayerAPI::RPC_MODE_REMOTESYNC: case MultiplayerAPI::RPC_MODE_PUPPETSYNC: { // Call it, sync always results in a local call. @@ -299,7 +300,7 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_ ERR_FAIL_COND(p_offset >= p_packet_len); int vlen; - Error err = decode_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen); + Error err = decode_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen, allow_object_decoding || network_peer->is_object_decoding_allowed()); ERR_EXPLAIN("Invalid packet received. Unable to decode RPC argument."); ERR_FAIL_COND(err != OK); @@ -335,7 +336,7 @@ void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p ERR_FAIL_COND(!_can_call_mode(p_node, rset_mode, p_from)); Variant value; - Error err = decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset); + Error err = decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset, NULL, allow_object_decoding || network_peer->is_object_decoding_allowed()); ERR_EXPLAIN("Invalid packet received. Unable to decode RSET value."); ERR_FAIL_COND(err != OK); @@ -526,11 +527,11 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p if (p_set) { // Set argument. - Error err = encode_variant(*p_arg[0], NULL, len); + Error err = encode_variant(*p_arg[0], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed()); ERR_EXPLAIN("Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!"); ERR_FAIL_COND(err != OK); MAKE_ROOM(ofs + len); - encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len); + encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed()); ofs += len; } else { @@ -539,11 +540,11 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p packet_cache.write[ofs] = p_argcount; ofs += 1; for (int i = 0; i < p_argcount; i++) { - Error err = encode_variant(*p_arg[i], NULL, len); + Error err = encode_variant(*p_arg[i], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed()); ERR_EXPLAIN("Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!"); ERR_FAIL_COND(err != OK); MAKE_ROOM(ofs + len); - encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len); + encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed()); ofs += len; } } @@ -818,6 +819,16 @@ Vector<int> MultiplayerAPI::get_network_connected_peers() const { return ret; } +void MultiplayerAPI::set_allow_object_decoding(bool p_enable) { + + allow_object_decoding = p_enable; +} + +bool MultiplayerAPI::is_object_decoding_allowed() const { + + return allow_object_decoding; +} + void MultiplayerAPI::_bind_methods() { ClassDB::bind_method(D_METHOD("set_root_node", "node"), &MultiplayerAPI::set_root_node); ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode"), &MultiplayerAPI::send_bytes, DEFVAL(NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE)); @@ -838,6 +849,10 @@ void MultiplayerAPI::_bind_methods() { ClassDB::bind_method(D_METHOD("get_network_connected_peers"), &MultiplayerAPI::get_network_connected_peers); ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &MultiplayerAPI::set_refuse_new_network_connections); ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &MultiplayerAPI::is_refusing_new_network_connections); + ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &MultiplayerAPI::set_allow_object_decoding); + ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &MultiplayerAPI::is_object_decoding_allowed); + + 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"); @@ -859,7 +874,8 @@ void MultiplayerAPI::_bind_methods() { BIND_ENUM_CONSTANT(RPC_MODE_PUPPETSYNC); } -MultiplayerAPI::MultiplayerAPI() { +MultiplayerAPI::MultiplayerAPI() : + allow_object_decoding(false) { rpc_sender_id = 0; root_node = NULL; clear(); diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h index a9cf77aaba..779dd043bd 100644 --- a/core/io/multiplayer_api.h +++ b/core/io/multiplayer_api.h @@ -63,6 +63,7 @@ private: int last_send_cache_id; Vector<uint8_t> packet_cache; Node *root_node; + bool allow_object_decoding; protected: static void _bind_methods(); @@ -126,6 +127,9 @@ public: void set_refuse_new_network_connections(bool p_refuse); bool is_refusing_new_network_connections() const; + void set_allow_object_decoding(bool p_enable); + bool is_object_decoding_allowed() const; + MultiplayerAPI(); ~MultiplayerAPI(); }; diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index d7bfdbbb37..c77c81f9e2 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -79,7 +79,7 @@ Error PacketPeer::put_packet_buffer(const PoolVector<uint8_t> &p_buffer) { return put_packet(&r[0], len); } -Error PacketPeer::get_var(Variant &r_variant) { +Error PacketPeer::get_var(Variant &r_variant, bool p_allow_objects) { const uint8_t *buffer; int buffer_size; @@ -87,13 +87,13 @@ Error PacketPeer::get_var(Variant &r_variant) { if (err) return err; - return decode_variant(r_variant, buffer, buffer_size, NULL, allow_object_decoding); + return decode_variant(r_variant, buffer, buffer_size, NULL, p_allow_objects || allow_object_decoding); } -Error PacketPeer::put_var(const Variant &p_packet) { +Error PacketPeer::put_var(const Variant &p_packet, bool p_full_objects) { int len; - Error err = encode_variant(p_packet, NULL, len, !allow_object_decoding); // compute len first + Error err = encode_variant(p_packet, NULL, len, p_full_objects || allow_object_decoding); // compute len first if (err) return err; @@ -102,15 +102,15 @@ Error PacketPeer::put_var(const Variant &p_packet) { uint8_t *buf = (uint8_t *)alloca(len); ERR_FAIL_COND_V(!buf, ERR_OUT_OF_MEMORY); - err = encode_variant(p_packet, buf, len, !allow_object_decoding); + err = encode_variant(p_packet, buf, len, p_full_objects || allow_object_decoding); ERR_FAIL_COND_V(err, err); return put_packet(buf, len); } -Variant PacketPeer::_bnd_get_var() { +Variant PacketPeer::_bnd_get_var(bool p_allow_objects) { Variant var; - get_var(var); + get_var(var, p_allow_objects); return var; }; @@ -132,8 +132,8 @@ Error PacketPeer::_get_packet_error() const { void PacketPeer::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_var"), &PacketPeer::_bnd_get_var); - ClassDB::bind_method(D_METHOD("put_var", "var"), &PacketPeer::put_var); + ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &PacketPeer::_bnd_get_var, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("put_var", "var", "full_objects"), &PacketPeer::put_var, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_packet"), &PacketPeer::_get_packet); ClassDB::bind_method(D_METHOD("put_packet", "buffer"), &PacketPeer::_put_packet); ClassDB::bind_method(D_METHOD("get_packet_error"), &PacketPeer::_get_packet_error); diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index 48c50eb76b..6475e4fed9 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -39,8 +39,7 @@ class PacketPeer : public Reference { GDCLASS(PacketPeer, Reference); - Variant _bnd_get_var(); - void _bnd_put_var(const Variant &p_var); + Variant _bnd_get_var(bool p_allow_objects = false); static void _bind_methods(); @@ -64,8 +63,8 @@ public: virtual Error get_packet_buffer(PoolVector<uint8_t> &r_buffer); virtual Error put_packet_buffer(const PoolVector<uint8_t> &p_buffer); - virtual Error get_var(Variant &r_variant); - virtual Error put_var(const Variant &p_packet); + virtual Error get_var(Variant &r_variant, bool p_allow_objects = false); + virtual Error put_var(const Variant &p_packet, bool p_full_objects = false); void set_allow_object_decoding(bool p_enable); bool is_object_decoding_allowed() const; diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index 3042c0f60a..6ad24a5f3a 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -221,14 +221,14 @@ void StreamPeer::put_utf8_string(const String &p_string) { put_u32(cs.length()); put_data((const uint8_t *)cs.get_data(), cs.length()); } -void StreamPeer::put_var(const Variant &p_variant) { +void StreamPeer::put_var(const Variant &p_variant, bool p_full_objects) { int len = 0; Vector<uint8_t> buf; - encode_variant(p_variant, NULL, len); + encode_variant(p_variant, NULL, len, p_full_objects); buf.resize(len); put_32(len); - encode_variant(p_variant, buf.ptrw(), len); + encode_variant(p_variant, buf.ptrw(), len, p_full_objects); put_data(buf.ptr(), buf.size()); } @@ -359,7 +359,7 @@ String StreamPeer::get_utf8_string(int p_bytes) { ret.parse_utf8((const char *)buf.ptr(), buf.size()); return ret; } -Variant StreamPeer::get_var() { +Variant StreamPeer::get_var(bool p_allow_objects) { int len = get_32(); Vector<uint8_t> var; @@ -369,7 +369,7 @@ Variant StreamPeer::get_var() { ERR_FAIL_COND_V(err != OK, Variant()); Variant ret; - decode_variant(ret, var.ptr(), len); + decode_variant(ret, var.ptr(), len, NULL, p_allow_objects); return ret; } @@ -398,7 +398,7 @@ void StreamPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("put_double", "value"), &StreamPeer::put_double); ClassDB::bind_method(D_METHOD("put_string", "value"), &StreamPeer::put_string); ClassDB::bind_method(D_METHOD("put_utf8_string", "value"), &StreamPeer::put_utf8_string); - ClassDB::bind_method(D_METHOD("put_var", "value"), &StreamPeer::put_var); + ClassDB::bind_method(D_METHOD("put_var", "value", "full_objects"), &StreamPeer::put_var, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_8"), &StreamPeer::get_8); ClassDB::bind_method(D_METHOD("get_u8"), &StreamPeer::get_u8); @@ -412,7 +412,7 @@ void StreamPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_double"), &StreamPeer::get_double); ClassDB::bind_method(D_METHOD("get_string", "bytes"), &StreamPeer::get_string, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("get_utf8_string", "bytes"), &StreamPeer::get_utf8_string, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("get_var"), &StreamPeer::get_var); + ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &StreamPeer::get_var, DEFVAL(false)); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian_enabled"); } diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index 059ccd016c..65e70995ad 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -73,7 +73,7 @@ public: void put_double(double p_val); void put_string(const String &p_string); void put_utf8_string(const String &p_string); - void put_var(const Variant &p_variant); + void put_var(const Variant &p_variant, bool p_full_objects = false); uint8_t get_u8(); int8_t get_8(); @@ -87,7 +87,7 @@ public: double get_double(); String get_string(int p_bytes = -1); String get_utf8_string(int p_bytes = -1); - Variant get_var(); + Variant get_var(bool p_allow_objects = false); StreamPeer() { big_endian = false; } }; diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h index f970c510e0..ebe0356c93 100644 --- a/core/math/audio_frame.h +++ b/core/math/audio_frame.h @@ -122,6 +122,12 @@ struct AudioFrame { r = p_frame.r; } + _ALWAYS_INLINE_ AudioFrame operator=(const AudioFrame &p_frame) { + l = p_frame.l; + r = p_frame.r; + return *this; + } + _ALWAYS_INLINE_ AudioFrame() {} }; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 8816e3639a..82b2f7006d 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -557,11 +557,23 @@ void Basis::set_euler_yxz(const Vector3 &p_euler) { *this = ymat * xmat * zmat; } -bool Basis::is_equal_approx(const Basis &a, const Basis &b) const { +bool Basis::is_equal_approx(const Basis &a, const Basis &b,real_t p_epsilon) const { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - if (!Math::is_equal_approx_ratio(a.elements[i][j], b.elements[i][j], UNIT_EPSILON)) + if (!Math::is_equal_approx(a.elements[i][j], b.elements[i][j], p_epsilon)) + return false; + } + } + + return true; +} + +bool Basis::is_equal_approx_ratio(const Basis &a, const Basis &b,real_t p_epsilon) const { + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (!Math::is_equal_approx_ratio(a.elements[i][j], b.elements[i][j], p_epsilon)) return false; } } @@ -605,12 +617,14 @@ Basis::operator String() const { Quat Basis::get_quat() const { +#ifdef MATH_CHECKS + if (!is_rotation()) { + ERR_EXPLAIN("Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quat() or call orthonormalized() instead."); + ERR_FAIL_V(Quat()); + } +#endif /* Allow getting a quaternion from an unnormalized transform */ Basis m = *this; - m.elements[0].normalize(); - m.elements[1].normalize(); - m.elements[2].normalize(); - real_t trace = m.elements[0][0] + m.elements[1][1] + m.elements[2][2]; real_t temp[4]; diff --git a/core/math/basis.h b/core/math/basis.h index 128e56b494..aa0ddb280f 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -133,7 +133,8 @@ public: return elements[0][2] * v[0] + elements[1][2] * v[1] + elements[2][2] * v[2]; } - bool is_equal_approx(const Basis &a, const Basis &b) const; + bool is_equal_approx(const Basis &a, const Basis &b, real_t p_epsilon=CMP_EPSILON) const; + bool is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsilon=UNIT_EPSILON) const; bool operator==(const Basis &p_matrix) const; bool operator!=(const Basis &p_matrix) const; diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 99251d80e3..05b49f0815 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -68,6 +68,7 @@ const char *Expression::func_name[Expression::FUNC_MAX] = { "lerp", "inverse_lerp", "range_lerp", + "smoothstep", "dectime", "randomize", "randi", @@ -164,10 +165,10 @@ int Expression::get_func_argument_count(BuiltinFunc p_func) { case TEXT_PRINTRAW: case VAR_TO_STR: case STR_TO_VAR: - case VAR_TO_BYTES: - case BYTES_TO_VAR: case TYPE_EXISTS: return 1; + case VAR_TO_BYTES: + case BYTES_TO_VAR: case MATH_ATAN2: case MATH_FMOD: case MATH_FPOSMOD: @@ -185,6 +186,7 @@ int Expression::get_func_argument_count(BuiltinFunc p_func) { return 2; case MATH_LERP: case MATH_INVERSE_LERP: + case MATH_SMOOTHSTEP: case MATH_DECTIME: case MATH_WRAP: case MATH_WRAPF: @@ -392,6 +394,12 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant VALIDATE_ARG_NUM(4); *r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]); } break; + case MATH_SMOOTHSTEP: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); + } break; case MATH_DECTIME: { VALIDATE_ARG_NUM(0); @@ -696,8 +704,9 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant case VAR_TO_BYTES: { PoolByteArray barr; + bool full_objects = *p_inputs[1]; int len; - Error err = encode_variant(*p_inputs[0], NULL, len); + Error err = encode_variant(*p_inputs[0], NULL, len, full_objects); if (err) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -709,7 +718,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant barr.resize(len); { PoolByteArray::Write w = barr.write(); - encode_variant(*p_inputs[0], w.ptr(), len); + encode_variant(*p_inputs[0], w.ptr(), len, full_objects); } *r_return = barr; } break; @@ -724,10 +733,11 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } PoolByteArray varr = *p_inputs[0]; + bool allow_objects = *p_inputs[1]; Variant ret; { PoolByteArray::Read r = varr.read(); - Error err = decode_variant(ret, r.ptr(), varr.size(), NULL); + Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects); if (err != OK) { r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format."); r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; diff --git a/core/math/expression.h b/core/math/expression.h index fa0878c93c..f9075cb689 100644 --- a/core/math/expression.h +++ b/core/math/expression.h @@ -66,6 +66,7 @@ public: MATH_LERP, MATH_INVERSE_LERP, MATH_RANGE_LERP, + MATH_SMOOTHSTEP, MATH_DECTIME, MATH_RANDOMIZE, MATH_RAND, diff --git a/core/math/geometry.h b/core/math/geometry.h index 4b478b6b16..7347cb742a 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -702,9 +702,11 @@ public: /* if we can assume that the line segment starts outside the circle (e.g. for continuous time collision detection) then the following can be skipped and we can just return the equivalent of res1 */ sqrtterm = Math::sqrt(sqrtterm); real_t res1 = (-b - sqrtterm) / (2 * a); - //real_t res2 = ( -b + sqrtterm ) / (2 * a); + real_t res2 = (-b + sqrtterm) / (2 * a); - return (res1 >= 0 && res1 <= 1) ? res1 : -1; + if (res1 >= 0 && res1 <= 1) return res1; + if (res2 >= 0 && res2 <= 1) return res2; + return -1; } static inline Vector<Vector3> clip_polygon(const Vector<Vector3> &polygon, const Plane &p_plane) { diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 17112d8940..0d209402dd 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -208,6 +208,17 @@ public: static _ALWAYS_INLINE_ double range_lerp(double p_value, double p_istart, double p_istop, double p_ostart, double p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); } static _ALWAYS_INLINE_ float range_lerp(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); } + static _ALWAYS_INLINE_ double smoothstep(double p_from, double p_to, double p_weight) { + if (is_equal_approx(p_from, p_to)) return p_from; + double x = CLAMP((p_weight - p_from) / (p_to - p_from), 0.0, 1.0); + return x * x * (3.0 - 2.0 * x); + } + static _ALWAYS_INLINE_ float smoothstep(float p_from, float p_to, float p_weight) { + if (is_equal_approx(p_from, p_to)) return p_from; + 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 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; } @@ -249,11 +260,11 @@ public: static float random(float from, float to); static real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); } - static _ALWAYS_INLINE_ bool is_equal_approx_ratio(real_t a, real_t b, real_t epsilon = CMP_EPSILON) { + static _ALWAYS_INLINE_ bool is_equal_approx_ratio(real_t a, real_t b, real_t epsilon = CMP_EPSILON, real_t min_epsilon = CMP_EPSILON) { // this is an approximate way to check that numbers are close, as a ratio of their average size // helps compare approximate numbers that may be very big or very small real_t diff = abs(a - b); - if (diff == 0.0) { + if (diff == 0.0 || diff < min_epsilon) { return true; } real_t avg_size = (abs(a) + abs(b)) / 2.0; diff --git a/core/math/quat.h b/core/math/quat.h index 7d71ec03e8..8ed2fa7cc2 100644 --- a/core/math/quat.h +++ b/core/math/quat.h @@ -131,6 +131,14 @@ public: w(q.w) { } + Quat operator=(const Quat &q) { + x = q.x; + y = q.y; + z = q.z; + w = q.w; + return *this; + } + Quat(const Vector3 &v0, const Vector3 &v1) // shortest arc { Vector3 c = v0.cross(v1); diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp index fccc0f72fe..6add00c1d8 100644 --- a/core/math/random_number_generator.cpp +++ b/core/math/random_number_generator.cpp @@ -40,6 +40,7 @@ void RandomNumberGenerator::_bind_methods() { ClassDB::bind_method(D_METHOD("randi"), &RandomNumberGenerator::randi); ClassDB::bind_method(D_METHOD("randf"), &RandomNumberGenerator::randf); + ClassDB::bind_method(D_METHOD("randfn", "mean", "deviation"), &RandomNumberGenerator::randfn, DEFVAL(0.0), DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("randf_range", "from", "to"), &RandomNumberGenerator::randf_range); ClassDB::bind_method(D_METHOD("randi_range", "from", "to"), &RandomNumberGenerator::randi_range); ClassDB::bind_method(D_METHOD("randomize"), &RandomNumberGenerator::randomize); diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h index 66c77b8ccf..6b6bcdd2cd 100644 --- a/core/math/random_number_generator.h +++ b/core/math/random_number_generator.h @@ -55,6 +55,8 @@ public: _FORCE_INLINE_ real_t randf_range(real_t from, real_t to) { return randbase.random(from, to); } + _FORCE_INLINE_ real_t randfn(real_t mean = 0.0, real_t deviation = 1.0) { return randbase.randfn(mean, deviation); } + _FORCE_INLINE_ int randi_range(int from, int to) { unsigned int ret = randbase.rand(); return ret % (to - from + 1) + from; diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp index 45467b32b2..8351bd138e 100644 --- a/core/math/random_pcg.cpp +++ b/core/math/random_pcg.cpp @@ -34,8 +34,7 @@ RandomPCG::RandomPCG(uint64_t p_seed, uint64_t p_inc) : pcg(), - current_seed(DEFAULT_SEED) { - pcg.inc = p_inc; + current_inc(p_inc) { seed(p_seed); } diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index 230eb9a11b..0d1b311c0d 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -31,6 +31,8 @@ #ifndef RANDOM_PCG_H #define RANDOM_PCG_H +#include <math.h> + #include "core/math/math_defs.h" #include "thirdparty/misc/pcg.h" @@ -38,18 +40,18 @@ class RandomPCG { pcg32_random_t pcg; uint64_t current_seed; // seed with this to get the same state + uint64_t current_inc; public: static const uint64_t DEFAULT_SEED = 12047754176567800795U; static const uint64_t DEFAULT_INC = PCG_DEFAULT_INC_64; static const uint64_t RANDOM_MAX = 0xFFFFFFFF; - RandomPCG(uint64_t p_seed = DEFAULT_SEED, uint64_t p_inc = PCG_DEFAULT_INC_64); + RandomPCG(uint64_t p_seed = DEFAULT_SEED, uint64_t p_inc = DEFAULT_INC); _FORCE_INLINE_ void seed(uint64_t p_seed) { current_seed = p_seed; - pcg.state = p_seed; - pcg32_random_r(&pcg); // Force changing internal state to avoid initial 0 + pcg32_srandom_r(&pcg, current_seed, current_inc); } _FORCE_INLINE_ uint64_t get_seed() { return current_seed; } @@ -61,6 +63,13 @@ public: _FORCE_INLINE_ double randd() { return (double)rand() / (double)RANDOM_MAX; } _FORCE_INLINE_ float randf() { return (float)rand() / (float)RANDOM_MAX; } + _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 + } + _FORCE_INLINE_ float randfn(float p_mean, float p_deviation) { + return p_mean + p_deviation * (cos(Math_TAU * randf()) * sqrt(-2.0 * log(randf()))); // Box-Muller transform + } + double random(double p_from, double p_to); float random(float p_from, float p_to); real_t random(int p_from, int p_to) { return (real_t)random((real_t)p_from, (real_t)p_to); } diff --git a/core/os/main_loop.h b/core/os/main_loop.h index bfdf92acfa..ad734d3fc8 100644 --- a/core/os/main_loop.h +++ b/core/os/main_loop.h @@ -51,21 +51,19 @@ protected: public: enum { - NOTIFICATION_WM_MOUSE_ENTER = 2, - NOTIFICATION_WM_MOUSE_EXIT = 3, - NOTIFICATION_WM_FOCUS_IN = 4, - NOTIFICATION_WM_FOCUS_OUT = 5, - NOTIFICATION_WM_QUIT_REQUEST = 6, - NOTIFICATION_WM_GO_BACK_REQUEST = 7, - NOTIFICATION_WM_UNFOCUS_REQUEST = 8, - NOTIFICATION_OS_MEMORY_WARNING = 9, - // Note: NOTIFICATION_TRANSLATION_CHANGED and NOTIFICATION_WM_ABOUT used to have id=10 and id=11 but these - // conflict with NOTIFICATION_ENTER_TREE (id=10) and NOTIFICATION_EXIT_TREE (id=11), so id=90 and id=91 - // fixes this issue. - NOTIFICATION_TRANSLATION_CHANGED = 90, - NOTIFICATION_WM_ABOUT = 91, - NOTIFICATION_CRASH = 92, - NOTIFICATION_OS_IME_UPDATE = 93, + //make sure these are replicated in Node + NOTIFICATION_WM_MOUSE_ENTER = 1002, + NOTIFICATION_WM_MOUSE_EXIT = 1003, + NOTIFICATION_WM_FOCUS_IN = 1004, + NOTIFICATION_WM_FOCUS_OUT = 1005, + NOTIFICATION_WM_QUIT_REQUEST = 1006, + NOTIFICATION_WM_GO_BACK_REQUEST = 1007, + NOTIFICATION_WM_UNFOCUS_REQUEST = 1008, + NOTIFICATION_OS_MEMORY_WARNING = 1009, + NOTIFICATION_TRANSLATION_CHANGED = 1010, + NOTIFICATION_WM_ABOUT = 1011, + NOTIFICATION_CRASH = 1012, + NOTIFICATION_OS_IME_UPDATE = 1013, }; virtual void input_event(const Ref<InputEvent> &p_event); diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp index 0d7ad23d68..7cb7ae130f 100644 --- a/core/os/midi_driver.cpp +++ b/core/os/midi_driver.cpp @@ -75,6 +75,11 @@ void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_ if (length >= 3) { event->set_pitch(data[1]); event->set_velocity(data[2]); + + if (event->get_message() == MIDI_MESSAGE_NOTE_ON && event->get_velocity() == 0) { + // https://www.midi.org/forum/228-writing-midi-software-send-note-off,-or-zero-velocity-note-on + event->set_message(MIDI_MESSAGE_NOTE_OFF); + } } break; diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp index 6c17f42b13..99bed829c1 100644 --- a/core/packed_data_container.cpp +++ b/core/packed_data_container.cpp @@ -114,7 +114,7 @@ Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, b } else { Variant v; - Error rerr = decode_variant(v, p_buf + p_ofs, datalen - p_ofs, NULL); + Error rerr = decode_variant(v, p_buf + p_ofs, datalen - p_ofs, NULL, false); if (rerr != OK) { @@ -249,9 +249,9 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd uint32_t pos = tmpdata.size(); int len; - encode_variant(p_data, NULL, len); + encode_variant(p_data, NULL, len, false); tmpdata.resize(tmpdata.size() + len); - encode_variant(p_data, &tmpdata.write[pos], len); + encode_variant(p_data, &tmpdata.write[pos], len, false); return pos; } break; diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 02c7c9e029..8c9a3dbcd4 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -501,7 +501,7 @@ Error ProjectSettings::_load_settings_binary(const String p_path) { d.resize(vlen); f->get_buffer(d.ptrw(), vlen); Variant value; - err = decode_variant(value, d.ptr(), d.size()); + err = decode_variant(value, d.ptr(), d.size(), NULL, false); ERR_EXPLAIN("Error decoding property: " + key); ERR_CONTINUE(err != OK); set(key, value); @@ -656,7 +656,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str file->store_string(key); int len; - err = encode_variant(p_custom_features, NULL, len); + err = encode_variant(p_custom_features, NULL, len, false); if (err != OK) { memdelete(file); ERR_FAIL_V(err); @@ -665,7 +665,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str Vector<uint8_t> buff; buff.resize(len); - err = encode_variant(p_custom_features, buff.ptrw(), len); + err = encode_variant(p_custom_features, buff.ptrw(), len, false); if (err != OK) { memdelete(file); ERR_FAIL_V(err); @@ -694,7 +694,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str file->store_string(key); int len; - err = encode_variant(value, NULL, len); + err = encode_variant(value, NULL, len, false); if (err != OK) memdelete(file); ERR_FAIL_COND_V(err != OK, ERR_INVALID_DATA); @@ -702,7 +702,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str Vector<uint8_t> buff; buff.resize(len); - err = encode_variant(value, buff.ptrw(), len); + err = encode_variant(value, buff.ptrw(), len, false); if (err != OK) memdelete(file); ERR_FAIL_COND_V(err != OK, ERR_INVALID_DATA); diff --git a/core/script_language.h b/core/script_language.h index b6d7bea9c7..005e21e2cc 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -205,6 +205,8 @@ public: static ScriptCodeCompletionCache *get_singleton() { return singleton; } ScriptCodeCompletionCache(); + + virtual ~ScriptCodeCompletionCache() {} }; class ScriptLanguage { diff --git a/core/typedefs.h b/core/typedefs.h index 78688ff311..660139b90a 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -328,4 +328,31 @@ struct _GlobalLock { #define _PRINTF_FORMAT_ATTRIBUTE_2_3 #endif +/** This is needed due to a strange OpenGL API that expects a pointer + * type for an argument that is actually an offset. + */ +#define CAST_INT_TO_UCHAR_PTR(ptr) ((uint8_t *)(uintptr_t)(ptr)) + +/** Hint for compilers that this fallthrough in a switch is intentional. + * Can be replaced by [[fallthrough]] annotation if we move to C++17. + * Including conditional support for it for people who set -std=c++17 + * themselves. + * Requires a trailing semicolon when used. + */ +#if __cplusplus >= 201703L +#define FALLTHROUGH [[fallthrough]] +#elif defined(__GNUC__) && __GNUC__ >= 7 +#define FALLTHROUGH __attribute__((fallthrough)) +#elif defined(__llvm__) && __cplusplus >= 201103L && defined(__has_feature) +#if __has_feature(cxx_attributes) && defined(__has_warning) +#if __has_warning("-Wimplicit-fallthrough") +#define FALLTHROUGH [[clang::fallthrough]] +#endif +#endif +#endif + +#ifndef FALLTHROUGH +#define FALLTHROUGH +#endif + #endif // TYPEDEFS_H diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index e13164d50f..69581e4115 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -90,7 +90,7 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) { actions.write[actions.size() - 1].last_tick = ticks; merge_mode = p_mode; - + merging = true; } else { Action new_action; @@ -250,6 +250,11 @@ void UndoRedo::commit_action() { if (action_level > 0) return; //still nested + if (merging) { + version--; + merging = false; + } + commiting++; redo(); // perform action commiting--; @@ -396,6 +401,7 @@ UndoRedo::UndoRedo() { action_level = 0; current_action = -1; merge_mode = MERGE_DISABLE; + merging = false; callback = NULL; callback_ud = NULL; diff --git a/core/undo_redo.h b/core/undo_redo.h index b626149ce6..6293e77acc 100644 --- a/core/undo_redo.h +++ b/core/undo_redo.h @@ -80,6 +80,7 @@ private: int current_action; int action_level; MergeMode merge_mode; + bool merging; uint64_t version; void _pop_history_tail(); diff --git a/core/ustring.h b/core/ustring.h index cb3d87378a..9288c1526e 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -97,6 +97,10 @@ public: _FORCE_INLINE_ CharString() {} _FORCE_INLINE_ CharString(const CharString &p_str) { _cowdata._ref(p_str._cowdata); } + _FORCE_INLINE_ CharString operator=(const CharString &p_str) { + _cowdata._ref(p_str._cowdata); + return *this; + } bool operator<(const CharString &p_right) const; CharString &operator+=(char p_char); @@ -339,6 +343,10 @@ public: _FORCE_INLINE_ String() {} _FORCE_INLINE_ String(const String &p_str) { _cowdata._ref(p_str._cowdata); } + String operator=(const String &p_str) { + _cowdata._ref(p_str._cowdata); + return *this; + } String(const char *p_str); String(const CharType *p_str, int p_clip_to_len = -1); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 25a0f3957c..9ef7b7e7e6 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -773,6 +773,8 @@ struct _VariantCall { VCALL_PTR0R(Basis, get_orthogonal_index); VCALL_PTR0R(Basis, orthonormalized); VCALL_PTR2R(Basis, slerp); + VCALL_PTR2R(Basis, is_equal_approx); + VCALL_PTR0R(Basis, get_rotation_quat); VCALL_PTR0R(Transform, inverse); VCALL_PTR0R(Transform, affine_inverse); @@ -1842,6 +1844,8 @@ void register_variant_methods() { ADDFUNC1R(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray()); ADDFUNC0R(BASIS, INT, Basis, get_orthogonal_index, varray()); ADDFUNC2R(BASIS, BASIS, Basis, slerp, BASIS, "b", REAL, "t", varray()); + ADDFUNC2R(BASIS, BOOL, Basis, is_equal_approx, BASIS, "b", REAL, "epsilon", varray(CMP_EPSILON)); + ADDFUNC0R(BASIS, QUAT, Basis, get_rotation_quat, varray()); ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, inverse, varray()); ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, affine_inverse, varray()); @@ -1923,9 +1927,9 @@ void register_variant_methods() { _VariantCall::add_variant_constant(Variant::TRANSFORM, "IDENTITY", identity_transform); transform_x.set(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0); _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_X", transform_x); - transform_x.set(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0); + transform_y.set(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0); _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Y", transform_y); - transform_x.set(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0); + transform_z.set(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0); _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Z", transform_z); _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_YZ", Plane(Vector3(1, 0, 0), 0)); |