summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bind/core_bind.cpp30
-rw-r--r--core/bind/core_bind.h8
-rw-r--r--core/class_db.cpp5
-rw-r--r--core/class_db.h1
-rw-r--r--core/io/file_access_pack.cpp2
-rw-r--r--core/io/logger.cpp2
-rw-r--r--core/io/marshalls.cpp41
-rw-r--r--core/io/marshalls.h4
-rw-r--r--core/io/multiplayer_api.cpp32
-rw-r--r--core/io/multiplayer_api.h4
-rw-r--r--core/io/packet_peer.cpp18
-rw-r--r--core/io/packet_peer.h7
-rw-r--r--core/io/stream_peer.cpp14
-rw-r--r--core/io/stream_peer.h4
-rw-r--r--core/math/audio_frame.h6
-rw-r--r--core/math/basis.cpp26
-rw-r--r--core/math/basis.h3
-rw-r--r--core/math/expression.cpp12
-rw-r--r--core/math/geometry.cpp2
-rw-r--r--core/math/geometry.h6
-rw-r--r--core/math/math_funcs.h4
-rw-r--r--core/math/quat.h8
-rw-r--r--core/math/random_number_generator.cpp1
-rw-r--r--core/math/random_number_generator.h2
-rw-r--r--core/math/random_pcg.cpp3
-rw-r--r--core/math/random_pcg.h15
-rw-r--r--core/os/main_loop.h28
-rw-r--r--core/os/midi_driver.cpp5
-rw-r--r--core/packed_data_container.cpp6
-rw-r--r--core/project_settings.cpp10
-rw-r--r--core/script_language.h2
-rw-r--r--core/typedefs.h29
-rw-r--r--core/undo_redo.cpp8
-rw-r--r--core/undo_redo.h1
-rw-r--r--core/ustring.h8
-rw-r--r--core/variant_call.cpp8
36 files changed, 242 insertions, 123 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index f5dbacd62d..67de156fc3 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -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++;
}
@@ -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);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 803743bc93..1c26d9b144 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -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);
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/logger.cpp b/core/io/logger.cpp
index eeb82bfce4..9175f6a262 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -39,7 +39,7 @@
// va_copy, otherwise you have to use the internal version (__va_copy).
#if !defined(va_copy)
#if defined(__GNUC__)
-#define va_copy(d, s) __va_copy(d, s)
+#define va_copy(d, s) __va_copy((d), (s))
#else
#define va_copy(d, s) ((d) = (s))
#endif
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..708054e4ab 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -164,10 +164,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:
@@ -696,8 +696,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 +710,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 +725,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/geometry.cpp b/core/math/geometry.cpp
index 194a6f6352..a84b5a16c7 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -515,7 +515,7 @@ static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, i
Vector3(1,1,1),
};
*/
-#define vert(m_idx) Vector3((m_idx & 4) >> 2, (m_idx & 2) >> 1, m_idx & 1)
+#define vert(m_idx) Vector3(((m_idx)&4) >> 2, ((m_idx)&2) >> 1, (m_idx)&1)
static const uint8_t indices[6][4] = {
{ 7, 6, 4, 5 },
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..6ac6839827 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -249,11 +249,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 03514466c0..660139b90a 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -137,7 +137,7 @@ T *_nullptr() {
/** Generic swap template */
#ifndef SWAP
-#define SWAP(m_x, m_y) __swap_tmpl(m_x, m_y)
+#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
template <class T>
inline void __swap_tmpl(T &x, T &y) {
@@ -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));