summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/core_bind.cpp6
-rw-r--r--core/core_bind.h4
-rw-r--r--core/crypto/crypto.cpp39
-rw-r--r--core/crypto/crypto.h34
-rw-r--r--core/extension/extension_api_dump.cpp15
-rw-r--r--core/extension/gdextension_interface.cpp8
-rw-r--r--core/extension/gdextension_interface.h1
-rw-r--r--core/input/input_event.cpp13
-rw-r--r--core/io/dtls_server.cpp2
-rw-r--r--core/io/dtls_server.h2
-rw-r--r--core/io/http_client.cpp2
-rw-r--r--core/io/http_client.h3
-rw-r--r--core/io/http_client_tcp.cpp33
-rw-r--r--core/io/http_client_tcp.h7
-rw-r--r--core/io/image.cpp46
-rw-r--r--core/io/image.h18
-rw-r--r--core/io/packet_peer_dtls.cpp2
-rw-r--r--core/io/packet_peer_dtls.h2
-rw-r--r--core/io/resource.cpp36
-rw-r--r--core/io/stream_peer_tls.cpp20
-rw-r--r--core/io/stream_peer_tls.h11
-rw-r--r--core/math/a_star.cpp14
-rw-r--r--core/math/a_star_grid_2d.cpp16
-rw-r--r--core/math/a_star_grid_2d.h2
-rw-r--r--core/math/bvh.h2
-rw-r--r--core/math/geometry_3d.cpp2
-rw-r--r--core/math/transform_2d.cpp39
-rw-r--r--core/object/make_virtuals.py4
-rw-r--r--core/object/object.cpp4
-rw-r--r--core/object/object.h10
-rw-r--r--core/os/keyboard.h2
-rw-r--r--core/os/mutex.h5
-rw-r--r--core/os/os.cpp10
-rw-r--r--core/os/os.h8
-rw-r--r--core/os/rw_lock.h38
-rw-r--r--core/os/semaphore.h29
-rw-r--r--core/register_core_types.cpp1
-rw-r--r--core/string/ustring.cpp20
-rw-r--r--core/string/ustring.h1
-rw-r--r--core/variant/array.cpp10
-rw-r--r--core/variant/array.h2
-rw-r--r--core/variant/dictionary.cpp10
-rw-r--r--core/variant/dictionary.h2
-rw-r--r--core/variant/variant.cpp40
-rw-r--r--core/variant/variant.h1
-rw-r--r--core/variant/variant_call.cpp6
-rw-r--r--core/variant/variant_utility.cpp7
47 files changed, 381 insertions, 208 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 96e1da9dde..9de901754a 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1105,8 +1105,8 @@ void Semaphore::wait() {
semaphore.wait();
}
-Error Semaphore::try_wait() {
- return semaphore.try_wait() ? OK : ERR_BUSY;
+bool Semaphore::try_wait() {
+ return semaphore.try_wait();
}
void Semaphore::post() {
@@ -1125,7 +1125,7 @@ void Mutex::lock() {
mutex.lock();
}
-Error Mutex::try_lock() {
+bool Mutex::try_lock() {
return mutex.try_lock();
}
diff --git a/core/core_bind.h b/core/core_bind.h
index c0c87fd009..8852463234 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -361,7 +361,7 @@ class Mutex : public RefCounted {
public:
void lock();
- Error try_lock();
+ bool try_lock();
void unlock();
};
@@ -373,7 +373,7 @@ class Semaphore : public RefCounted {
public:
void wait();
- Error try_wait();
+ bool try_wait();
void post();
};
diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp
index cbb18a277f..939c1c298f 100644
--- a/core/crypto/crypto.cpp
+++ b/core/crypto/crypto.cpp
@@ -65,6 +65,45 @@ void X509Certificate::_bind_methods() {
ClassDB::bind_method(D_METHOD("load", "path"), &X509Certificate::load);
}
+/// TLSOptions
+
+Ref<TLSOptions> TLSOptions::client(Ref<X509Certificate> p_trusted_chain, const String &p_common_name_override) {
+ Ref<TLSOptions> opts;
+ opts.instantiate();
+ opts->trusted_ca_chain = p_trusted_chain;
+ opts->common_name = p_common_name_override;
+ opts->verify_mode = TLS_VERIFY_FULL;
+ return opts;
+}
+
+Ref<TLSOptions> TLSOptions::client_unsafe(Ref<X509Certificate> p_trusted_chain) {
+ Ref<TLSOptions> opts;
+ opts.instantiate();
+ opts->trusted_ca_chain = p_trusted_chain;
+ if (p_trusted_chain.is_null()) {
+ opts->verify_mode = TLS_VERIFY_NONE;
+ } else {
+ opts->verify_mode = TLS_VERIFY_CERT;
+ }
+ return opts;
+}
+
+Ref<TLSOptions> TLSOptions::server(Ref<CryptoKey> p_own_key, Ref<X509Certificate> p_own_certificate) {
+ Ref<TLSOptions> opts;
+ opts.instantiate();
+ opts->server_mode = true;
+ opts->own_certificate = p_own_certificate;
+ opts->private_key = p_own_key;
+ opts->verify_mode = TLS_VERIFY_NONE;
+ return opts;
+}
+
+void TLSOptions::_bind_methods() {
+ ClassDB::bind_static_method("TLSOptions", D_METHOD("client", "trusted_chain", "common_name_override"), &TLSOptions::client, DEFVAL(Ref<X509Certificate>()), DEFVAL(String()));
+ ClassDB::bind_static_method("TLSOptions", D_METHOD("client_unsafe", "trusted_chain"), &TLSOptions::client_unsafe, DEFVAL(Ref<X509Certificate>()));
+ ClassDB::bind_static_method("TLSOptions", D_METHOD("server", "key", "certificate"), &TLSOptions::server);
+}
+
/// HMACContext
void HMACContext::_bind_methods() {
diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h
index 981f67883c..999fe076d6 100644
--- a/core/crypto/crypto.h
+++ b/core/crypto/crypto.h
@@ -67,6 +67,40 @@ public:
virtual Error save(String p_path) = 0;
};
+class TLSOptions : public RefCounted {
+ GDCLASS(TLSOptions, RefCounted);
+
+public:
+ enum TLSVerifyMode {
+ TLS_VERIFY_NONE = 0,
+ TLS_VERIFY_CERT = 1,
+ TLS_VERIFY_FULL = 2,
+ };
+
+private:
+ bool server_mode = false;
+ String common_name;
+ TLSVerifyMode verify_mode = TLS_VERIFY_FULL;
+ Ref<X509Certificate> trusted_ca_chain;
+ Ref<X509Certificate> own_certificate;
+ Ref<CryptoKey> private_key;
+
+protected:
+ static void _bind_methods();
+
+public:
+ static Ref<TLSOptions> client(Ref<X509Certificate> p_trusted_chain = Ref<X509Certificate>(), const String &p_common_name_override = String());
+ static Ref<TLSOptions> client_unsafe(Ref<X509Certificate> p_trusted_chain);
+ static Ref<TLSOptions> server(Ref<CryptoKey> p_own_key, Ref<X509Certificate> p_own_certificate);
+
+ TLSVerifyMode get_verify_mode() const { return verify_mode; }
+ String get_common_name() const { return common_name; }
+ Ref<X509Certificate> get_trusted_ca_chain() const { return trusted_ca_chain; }
+ Ref<X509Certificate> get_own_certificate() const { return own_certificate; }
+ Ref<CryptoKey> get_private_key() const { return private_key; }
+ bool is_server() const { return server_mode; }
+};
+
class HMACContext : public RefCounted {
GDCLASS(HMACContext, RefCounted);
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 7be14b741d..e26ead6d8c 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -82,6 +82,11 @@ static String get_property_info_type_name(const PropertyInfo &p_info) {
return get_builtin_or_variant_type_name(p_info.type);
}
+static String get_type_meta_name(const GodotTypeInfo::Metadata metadata) {
+ static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" };
+ return argmeta[metadata];
+}
+
Dictionary GDExtensionAPIDump::generate_extension_api() {
Dictionary api_dump;
@@ -840,6 +845,10 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d3["type"] = get_property_info_type_name(pinfo);
+ if (mi.get_argument_meta(i) > 0) {
+ d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)mi.get_argument_meta(i));
+ }
+
if (i == -1) {
d2["return_value"] = d3;
} else {
@@ -884,8 +893,7 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d3["type"] = get_property_info_type_name(pinfo);
if (method->get_argument_meta(i) > 0) {
- static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" };
- d3["meta"] = argmeta[method->get_argument_meta(i)];
+ d3["meta"] = get_type_meta_name(method->get_argument_meta(i));
}
if (i >= 0 && i >= (method->get_argument_count() - default_args.size())) {
@@ -929,6 +937,9 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
Dictionary d3;
d3["name"] = F.arguments[i].name;
d3["type"] = get_property_info_type_name(F.arguments[i]);
+ if (F.get_argument_meta(i) > 0) {
+ d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)F.get_argument_meta(i));
+ }
arguments.push_back(d3);
}
if (arguments.size()) {
diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp
index a9063c8b27..63ed60a710 100644
--- a/core/extension/gdextension_interface.cpp
+++ b/core/extension/gdextension_interface.cpp
@@ -856,6 +856,13 @@ static GDExtensionVariantPtr gdextension_array_operator_index_const(GDExtensionC
return (GDExtensionVariantPtr)&self->operator[](p_index);
}
+void gdextension_array_set_typed(GDExtensionTypePtr p_self, uint32_t p_type, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstVariantPtr p_script) {
+ Array *self = reinterpret_cast<Array *>(p_self);
+ const StringName *class_name = reinterpret_cast<const StringName *>(p_class_name);
+ const Variant *script = reinterpret_cast<const Variant *>(p_script);
+ self->set_typed(p_type, *class_name, *script);
+}
+
/* Dictionary functions */
static GDExtensionVariantPtr gdextension_dictionary_operator_index(GDExtensionTypePtr p_self, GDExtensionConstVariantPtr p_key) {
@@ -1129,6 +1136,7 @@ void gdextension_setup_interface(GDExtensionInterface *p_interface) {
gde_interface.array_operator_index = gdextension_array_operator_index;
gde_interface.array_operator_index_const = gdextension_array_operator_index_const;
+ gde_interface.array_set_typed = gdextension_array_set_typed;
/* Dictionary functions */
diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h
index 6e5dee8265..7f8f7374e9 100644
--- a/core/extension/gdextension_interface.h
+++ b/core/extension/gdextension_interface.h
@@ -551,6 +551,7 @@ typedef struct {
GDExtensionVariantPtr (*array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr
GDExtensionVariantPtr (*array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr
+ void (*array_set_typed)(GDExtensionTypePtr p_self, uint32_t p_type, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstVariantPtr p_script); // p_self should be an Array ptr
/* Dictionary functions */
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 74c0812f43..5a9ec74184 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -1499,7 +1499,18 @@ bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool p_exact
}
String InputEventAction::as_text() const {
- return vformat(RTR("Input Action %s was %s"), action, pressed ? "pressed" : "released");
+ const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(action);
+ if (!events) {
+ return String();
+ }
+
+ for (const Ref<InputEvent> &E : *events) {
+ if (E.is_valid()) {
+ return E->as_text();
+ }
+ }
+
+ return String();
}
String InputEventAction::to_string() {
diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp
index c542e394a1..07d62d3a8d 100644
--- a/core/io/dtls_server.cpp
+++ b/core/io/dtls_server.cpp
@@ -48,6 +48,6 @@ bool DTLSServer::is_available() {
}
void DTLSServer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("setup", "key", "certificate", "chain"), &DTLSServer::setup, DEFVAL(Ref<X509Certificate>()));
+ ClassDB::bind_method(D_METHOD("setup", "server_options"), &DTLSServer::setup);
ClassDB::bind_method(D_METHOD("take_connection", "udp_peer"), &DTLSServer::take_connection);
}
diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h
index e749e6968b..f3fbde3c15 100644
--- a/core/io/dtls_server.h
+++ b/core/io/dtls_server.h
@@ -47,7 +47,7 @@ public:
static bool is_available();
static DTLSServer *create();
- virtual Error setup(Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>()) = 0;
+ virtual Error setup(Ref<TLSOptions> p_options) = 0;
virtual void stop() = 0;
virtual Ref<PacketPeerDTLS> take_connection(Ref<PacketPeerUDP> p_peer) = 0;
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 829abdc614..190edbfb82 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -138,7 +138,7 @@ PackedStringArray HTTPClient::_get_response_headers() {
}
void HTTPClient::_bind_methods() {
- ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_tls", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(-1), DEFVAL(false), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "tls_options"), &HTTPClient::connect_to_host, DEFVAL(-1), DEFVAL(Ref<TLSOptions>()));
ClassDB::bind_method(D_METHOD("set_connection", "connection"), &HTTPClient::set_connection);
ClassDB::bind_method(D_METHOD("get_connection"), &HTTPClient::get_connection);
ClassDB::bind_method(D_METHOD("request_raw", "method", "url", "headers", "body"), &HTTPClient::_request_raw);
diff --git a/core/io/http_client.h b/core/io/http_client.h
index 853ea7f472..9e018182e3 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -31,6 +31,7 @@
#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H
+#include "core/crypto/crypto.h"
#include "core/io/ip.h"
#include "core/io/stream_peer.h"
#include "core/io/stream_peer_tcp.h"
@@ -168,7 +169,7 @@ public:
Error verify_headers(const Vector<String> &p_headers);
virtual Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_size) = 0;
- virtual Error connect_to_host(const String &p_host, int p_port = -1, bool p_tls = false, bool p_verify_host = true) = 0;
+ virtual Error connect_to_host(const String &p_host, int p_port = -1, Ref<TLSOptions> p_tls_options = Ref<TLSOptions>()) = 0;
virtual void set_connection(const Ref<StreamPeer> &p_connection) = 0;
virtual Ref<StreamPeer> get_connection() const = 0;
diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp
index 5cdb13fa06..3788fa501e 100644
--- a/core/io/http_client_tcp.cpp
+++ b/core/io/http_client_tcp.cpp
@@ -39,29 +39,31 @@ HTTPClient *HTTPClientTCP::_create_func() {
return memnew(HTTPClientTCP);
}
-Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_tls, bool p_verify_host) {
+Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, Ref<TLSOptions> p_options) {
close();
conn_port = p_port;
conn_host = p_host;
+ tls_options = p_options;
ip_candidates.clear();
- tls = p_tls;
- tls_verify_host = p_verify_host;
-
String host_lower = conn_host.to_lower();
if (host_lower.begins_with("http://")) {
conn_host = conn_host.substr(7, conn_host.length() - 7);
+ tls_options.unref();
} else if (host_lower.begins_with("https://")) {
- tls = true;
+ if (tls_options.is_null()) {
+ tls_options = TLSOptions::client();
+ }
conn_host = conn_host.substr(8, conn_host.length() - 8);
}
+ ERR_FAIL_COND_V(tls_options.is_valid() && tls_options->is_server(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(conn_host.length() < HOST_MIN_LEN, ERR_INVALID_PARAMETER);
if (conn_port < 0) {
- if (tls) {
+ if (tls_options.is_valid()) {
conn_port = PORT_HTTPS;
} else {
conn_port = PORT_HTTP;
@@ -70,11 +72,11 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_tl
connection = tcp_connection;
- if (tls && https_proxy_port != -1) {
+ if (tls_options.is_valid() && https_proxy_port != -1) {
proxy_client.instantiate(); // Needs proxy negotiation.
server_host = https_proxy_host;
server_port = https_proxy_port;
- } else if (!tls && http_proxy_port != -1) {
+ } else if (tls_options.is_null() && http_proxy_port != -1) {
server_host = http_proxy_host;
server_port = http_proxy_port;
} else {
@@ -107,7 +109,7 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_tl
void HTTPClientTCP::set_connection(const Ref<StreamPeer> &p_connection) {
ERR_FAIL_COND_MSG(p_connection.is_null(), "Connection is not a reference to a valid StreamPeer object.");
- if (tls) {
+ if (tls_options.is_valid()) {
ERR_FAIL_NULL_MSG(Object::cast_to<StreamPeerTLS>(p_connection.ptr()),
"Connection is not a reference to a valid StreamPeerTLS object.");
}
@@ -156,7 +158,7 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector<
}
String uri = p_url;
- if (!tls && http_proxy_port != -1) {
+ if (tls_options.is_null() && http_proxy_port != -1) {
uri = vformat("http://%s:%d%s", conn_host, conn_port, p_url);
}
@@ -181,7 +183,7 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector<
}
}
if (add_host) {
- if ((tls && conn_port == PORT_HTTPS) || (!tls && conn_port == PORT_HTTP)) {
+ if ((tls_options.is_valid() && conn_port == PORT_HTTPS) || (tls_options.is_null() && conn_port == PORT_HTTP)) {
// Don't append the standard ports.
request += "Host: " + conn_host + "\r\n";
} else {
@@ -316,7 +318,7 @@ Error HTTPClientTCP::poll() {
return OK;
} break;
case StreamPeerTCP::STATUS_CONNECTED: {
- if (tls && proxy_client.is_valid()) {
+ if (tls_options.is_valid() && proxy_client.is_valid()) {
Error err = proxy_client->poll();
if (err == ERR_UNCONFIGURED) {
proxy_client->set_connection(tcp_connection);
@@ -357,13 +359,12 @@ Error HTTPClientTCP::poll() {
return ERR_CANT_CONNECT;
} break;
}
- } else if (tls) {
+ } else if (tls_options.is_valid()) {
Ref<StreamPeerTLS> tls_conn;
if (!handshaking) {
// Connect the StreamPeerTLS and start handshaking.
tls_conn = Ref<StreamPeerTLS>(StreamPeerTLS::create());
- tls_conn->set_blocking_handshake_enabled(false);
- Error err = tls_conn->connect_to_stream(tcp_connection, tls_verify_host, conn_host);
+ Error err = tls_conn->connect_to_stream(tcp_connection, conn_host, tls_options);
if (err != OK) {
close();
status = STATUS_TLS_HANDSHAKE_ERROR;
@@ -421,7 +422,7 @@ Error HTTPClientTCP::poll() {
case STATUS_BODY:
case STATUS_CONNECTED: {
// Check if we are still connected.
- if (tls) {
+ if (tls_options.is_valid()) {
Ref<StreamPeerTLS> tmp = connection;
tmp->poll();
if (tmp->get_status() != StreamPeerTLS::STATUS_CONNECTED) {
diff --git a/core/io/http_client_tcp.h b/core/io/http_client_tcp.h
index 97ac2d76a7..6060c975bc 100644
--- a/core/io/http_client_tcp.h
+++ b/core/io/http_client_tcp.h
@@ -33,6 +33,8 @@
#include "http_client.h"
+#include "core/crypto/crypto.h"
+
class HTTPClientTCP : public HTTPClient {
private:
Status status = STATUS_DISCONNECTED;
@@ -46,11 +48,10 @@ private:
String http_proxy_host;
int https_proxy_port = -1; // Proxy server for https requests.
String https_proxy_host;
- bool tls = false;
- bool tls_verify_host = false;
bool blocking = false;
bool handshaking = false;
bool head_request = false;
+ Ref<TLSOptions> tls_options;
Vector<uint8_t> response_str;
@@ -79,7 +80,7 @@ public:
Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_size) override;
- Error connect_to_host(const String &p_host, int p_port = -1, bool p_tls = false, bool p_verify_host = true) override;
+ Error connect_to_host(const String &p_host, int p_port = -1, Ref<TLSOptions> p_tls_options = Ref<TLSOptions>()) override;
void set_connection(const Ref<StreamPeer> &p_connection) override;
Ref<StreamPeer> get_connection() const override;
void close() override;
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 9408a9c103..736a3ec82e 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -78,6 +78,10 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
"ETC2_RGB8A1",
"ETC2_RA_AS_RG",
"FORMAT_DXT5_RA_AS_RG",
+ "ASTC_4x4",
+ "ASTC_4x4_HDR",
+ "ASTC_8x8",
+ "ASTC_8x8_HDR",
};
SavePNGFunc Image::save_png_func = nullptr;
@@ -2187,16 +2191,16 @@ void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Forma
int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
if (unlikely(p_data.size() != size)) {
- String description_mipmaps;
+ String description_mipmaps = get_format_name(p_format) + " ";
if (p_use_mipmaps) {
const int num_mipmaps = get_image_required_mipmaps(p_width, p_height, p_format);
if (num_mipmaps != 1) {
- description_mipmaps = vformat("with %d mipmaps", num_mipmaps);
+ description_mipmaps += vformat("with %d mipmaps", num_mipmaps);
} else {
- description_mipmaps = "with 1 mipmap";
+ description_mipmaps += "with 1 mipmap";
}
} else {
- description_mipmaps = "without mipmaps";
+ description_mipmaps += "without mipmaps";
}
const String description = vformat("%dx%dx%d (%s)", p_width, p_height, get_format_pixel_size(p_format), description_mipmaps);
ERR_FAIL_MSG(vformat("Expected Image data size of %s = %d bytes, got %d bytes instead.", description, size, p_data.size()));
@@ -2618,35 +2622,35 @@ Error Image::decompress() {
return OK;
}
-Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality, ASTCFormat p_astc_format) {
+Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p_astc_format) {
ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode.");
ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source.");
- return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality, p_astc_format);
+ return compress_from_channels(p_mode, detect_used_channels(p_source), p_astc_format);
}
-Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality, ASTCFormat p_astc_format) {
+Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) {
ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA);
switch (p_mode) {
case COMPRESS_S3TC: {
ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE);
- _image_compress_bc_func(this, p_lossy_quality, p_channels);
+ _image_compress_bc_func(this, p_channels);
} break;
case COMPRESS_ETC: {
ERR_FAIL_COND_V(!_image_compress_etc1_func, ERR_UNAVAILABLE);
- _image_compress_etc1_func(this, p_lossy_quality);
+ _image_compress_etc1_func(this);
} break;
case COMPRESS_ETC2: {
ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE);
- _image_compress_etc2_func(this, p_lossy_quality, p_channels);
+ _image_compress_etc2_func(this, p_channels);
} break;
case COMPRESS_BPTC: {
ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
- _image_compress_bptc_func(this, p_lossy_quality, p_channels);
+ _image_compress_bptc_func(this, p_channels);
} break;
case COMPRESS_ASTC: {
ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
- _image_compress_astc_func(this, p_lossy_quality, p_astc_format);
+ _image_compress_astc_func(this, p_astc_format);
} break;
case COMPRESS_MAX: {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
@@ -3000,11 +3004,11 @@ ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr;
-void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nullptr;
-void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr;
-void (*Image::_image_compress_etc1_func)(Image *, float) = nullptr;
-void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = nullptr;
-void (*Image::_image_compress_astc_func)(Image *, float, Image::ASTCFormat) = nullptr;
+void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr;
+void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr;
+void (*Image::_image_compress_etc1_func)(Image *) = nullptr;
+void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr;
+void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr;
void (*Image::_image_decompress_bc)(Image *) = nullptr;
void (*Image::_image_decompress_bptc)(Image *) = nullptr;
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
@@ -3426,8 +3430,8 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible);
ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC));
- ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4));
- ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality", "astc_format"), &Image::compress_from_channels, DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4));
+ ClassDB::bind_method(D_METHOD("compress", "mode", "source", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(ASTC_FORMAT_4x4));
+ ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "astc_format"), &Image::compress_from_channels, DEFVAL(ASTC_FORMAT_4x4));
ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress);
ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed);
@@ -3547,11 +3551,11 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(ASTC_FORMAT_8x8);
}
-void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)) {
+void Image::set_compress_bc_func(void (*p_compress_func)(Image *, UsedChannels)) {
_image_compress_bc_func = p_compress_func;
}
-void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)) {
+void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, UsedChannels)) {
_image_compress_bptc_func = p_compress_func;
}
diff --git a/core/io/image.h b/core/io/image.h
index 29ceb9478f..8e353a8bb7 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -149,11 +149,11 @@ public:
static ImageMemLoadFunc _tga_mem_loader_func;
static ImageMemLoadFunc _bmp_mem_loader_func;
- static void (*_image_compress_bc_func)(Image *, float, UsedChannels p_channels);
- static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels);
- static void (*_image_compress_etc1_func)(Image *, float);
- static void (*_image_compress_etc2_func)(Image *, float, UsedChannels p_channels);
- static void (*_image_compress_astc_func)(Image *, float, ASTCFormat p_format);
+ static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels);
+ static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels);
+ static void (*_image_compress_etc1_func)(Image *);
+ static void (*_image_compress_etc2_func)(Image *, UsedChannels p_channels);
+ static void (*_image_compress_astc_func)(Image *, ASTCFormat p_format);
static void (*_image_decompress_bc)(Image *);
static void (*_image_decompress_bptc)(Image *);
@@ -368,8 +368,8 @@ public:
COMPRESS_SOURCE_MAX,
};
- Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
- Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
+ Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
+ Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
Error decompress();
bool is_compressed() const;
@@ -391,8 +391,8 @@ public:
Rect2i get_used_rect() const;
Ref<Image> get_region(const Rect2i &p_area) const;
- static void set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels));
- static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels));
+ static void set_compress_bc_func(void (*p_compress_func)(Image *, UsedChannels));
+ static void set_compress_bptc_func(void (*p_compress_func)(Image *, UsedChannels));
static String get_format_name(Format p_format);
Error load_png_from_buffer(const Vector<uint8_t> &p_array);
diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp
index c0998f10bc..18bef3ff3c 100644
--- a/core/io/packet_peer_dtls.cpp
+++ b/core/io/packet_peer_dtls.cpp
@@ -48,7 +48,7 @@ bool PacketPeerDTLS::is_available() {
void PacketPeerDTLS::_bind_methods() {
ClassDB::bind_method(D_METHOD("poll"), &PacketPeerDTLS::poll);
- ClassDB::bind_method(D_METHOD("connect_to_peer", "packet_peer", "validate_certs", "for_hostname", "valid_certificate"), &PacketPeerDTLS::connect_to_peer, DEFVAL(true), DEFVAL(String()), DEFVAL(Ref<X509Certificate>()));
+ ClassDB::bind_method(D_METHOD("connect_to_peer", "packet_peer", "hostname", "client_options"), &PacketPeerDTLS::connect_to_peer, DEFVAL(Ref<TLSOptions>()));
ClassDB::bind_method(D_METHOD("get_status"), &PacketPeerDTLS::get_status);
ClassDB::bind_method(D_METHOD("disconnect_from_peer"), &PacketPeerDTLS::disconnect_from_peer);
diff --git a/core/io/packet_peer_dtls.h b/core/io/packet_peer_dtls.h
index 5ba1faed7c..3990a851f7 100644
--- a/core/io/packet_peer_dtls.h
+++ b/core/io/packet_peer_dtls.h
@@ -53,7 +53,7 @@ public:
};
virtual void poll() = 0;
- virtual Error connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_validate_certs = true, const String &p_for_hostname = String(), Ref<X509Certificate> p_ca_certs = Ref<X509Certificate>()) = 0;
+ virtual Error connect_to_peer(Ref<PacketPeerUDP> p_base, const String &p_hostname, Ref<TLSOptions> p_options = Ref<TLSOptions>()) = 0;
virtual void disconnect_from_peer() = 0;
virtual Status get_status() const = 0;
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index e44bbc246b..4abcbffb61 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -260,15 +260,35 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const {
}
Variant p = get(E.name);
- if ((p.get_type() == Variant::DICTIONARY || p.get_type() == Variant::ARRAY)) {
- r->set(E.name, p.duplicate(p_subresources));
- } else if (p.get_type() == Variant::OBJECT && !(E.usage & PROPERTY_USAGE_NEVER_DUPLICATE) && (p_subresources || (E.usage & PROPERTY_USAGE_ALWAYS_DUPLICATE))) {
- Ref<Resource> sr = p;
- if (sr.is_valid()) {
- r->set(E.name, sr->duplicate(p_subresources));
+ switch (p.get_type()) {
+ case Variant::Type::DICTIONARY:
+ case Variant::Type::ARRAY:
+ case Variant::Type::PACKED_BYTE_ARRAY:
+ case Variant::Type::PACKED_COLOR_ARRAY:
+ case Variant::Type::PACKED_INT32_ARRAY:
+ case Variant::Type::PACKED_INT64_ARRAY:
+ case Variant::Type::PACKED_FLOAT32_ARRAY:
+ case Variant::Type::PACKED_FLOAT64_ARRAY:
+ case Variant::Type::PACKED_STRING_ARRAY:
+ case Variant::Type::PACKED_VECTOR2_ARRAY:
+ case Variant::Type::PACKED_VECTOR3_ARRAY: {
+ r->set(E.name, p.duplicate(p_subresources));
+ } break;
+
+ case Variant::Type::OBJECT: {
+ if (!(E.usage & PROPERTY_USAGE_NEVER_DUPLICATE) && (p_subresources || (E.usage & PROPERTY_USAGE_ALWAYS_DUPLICATE))) {
+ Ref<Resource> sr = p;
+ if (sr.is_valid()) {
+ r->set(E.name, sr->duplicate(p_subresources));
+ }
+ } else {
+ r->set(E.name, p);
+ }
+ } break;
+
+ default: {
+ r->set(E.name, p);
}
- } else {
- r->set(E.name, p);
}
}
diff --git a/core/io/stream_peer_tls.cpp b/core/io/stream_peer_tls.cpp
index 71fadd1d30..69877974e6 100644
--- a/core/io/stream_peer_tls.cpp
+++ b/core/io/stream_peer_tls.cpp
@@ -41,31 +41,17 @@ StreamPeerTLS *StreamPeerTLS::create() {
return nullptr;
}
-bool StreamPeerTLS::available = false;
-
bool StreamPeerTLS::is_available() {
- return available;
-}
-
-void StreamPeerTLS::set_blocking_handshake_enabled(bool p_enabled) {
- blocking_handshake = p_enabled;
-}
-
-bool StreamPeerTLS::is_blocking_handshake_enabled() const {
- return blocking_handshake;
+ return _create != nullptr;
}
void StreamPeerTLS::_bind_methods() {
ClassDB::bind_method(D_METHOD("poll"), &StreamPeerTLS::poll);
- ClassDB::bind_method(D_METHOD("accept_stream", "stream", "private_key", "certificate", "chain"), &StreamPeerTLS::accept_stream, DEFVAL(Ref<X509Certificate>()));
- ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "validate_certs", "for_hostname", "valid_certificate"), &StreamPeerTLS::connect_to_stream, DEFVAL(false), DEFVAL(String()), DEFVAL(Ref<X509Certificate>()));
+ ClassDB::bind_method(D_METHOD("accept_stream", "stream", "server_options"), &StreamPeerTLS::accept_stream);
+ ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "common_name", "client_options"), &StreamPeerTLS::connect_to_stream, DEFVAL(Ref<TLSOptions>()));
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTLS::get_status);
ClassDB::bind_method(D_METHOD("get_stream"), &StreamPeerTLS::get_stream);
ClassDB::bind_method(D_METHOD("disconnect_from_stream"), &StreamPeerTLS::disconnect_from_stream);
- ClassDB::bind_method(D_METHOD("set_blocking_handshake_enabled", "enabled"), &StreamPeerTLS::set_blocking_handshake_enabled);
- ClassDB::bind_method(D_METHOD("is_blocking_handshake_enabled"), &StreamPeerTLS::is_blocking_handshake_enabled);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "blocking_handshake"), "set_blocking_handshake_enabled", "is_blocking_handshake_enabled");
BIND_ENUM_CONSTANT(STATUS_DISCONNECTED);
BIND_ENUM_CONSTANT(STATUS_HANDSHAKING);
diff --git a/core/io/stream_peer_tls.h b/core/io/stream_peer_tls.h
index 6666107ad8..5894abb7a4 100644
--- a/core/io/stream_peer_tls.h
+++ b/core/io/stream_peer_tls.h
@@ -41,10 +41,6 @@ protected:
static StreamPeerTLS *(*_create)();
static void _bind_methods();
- static bool available;
-
- bool blocking_handshake = true;
-
public:
enum Status {
STATUS_DISCONNECTED,
@@ -54,12 +50,9 @@ public:
STATUS_ERROR_HOSTNAME_MISMATCH
};
- void set_blocking_handshake_enabled(bool p_enabled);
- bool is_blocking_handshake_enabled() const;
-
virtual void poll() = 0;
- virtual Error accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>()) = 0;
- virtual Error connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs = false, const String &p_for_hostname = String(), Ref<X509Certificate> p_valid_cert = Ref<X509Certificate>()) = 0;
+ virtual Error accept_stream(Ref<StreamPeer> p_base, Ref<TLSOptions> p_options) = 0;
+ virtual Error connect_to_stream(Ref<StreamPeer> p_base, const String &p_common_name, Ref<TLSOptions> p_options) = 0;
virtual Status get_status() const = 0;
virtual Ref<StreamPeer> get_stream() const = 0;
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 646bdea758..f0f160940d 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -327,7 +327,7 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point) {
bool found_route = false;
- Vector<Point *> open_list;
+ LocalVector<Point *> open_list;
SortArray<Point *, SortPoints> sorter;
begin_point->g_score = 0;
@@ -335,19 +335,19 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point) {
open_list.push_back(begin_point);
while (!open_list.is_empty()) {
- Point *p = open_list[0]; // The currently processed point
+ Point *p = open_list[0]; // The currently processed point.
if (p == end_point) {
found_route = true;
break;
}
- sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list
+ sorter.pop_heap(0, open_list.size(), open_list.ptr()); // Remove the current point from the open list.
open_list.remove_at(open_list.size() - 1);
- p->closed_pass = pass; // Mark the point as closed
+ p->closed_pass = pass; // Mark the point as closed.
for (OAHashMap<int64_t, Point *>::Iterator it = p->neighbors.iter(); it.valid; it = p->neighbors.next_iter(it)) {
- Point *e = *(it.value); // The neighbor point
+ Point *e = *(it.value); // The neighbor point.
if (!e->enabled || e->closed_pass == pass) {
continue;
@@ -370,9 +370,9 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point) {
e->f_score = e->g_score + _estimate_cost(e->id, end_point->id);
if (new_point) { // The position of the new points is already known.
- sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw());
+ sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptr());
} else {
- sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw());
+ sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptr());
}
}
}
diff --git a/core/math/a_star_grid_2d.cpp b/core/math/a_star_grid_2d.cpp
index 677e609763..139dc3afb1 100644
--- a/core/math/a_star_grid_2d.cpp
+++ b/core/math/a_star_grid_2d.cpp
@@ -265,7 +265,7 @@ AStarGrid2D::Point *AStarGrid2D::_jump(Point *p_from, Point *p_to) {
return nullptr;
}
-void AStarGrid2D::_get_nbors(Point *p_point, List<Point *> &r_nbors) {
+void AStarGrid2D::_get_nbors(Point *p_point, LocalVector<Point *> &r_nbors) {
bool ts0 = false, td0 = false,
ts1 = false, td1 = false,
ts2 = false, td2 = false,
@@ -378,7 +378,7 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) {
bool found_route = false;
- Vector<Point *> open_list;
+ LocalVector<Point *> open_list;
SortArray<Point *, SortPoints> sorter;
p_begin_point->g_score = 0;
@@ -394,14 +394,14 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) {
break;
}
- sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list.
+ sorter.pop_heap(0, open_list.size(), open_list.ptr()); // Remove the current point from the open list.
open_list.remove_at(open_list.size() - 1);
p->closed_pass = pass; // Mark the point as closed.
- List<Point *> nbors;
+ LocalVector<Point *> nbors;
_get_nbors(p, nbors);
- for (List<Point *>::Element *E = nbors.front(); E; E = E->next()) {
- Point *e = E->get(); // The neighbor point.
+
+ for (Point *e : nbors) {
real_t weight_scale = 1.0;
if (jumping_enabled) {
@@ -433,9 +433,9 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) {
e->f_score = e->g_score + _estimate_cost(e->id, p_end_point->id);
if (new_point) { // The position of the new points is already known.
- sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw());
+ sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptr());
} else {
- sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw());
+ sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptr());
}
}
}
diff --git a/core/math/a_star_grid_2d.h b/core/math/a_star_grid_2d.h
index 6b9012a5e3..e4e62ec360 100644
--- a/core/math/a_star_grid_2d.h
+++ b/core/math/a_star_grid_2d.h
@@ -124,7 +124,7 @@ private: // Internal routines.
return &points[p_y][p_x];
}
- void _get_nbors(Point *p_point, List<Point *> &r_nbors);
+ void _get_nbors(Point *p_point, LocalVector<Point *> &r_nbors);
Point *_jump(Point *p_from, Point *p_to);
bool _solve(Point *p_begin_point, Point *p_end_point);
diff --git a/core/math/bvh.h b/core/math/bvh.h
index 357d483375..ea8289607e 100644
--- a/core/math/bvh.h
+++ b/core/math/bvh.h
@@ -780,7 +780,7 @@ private:
if (p_thread_safe) {
_mutex = p_mutex;
- if (_mutex->try_lock() != OK) {
+ if (!_mutex->try_lock()) {
WARN_PRINT("Info : multithread BVH access detected (benign)");
_mutex->lock();
}
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index 4786110054..590483bf20 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -151,7 +151,7 @@ void Geometry3D::MeshData::optimize_vertices() {
}
}
- for (MeshData::Edge edge : edges) {
+ for (MeshData::Edge &edge : edges) {
int a = edge.vertex_a;
int b = edge.vertex_b;
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index 910995d717..96010b4096 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -263,39 +263,12 @@ real_t Transform2D::basis_determinant() const {
return columns[0].x * columns[1].y - columns[0].y * columns[1].x;
}
-Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_c) const {
- //extract parameters
- Vector2 p1 = get_origin();
- Vector2 p2 = p_transform.get_origin();
-
- real_t r1 = get_rotation();
- real_t r2 = p_transform.get_rotation();
-
- Size2 s1 = get_scale();
- Size2 s2 = p_transform.get_scale();
-
- //slerp rotation
- Vector2 v1(Math::cos(r1), Math::sin(r1));
- Vector2 v2(Math::cos(r2), Math::sin(r2));
-
- real_t dot = v1.dot(v2);
-
- dot = CLAMP(dot, (real_t)-1.0, (real_t)1.0);
-
- Vector2 v;
-
- if (dot > 0.9995f) {
- v = v1.lerp(v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues
- } else {
- real_t angle = p_c * Math::acos(dot);
- Vector2 v3 = (v2 - v1 * dot).normalized();
- v = v1 * Math::cos(angle) + v3 * Math::sin(angle);
- }
-
- //construct matrix
- Transform2D res(v.angle(), p1.lerp(p2, p_c));
- res.scale_basis(s1.lerp(s2, p_c));
- return res;
+Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_weight) const {
+ return Transform2D(
+ Math::lerp_angle(get_rotation(), p_transform.get_rotation(), p_weight),
+ get_scale().lerp(p_transform.get_scale(), p_weight),
+ Math::lerp_angle(get_skew(), p_transform.get_skew(), p_weight),
+ get_origin().lerp(p_transform.get_origin(), p_weight));
}
void Transform2D::operator*=(const real_t p_val) {
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 0ee95835a6..18f27ae4a4 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -72,6 +72,7 @@ def generate_version(argcount, const=False, returns=False):
s = s.replace("$RVOID", "(void)r_ret;") # If required, may lead to uninitialized errors
s = s.replace("$CALLPTRRETDEF", "PtrToArg<m_ret>::EncodeT ret;")
method_info += "\tmethod_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n"
+ method_info += "\tmethod_info.return_val_metadata = GetTypeInfo<m_ret>::METADATA;\\\n"
else:
s = s.replace("$RET", "")
s = s.replace("$RVOID", "")
@@ -113,6 +114,9 @@ def generate_version(argcount, const=False, returns=False):
)
callptrargsptr += "&argval" + str(i + 1)
method_info += "\tmethod_info.arguments.push_back(GetTypeInfo<m_type" + str(i + 1) + ">::get_class_info());\\\n"
+ method_info += (
+ "\tmethod_info.arguments_metadata.push_back(GetTypeInfo<m_type" + str(i + 1) + ">::METADATA);\\\n"
+ )
if argcount:
callsiargs += "};\\\n"
diff --git a/core/object/object.cpp b/core/object/object.cpp
index a8b9e00c96..57aa1339ec 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1549,7 +1549,9 @@ void Object::_bind_methods() {
#define BIND_OBJ_CORE_METHOD(m_method) \
::ClassDB::add_virtual_method(get_class_static(), m_method, true, Vector<String>(), true);
- BIND_OBJ_CORE_METHOD(MethodInfo("_notification", PropertyInfo(Variant::INT, "what")));
+ MethodInfo notification_mi("_notification", PropertyInfo(Variant::INT, "what"));
+ notification_mi.arguments_metadata.push_back(GodotTypeInfo::Metadata::METADATA_INT_IS_INT32);
+ BIND_OBJ_CORE_METHOD(notification_mi);
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value")));
#ifdef TOOLS_ENABLED
MethodInfo miget("_get", PropertyInfo(Variant::STRING_NAME, "property"));
diff --git a/core/object/object.h b/core/object/object.h
index ec77da4ee1..5ec69a371b 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -223,6 +223,16 @@ struct MethodInfo {
int id = 0;
List<PropertyInfo> arguments;
Vector<Variant> default_arguments;
+ int return_val_metadata = 0;
+ Vector<int> arguments_metadata;
+
+ int get_argument_meta(int p_arg) const {
+ ERR_FAIL_COND_V(p_arg < -1 || p_arg > arguments.size(), 0);
+ if (p_arg == -1) {
+ return return_val_metadata;
+ }
+ return arguments_metadata.size() > p_arg ? arguments_metadata[p_arg] : 0;
+ }
inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id; }
inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); }
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 6315356510..84017e89a6 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -124,8 +124,6 @@ enum class Key {
KP_7 = SPECIAL | 0x8D,
KP_8 = SPECIAL | 0x8E,
KP_9 = SPECIAL | 0x8F,
- SUPER_L = SPECIAL | 0x40,
- SUPER_R = SPECIAL | 0x41,
MENU = SPECIAL | 0x42,
HYPER = SPECIAL | 0x43,
HELP = SPECIAL | 0x45,
diff --git a/core/os/mutex.h b/core/os/mutex.h
index c91917a9a1..ceedcb235a 100644
--- a/core/os/mutex.h
+++ b/core/os/mutex.h
@@ -31,7 +31,6 @@
#ifndef MUTEX_H
#define MUTEX_H
-#include "core/error/error_list.h"
#include "core/typedefs.h"
#include <mutex>
@@ -49,8 +48,8 @@ public:
mutex.unlock();
}
- _ALWAYS_INLINE_ Error try_lock() const {
- return mutex.try_lock() ? OK : ERR_BUSY;
+ _ALWAYS_INLINE_ bool try_lock() const {
+ return mutex.try_lock();
}
};
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 86469852e3..ef7d860d19 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -553,6 +553,16 @@ void OS::add_frame_delay(bool p_can_draw) {
}
}
+OS::PreferredTextureFormat OS::get_preferred_texture_format() const {
+#if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64)
+ return PREFERRED_TEXTURE_FORMAT_ETC2_ASTC; // By rule, ARM hardware uses ETC texture compression.
+#elif defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
+ return PREFERRED_TEXTURE_FORMAT_S3TC_BPTC; // By rule, X86 hardware prefers S3TC and derivatives.
+#else
+ return PREFERRED_TEXTURE_FORMAT_S3TC_BPTC; // Override in platform if needed.
+#endif
+}
+
OS::OS() {
singleton = this;
diff --git a/core/os/os.h b/core/os/os.h
index 436a83eae3..d77890d89d 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -290,6 +290,14 @@ public:
virtual Vector<String> get_granted_permissions() const { return Vector<String>(); }
virtual void process_and_drop_events() {}
+
+ enum PreferredTextureFormat {
+ PREFERRED_TEXTURE_FORMAT_S3TC_BPTC,
+ PREFERRED_TEXTURE_FORMAT_ETC2_ASTC
+ };
+
+ virtual PreferredTextureFormat get_preferred_texture_format() const;
+
OS();
virtual ~OS();
};
diff --git a/core/os/rw_lock.h b/core/os/rw_lock.h
index e290b7c00b..a232fcb1ce 100644
--- a/core/os/rw_lock.h
+++ b/core/os/rw_lock.h
@@ -31,7 +31,7 @@
#ifndef RW_LOCK_H
#define RW_LOCK_H
-#include "core/error/error_list.h"
+#include "core/typedefs.h"
#include <shared_mutex>
@@ -39,34 +39,34 @@ class RWLock {
mutable std::shared_timed_mutex mutex;
public:
- // Lock the rwlock, block if locked by someone else
- void read_lock() const {
+ // Lock the RWLock, block if locked by someone else.
+ _ALWAYS_INLINE_ void read_lock() const {
mutex.lock_shared();
}
- // Unlock the rwlock, let other threads continue
- void read_unlock() const {
+ // Unlock the RWLock, let other threads continue.
+ _ALWAYS_INLINE_ void read_unlock() const {
mutex.unlock_shared();
}
- // Attempt to lock the rwlock, OK on success, ERR_BUSY means it can't lock.
- Error read_try_lock() const {
- return mutex.try_lock_shared() ? OK : ERR_BUSY;
+ // Attempt to lock the RWLock for reading. True on success, false means it can't lock.
+ _ALWAYS_INLINE_ bool read_try_lock() const {
+ return mutex.try_lock_shared();
}
- // Lock the rwlock, block if locked by someone else
- void write_lock() {
+ // Lock the RWLock, block if locked by someone else.
+ _ALWAYS_INLINE_ void write_lock() {
mutex.lock();
}
- // Unlock the rwlock, let other thwrites continue
- void write_unlock() {
+ // Unlock the RWLock, let other threads continue.
+ _ALWAYS_INLINE_ void write_unlock() {
mutex.unlock();
}
- // Attempt to lock the rwlock, OK on success, ERR_BUSY means it can't lock.
- Error write_try_lock() {
- return mutex.try_lock() ? OK : ERR_BUSY;
+ // Attempt to lock the RWLock for writing. True on success, false means it can't lock.
+ _ALWAYS_INLINE_ bool write_try_lock() {
+ return mutex.try_lock();
}
};
@@ -74,11 +74,11 @@ class RWLockRead {
const RWLock &lock;
public:
- RWLockRead(const RWLock &p_lock) :
+ _ALWAYS_INLINE_ RWLockRead(const RWLock &p_lock) :
lock(p_lock) {
lock.read_lock();
}
- ~RWLockRead() {
+ _ALWAYS_INLINE_ ~RWLockRead() {
lock.read_unlock();
}
};
@@ -87,11 +87,11 @@ class RWLockWrite {
RWLock &lock;
public:
- RWLockWrite(RWLock &p_lock) :
+ _ALWAYS_INLINE_ RWLockWrite(RWLock &p_lock) :
lock(p_lock) {
lock.write_lock();
}
- ~RWLockWrite() {
+ _ALWAYS_INLINE_ ~RWLockWrite() {
lock.write_unlock();
}
};
diff --git a/core/os/semaphore.h b/core/os/semaphore.h
index 6a290f21c6..a992a4587d 100644
--- a/core/os/semaphore.h
+++ b/core/os/semaphore.h
@@ -39,32 +39,33 @@
class Semaphore {
private:
- mutable std::mutex mutex_;
- mutable std::condition_variable condition_;
- mutable unsigned long count_ = 0; // Initialized as locked.
+ mutable std::mutex mutex;
+ mutable std::condition_variable condition;
+ mutable uint32_t count = 0; // Initialized as locked.
public:
_ALWAYS_INLINE_ void post() const {
- std::lock_guard<decltype(mutex_)> lock(mutex_);
- ++count_;
- condition_.notify_one();
+ std::lock_guard lock(mutex);
+ count++;
+ condition.notify_one();
}
_ALWAYS_INLINE_ void wait() const {
- std::unique_lock<decltype(mutex_)> lock(mutex_);
- while (!count_) { // Handle spurious wake-ups.
- condition_.wait(lock);
+ std::unique_lock lock(mutex);
+ while (!count) { // Handle spurious wake-ups.
+ condition.wait(lock);
}
- --count_;
+ count--;
}
_ALWAYS_INLINE_ bool try_wait() const {
- std::lock_guard<decltype(mutex_)> lock(mutex_);
- if (count_) {
- --count_;
+ std::lock_guard lock(mutex);
+ if (count) {
+ count--;
return true;
+ } else {
+ return false;
}
- return false;
}
};
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 700174bdae..a374e7c009 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -209,6 +209,7 @@ void register_core_types() {
GDREGISTER_CLASS(AESContext);
ClassDB::register_custom_instance_class<X509Certificate>();
ClassDB::register_custom_instance_class<CryptoKey>();
+ GDREGISTER_ABSTRACT_CLASS(TLSOptions);
ClassDB::register_custom_instance_class<HMACContext>();
ClassDB::register_custom_instance_class<Crypto>();
ClassDB::register_custom_instance_class<StreamPeerTLS>();
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 9e468f7075..b34d9f3271 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -4342,6 +4342,9 @@ bool String::is_valid_html_color() const {
return Color::html_is_valid(*this);
}
+// Changes made to the set of invalid filename characters must also be reflected in the String documentation for is_valid_filename.
+static const char *invalid_filename_characters = ": / \\ ? * \" | % < >";
+
bool String::is_valid_filename() const {
String stripped = strip_edges();
if (*this != stripped) {
@@ -4352,7 +4355,22 @@ bool String::is_valid_filename() const {
return false;
}
- return !(find(":") != -1 || find("/") != -1 || find("\\") != -1 || find("?") != -1 || find("*") != -1 || find("\"") != -1 || find("|") != -1 || find("%") != -1 || find("<") != -1 || find(">") != -1);
+ Vector<String> chars = String(invalid_filename_characters).split(" ");
+ for (const String &ch : chars) {
+ if (contains(ch)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+String String::validate_filename() const {
+ Vector<String> chars = String(invalid_filename_characters).split(" ");
+ String name = strip_edges();
+ for (int i = 0; i < chars.size(); i++) {
+ name = name.replace(chars[i], "_");
+ }
+ return name;
}
bool String::is_valid_ip_address() const {
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 6338f1d3cd..1582504c57 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -433,6 +433,7 @@ public:
static const String invalid_node_name_characters;
String validate_node_name() const;
String validate_identifier() const;
+ String validate_filename() const;
bool is_valid_identifier() const;
bool is_valid_int() const;
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index f8af78f3c1..94d1596514 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -775,15 +775,9 @@ Variant Array::get_typed_script() const {
return _p->typed.script;
}
-void Array::set_read_only(bool p_enable) {
- if (p_enable == bool(_p->read_only != nullptr)) {
- return;
- }
- if (p_enable) {
+void Array::make_read_only() {
+ if (_p->read_only == nullptr) {
_p->read_only = memnew(Variant);
- } else {
- memdelete(_p->read_only);
- _p->read_only = nullptr;
}
}
diff --git a/core/variant/array.h b/core/variant/array.h
index 3728c22fe0..d9ca3278fb 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -127,7 +127,7 @@ public:
StringName get_typed_class_name() const;
Variant get_typed_script() const;
- void set_read_only(bool p_enable);
+ void make_read_only();
bool is_read_only() const;
Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script);
diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp
index f87064a0d1..0429508cc5 100644
--- a/core/variant/dictionary.cpp
+++ b/core/variant/dictionary.cpp
@@ -333,15 +333,9 @@ Dictionary Dictionary::duplicate(bool p_deep) const {
return recursive_duplicate(p_deep, 0);
}
-void Dictionary::set_read_only(bool p_enable) {
- if (p_enable == bool(_p->read_only != nullptr)) {
- return;
- }
- if (p_enable) {
+void Dictionary::make_read_only() {
+ if (_p->read_only == nullptr) {
_p->read_only = memnew(Variant);
- } else {
- memdelete(_p->read_only);
- _p->read_only = nullptr;
}
}
bool Dictionary::is_read_only() const {
diff --git a/core/variant/dictionary.h b/core/variant/dictionary.h
index e6d8ebe25b..8935d35ed9 100644
--- a/core/variant/dictionary.h
+++ b/core/variant/dictionary.h
@@ -86,7 +86,7 @@ public:
Dictionary duplicate(bool p_deep = false) const;
Dictionary recursive_duplicate(bool p_deep, int recursion_count) const;
- void set_read_only(bool p_enable);
+ void make_read_only();
bool is_read_only() const;
const void *id() const;
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index ca42738b05..672b030806 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -3492,6 +3492,46 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
}
}
+bool Variant::identity_compare(const Variant &p_variant) const {
+ if (type != p_variant.type) {
+ return false;
+ }
+
+ switch (type) {
+ case OBJECT: {
+ return _get_obj().obj == p_variant._get_obj().obj;
+ } break;
+
+ case DICTIONARY: {
+ const Dictionary &l = *(reinterpret_cast<const Dictionary *>(_data._mem));
+ const Dictionary &r = *(reinterpret_cast<const Dictionary *>(p_variant._data._mem));
+ return l.id() == r.id();
+ } break;
+
+ case ARRAY: {
+ const Array &l = *(reinterpret_cast<const Array *>(_data._mem));
+ const Array &r = *(reinterpret_cast<const Array *>(p_variant._data._mem));
+ return l.id() == r.id();
+ } break;
+
+ case PACKED_BYTE_ARRAY:
+ case PACKED_INT32_ARRAY:
+ case PACKED_INT64_ARRAY:
+ case PACKED_FLOAT32_ARRAY:
+ case PACKED_FLOAT64_ARRAY:
+ case PACKED_STRING_ARRAY:
+ case PACKED_VECTOR2_ARRAY:
+ case PACKED_VECTOR3_ARRAY:
+ case PACKED_COLOR_ARRAY: {
+ return _data.packed_array == p_variant._data.packed_array;
+ } break;
+
+ default: {
+ return hash_compare(p_variant);
+ }
+ }
+}
+
bool StringLikeVariantComparator::compare(const Variant &p_lhs, const Variant &p_rhs) {
if (p_lhs.hash_compare(p_rhs)) {
return true;
diff --git a/core/variant/variant.h b/core/variant/variant.h
index b9294de77d..b2f31a6d57 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -748,6 +748,7 @@ public:
uint32_t recursive_hash(int recursion_count) const;
bool hash_compare(const Variant &p_variant, int recursion_count = 0) const;
+ bool identity_compare(const Variant &p_variant) const;
bool booleanize() const;
String stringify(int recursion_count = 0) const;
String to_json_string() const;
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 9e8c6fccb3..e7d1a2478f 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1695,6 +1695,7 @@ static void _register_variant_builtin_methods() {
bind_string_method(json_escape, sarray(), varray());
bind_string_method(validate_node_name, sarray(), varray());
+ bind_string_method(validate_filename, sarray(), varray());
bind_string_method(is_valid_identifier, sarray(), varray());
bind_string_method(is_valid_int, sarray(), varray());
@@ -2179,6 +2180,8 @@ static void _register_variant_builtin_methods() {
bind_method(Dictionary, values, sarray(), varray());
bind_method(Dictionary, duplicate, sarray("deep"), varray(false));
bind_method(Dictionary, get, sarray("key", "default"), varray(Variant()));
+ bind_method(Dictionary, make_read_only, sarray(), varray());
+ bind_method(Dictionary, is_read_only, sarray(), varray());
/* Array */
@@ -2221,12 +2224,11 @@ static void _register_variant_builtin_methods() {
bind_method(Array, max, sarray(), varray());
bind_method(Array, min, sarray(), varray());
bind_method(Array, typed_assign, sarray("array"), varray());
- bind_method(Array, set_typed, sarray("type", "class_name", "script"), varray());
bind_method(Array, is_typed, sarray(), varray());
bind_method(Array, get_typed_builtin, sarray(), varray());
bind_method(Array, get_typed_class_name, sarray(), varray());
bind_method(Array, get_typed_script, sarray(), varray());
- bind_method(Array, set_read_only, sarray("enable"), varray());
+ bind_method(Array, make_read_only, sarray(), varray());
bind_method(Array, is_read_only, sarray(), varray());
/* Byte Array */
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index fe7150bca9..042ebe368a 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -1007,9 +1007,14 @@ struct VariantUtilityFunctions {
static inline uint64_t rid_allocate_id() {
return RID_AllocBase::_gen_id();
}
+
static inline RID rid_from_int64(uint64_t p_base) {
return RID::from_uint64(p_base);
}
+
+ static inline bool is_same(const Variant &p_a, const Variant &p_b) {
+ return p_a.identity_compare(p_b);
+ }
};
#ifdef DEBUG_METHODS_ENABLED
@@ -1601,6 +1606,8 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(rid_allocate_id, Vector<String>(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDR(rid_from_int64, sarray("base"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+
+ FUNCBINDR(is_same, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_GENERAL);
}
void Variant::_unregister_variant_utility_functions() {