summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/io/http_client.cpp132
-rw-r--r--core/io/http_client.h27
-rw-r--r--core/io/packet_peer.cpp10
-rw-r--r--core/io/packet_peer.h12
-rw-r--r--core/io/resource_format_binary.cpp68
-rw-r--r--core/io/resource_format_binary.h7
-rw-r--r--core/ustring.cpp19
-rw-r--r--core/ustring.h2
-rw-r--r--core/variant_call.cpp4
-rw-r--r--doc/classes/Animation.xml3
-rw-r--r--doc/classes/CanvasItem.xml30
-rw-r--r--doc/classes/Curve.xml27
-rw-r--r--doc/classes/Curve3D.xml2
-rw-r--r--doc/classes/Navigation.xml11
-rw-r--r--doc/classes/String.xml3
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp1
-rw-r--r--drivers/unix/packet_peer_udp_posix.cpp2
-rw-r--r--drivers/unix/packet_peer_udp_posix.h12
-rw-r--r--drivers/windows/packet_peer_udp_winsock.cpp (renamed from platform/windows/packet_peer_udp_winsock.cpp)6
-rw-r--r--drivers/windows/packet_peer_udp_winsock.h (renamed from platform/windows/packet_peer_udp_winsock.h)16
-rw-r--r--drivers/windows/stream_peer_tcp_winsock.cpp (renamed from platform/windows/stream_peer_winsock.cpp)52
-rw-r--r--drivers/windows/stream_peer_tcp_winsock.h (renamed from platform/windows/stream_peer_winsock.h)12
-rw-r--r--drivers/windows/tcp_server_winsock.cpp (renamed from platform/windows/tcp_server_winsock.cpp)8
-rw-r--r--drivers/windows/tcp_server_winsock.h (renamed from platform/windows/tcp_server_winsock.h)4
-rw-r--r--editor/editor_export.cpp31
-rw-r--r--editor/editor_export.h9
-rw-r--r--editor/editor_node.cpp5
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--editor/script_create_dialog.cpp2
-rw-r--r--main/input_default.cpp24
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp4
-rw-r--r--modules/enet/networked_multiplayer_enet.h8
-rw-r--r--modules/gdnative/gdnative_api.json12
-rw-r--r--modules/gridmap/grid_map.h5
-rw-r--r--modules/thekla_unwrap/SCsub2
-rw-r--r--platform/javascript/http_client_javascript.cpp39
-rw-r--r--platform/uwp/SCsub3
-rw-r--r--platform/uwp/os_uwp.cpp8
-rw-r--r--platform/windows/SCsub3
-rw-r--r--platform/windows/context_gl_win.cpp2
-rw-r--r--platform/windows/detect.py2
-rw-r--r--platform/windows/os_windows.cpp10
-rw-r--r--scene/3d/baked_lightmap.cpp1
-rw-r--r--scene/gui/dialogs.cpp13
-rw-r--r--scene/gui/rich_text_label.cpp11
-rw-r--r--scene/gui/slider.cpp8
-rw-r--r--scene/gui/tree.cpp14
-rw-r--r--scene/main/http_request.cpp72
-rw-r--r--scene/main/http_request.h1
-rw-r--r--scene/main/viewport.cpp2
-rw-r--r--scene/resources/scene_format_text.cpp774
-rw-r--r--scene/resources/scene_format_text.h26
-rw-r--r--servers/visual/shader_language.cpp79
-rw-r--r--servers/visual/shader_language.h25
-rw-r--r--servers/visual/shader_types.cpp143
-rw-r--r--thirdparty/README.md10
-rw-r--r--thirdparty/fonts/Hack_Regular.ttfbin399724 -> 307420 bytes
-rw-r--r--thirdparty/fonts/LICENSE_Hack.md57
-rw-r--r--thirdparty/thekla_atlas/nvcore/Debug.cpp14
-rw-r--r--thirdparty/thekla_atlas/nvcore/DefsGnucWin32.h2
-rw-r--r--thirdparty/thekla_atlas/nvmath/ftoi.h5
-rw-r--r--thirdparty/thekla_atlas/nvmath/nvmath.h17
62 files changed, 1267 insertions, 648 deletions
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 9d89baafb1..e457a4ac1e 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -30,27 +30,53 @@
#include "http_client.h"
#include "io/stream_peer_ssl.h"
+const char *HTTPClient::_methods[METHOD_MAX] = {
+ "GET",
+ "HEAD",
+ "POST",
+ "PUT",
+ "DELETE",
+ "OPTIONS",
+ "TRACE",
+ "CONNECT",
+ "PATCH"
+};
+
#ifndef JAVASCRIPT_ENABLED
Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, bool p_verify_host) {
close();
+
conn_port = p_port;
conn_host = p_host;
- if (conn_host.begins_with("http://")) {
+ ssl = p_ssl;
+ ssl_verify_host = p_verify_host;
+
+ String host_lower = conn_host.to_lower();
+ if (host_lower.begins_with("http://")) {
- conn_host = conn_host.replace_first("http://", "");
- } else if (conn_host.begins_with("https://")) {
- //use https
- conn_host = conn_host.replace_first("https://", "");
+ conn_host = conn_host.substr(7, conn_host.length() - 7);
+ } else if (host_lower.begins_with("https://")) {
+
+ ssl = true;
+ conn_host = conn_host.substr(8, conn_host.length() - 8);
+ }
+
+ ERR_FAIL_COND_V(conn_host.length() < HOST_MIN_LEN, ERR_INVALID_PARAMETER);
+
+ if (conn_port < 0) {
+ if (ssl) {
+ conn_port = PORT_HTTPS;
+ } else {
+ conn_port = PORT_HTTP;
+ }
}
- ssl = p_ssl;
- ssl_verify_host = p_verify_host;
connection = tcp_connection;
if (conn_host.is_valid_ip_address()) {
- //is ip
+ // Host contains valid IP
Error err = tcp_connection->connect_to_host(IP_Address(conn_host), p_port);
if (err) {
status = STATUS_CANT_CONNECT;
@@ -59,7 +85,7 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl,
status = STATUS_CONNECTING;
} else {
- //is hostname
+ // Host contains hostname and needs to be resolved to IP
resolving = IP::get_singleton()->resolve_hostname_queue_item(conn_host);
status = STATUS_RESOLVING;
}
@@ -82,24 +108,13 @@ Ref<StreamPeer> HTTPClient::get_connection() const {
Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) {
ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
- static const char *_methods[METHOD_MAX] = {
- "GET",
- "HEAD",
- "POST",
- "PUT",
- "DELETE",
- "OPTIONS",
- "TRACE",
- "CONNECT",
- "PATCH"
- };
-
String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
- if ((ssl && conn_port == 443) || (!ssl && conn_port == 80)) {
- // don't append the standard ports
+ if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) {
+ // Don't append the standard ports
request += "Host: " + conn_host + "\r\n";
} else {
request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
@@ -113,17 +128,20 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector
}
if (add_clen) {
request += "Content-Length: " + itos(p_body.size()) + "\r\n";
- //should it add utf8 encoding? not sure
+ // Should it add utf8 encoding?
}
request += "\r\n";
CharString cs = request.utf8();
PoolVector<uint8_t> data;
-
- //Maybe this goes faster somehow?
- for (int i = 0; i < cs.length(); i++) {
- data.append(cs[i]);
+ data.resize(cs.length());
+ {
+ PoolVector<uint8_t>::Write data_write = data.write();
+ for (int i = 0; i < cs.length(); i++) {
+ data_write[i] = cs[i];
+ }
}
+
data.append_array(p_body);
PoolVector<uint8_t>::Read r = data.read();
@@ -143,24 +161,13 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector
Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) {
ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
- static const char *_methods[METHOD_MAX] = {
- "GET",
- "HEAD",
- "POST",
- "PUT",
- "DELETE",
- "OPTIONS",
- "TRACE",
- "CONNECT",
- "PATCH"
- };
-
String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
- if ((ssl && conn_port == 443) || (!ssl && conn_port == 80)) {
- // don't append the standard ports
+ if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) {
+ // Don't append the standard ports
request += "Host: " + conn_host + "\r\n";
} else {
request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
@@ -174,7 +181,7 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str
}
if (add_clen) {
request += "Content-Length: " + itos(p_body.utf8().length()) + "\r\n";
- //should it add utf8 encoding? not sure
+ // Should it add utf8 encoding?
}
request += "\r\n";
request += p_body;
@@ -253,7 +260,7 @@ Error HTTPClient::poll() {
IP::ResolverStatus rstatus = IP::get_singleton()->get_resolve_item_status(resolving);
switch (rstatus) {
case IP::RESOLVER_STATUS_WAITING:
- return OK; //still resolving
+ return OK; // Still resolving
case IP::RESOLVER_STATUS_DONE: {
@@ -285,7 +292,7 @@ Error HTTPClient::poll() {
switch (s) {
case StreamPeerTCP::STATUS_CONNECTING: {
- return OK; //do none
+ return OK;
} break;
case StreamPeerTCP::STATUS_CONNECTED: {
if (ssl) {
@@ -296,7 +303,6 @@ Error HTTPClient::poll() {
status = STATUS_SSL_HANDSHAKE_ERROR;
return ERR_CANT_CONNECT;
}
- //print_line("SSL! TURNED ON!");
connection = ssl;
}
status = STATUS_CONNECTED;
@@ -312,7 +318,7 @@ Error HTTPClient::poll() {
}
} break;
case STATUS_CONNECTED: {
- //request something please
+ // Connection established, requests can now be made
return OK;
} break;
case STATUS_REQUESTING: {
@@ -328,7 +334,7 @@ Error HTTPClient::poll() {
}
if (rec == 0)
- return OK; //keep trying!
+ return OK; // Still requesting, keep trying!
response_str.push_back(byte);
int rs = response_str.size();
@@ -336,11 +342,10 @@ Error HTTPClient::poll() {
(rs >= 2 && response_str[rs - 2] == '\n' && response_str[rs - 1] == '\n') ||
(rs >= 4 && response_str[rs - 4] == '\r' && response_str[rs - 3] == '\n' && response_str[rs - 2] == '\r' && response_str[rs - 1] == '\n')) {
- //end of response, parse.
+ // End of response, parse.
response_str.push_back(0);
String response;
response.parse_utf8((const char *)response_str.ptr());
- //print_line("END OF RESPONSE? :\n"+response+"\n------");
Vector<String> responses = response.split("\n");
body_size = 0;
chunked = false;
@@ -363,7 +368,6 @@ Error HTTPClient::poll() {
if (s.begins_with("transfer-encoding:")) {
String encoding = header.substr(header.find(":") + 1, header.length()).strip_edges();
- //print_line("TRANSFER ENCODING: "+encoding);
if (encoding == "chunked") {
chunked = true;
}
@@ -381,14 +385,14 @@ Error HTTPClient::poll() {
if (body_size == 0 && !chunked) {
- status = STATUS_CONNECTED; //ask for something again?
+ status = STATUS_CONNECTED; // Ready for new requests
} else {
status = STATUS_BODY;
}
return OK;
}
}
- //wait for response
+ // Wait for response
return OK;
} break;
case STATUS_DISCONNECTED: {
@@ -424,7 +428,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
while (true) {
if (chunk_left == 0) {
- //reading len
+ // Reading length
uint8_t b;
int rec = 0;
err = _get_http_data(&b, 1, rec);
@@ -467,7 +471,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
}
if (len == 0) {
- //end!
+ // End reached!
status = STATUS_CONNECTED;
chunk.clear();
return PoolByteArray();
@@ -525,7 +529,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
to_read -= rec;
_offset += rec;
} else {
- if (to_read > 0) //ended up reading less
+ if (to_read > 0) // Ended up reading less
ret.resize(_offset);
break;
}
@@ -540,7 +544,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
close();
if (err == ERR_FILE_EOF) {
- status = STATUS_DISCONNECTED; //server disconnected
+ status = STATUS_DISCONNECTED; // Server disconnected
} else {
status = STATUS_CONNECTION_ERROR;
@@ -593,7 +597,7 @@ HTTPClient::HTTPClient() {
tcp_connection = StreamPeerTCP::create_ref();
resolving = IP::RESOLVER_INVALID_ID;
status = STATUS_DISCONNECTED;
- conn_port = 80;
+ conn_port = -1;
body_size = 0;
chunked = false;
body_left = 0;
@@ -653,7 +657,7 @@ PoolStringArray HTTPClient::_get_response_headers() {
void HTTPClient::_bind_methods() {
- ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_ssl", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(false), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_ssl", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(-1), DEFVAL(false), DEFVAL(true));
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);
@@ -689,13 +693,13 @@ void HTTPClient::_bind_methods() {
BIND_ENUM_CONSTANT(METHOD_MAX);
BIND_ENUM_CONSTANT(STATUS_DISCONNECTED);
- BIND_ENUM_CONSTANT(STATUS_RESOLVING); //resolving hostname (if passed a hostname)
+ BIND_ENUM_CONSTANT(STATUS_RESOLVING); // Resolving hostname (if hostname was passed in)
BIND_ENUM_CONSTANT(STATUS_CANT_RESOLVE);
- BIND_ENUM_CONSTANT(STATUS_CONNECTING); //connecting to ip
+ BIND_ENUM_CONSTANT(STATUS_CONNECTING); // Connecting to IP
BIND_ENUM_CONSTANT(STATUS_CANT_CONNECT);
- BIND_ENUM_CONSTANT(STATUS_CONNECTED); //connected ); requests only accepted here
- BIND_ENUM_CONSTANT(STATUS_REQUESTING); // request in progress
- BIND_ENUM_CONSTANT(STATUS_BODY); // request resulted in body ); which must be read
+ BIND_ENUM_CONSTANT(STATUS_CONNECTED); // Connected, now accepting requests
+ BIND_ENUM_CONSTANT(STATUS_REQUESTING); // Request in progress
+ BIND_ENUM_CONSTANT(STATUS_BODY); // Request resulted in body which must be read
BIND_ENUM_CONSTANT(STATUS_CONNECTION_ERROR);
BIND_ENUM_CONSTANT(STATUS_SSL_HANDSHAKE_ERROR);
diff --git a/core/io/http_client.h b/core/io/http_client.h
index 2e0a345f1c..3d8953c156 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -133,19 +133,29 @@ public:
enum Status {
STATUS_DISCONNECTED,
- STATUS_RESOLVING, //resolving hostname (if passed a hostname)
+ STATUS_RESOLVING, // Resolving hostname (if passed a hostname)
STATUS_CANT_RESOLVE,
- STATUS_CONNECTING, //connecting to ip
+ STATUS_CONNECTING, // Connecting to IP
STATUS_CANT_CONNECT,
- STATUS_CONNECTED, //connected, requests only accepted here
- STATUS_REQUESTING, // request in progress
- STATUS_BODY, // request resulted in body, which must be read
+ STATUS_CONNECTED, // Connected, requests can be made
+ STATUS_REQUESTING, // Request in progress
+ STATUS_BODY, // Request resulted in body, which must be read
STATUS_CONNECTION_ERROR,
STATUS_SSL_HANDSHAKE_ERROR,
};
private:
+ static const char *_methods[METHOD_MAX];
+ static const int HOST_MIN_LEN = 4;
+
+ enum Port {
+
+ PORT_HTTP = 80,
+ PORT_HTTPS = 443,
+
+ };
+
#ifndef JAVASCRIPT_ENABLED
Status status;
IP::ResolverID resolving;
@@ -182,8 +192,7 @@ private:
static void _bind_methods();
public:
- //Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request
- Error connect_to_host(const String &p_host, int p_port, bool p_ssl = false, bool p_verify_host = true);
+ Error connect_to_host(const String &p_host, int p_port = -1, bool p_ssl = false, bool p_verify_host = true);
void set_connection(const Ref<StreamPeer> &p_connection);
Ref<StreamPeer> get_connection() const;
@@ -201,9 +210,9 @@ public:
Error get_response_headers(List<String> *r_response);
int get_response_body_length() const;
- PoolByteArray read_response_body_chunk(); // can't get body as partial text because of most encodings UTF8, gzip, etc.
+ PoolByteArray read_response_body_chunk(); // Can't get body as partial text because of most encodings UTF8, gzip, etc.
- void set_blocking_mode(bool p_enable); //useful mostly if running in a thread
+ void set_blocking_mode(bool p_enable); // Useful mostly if running in a thread
bool is_blocking_mode_enabled() const;
void set_read_chunk_size(int p_size);
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index 16c73c26e7..c6b12f73ae 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -49,7 +49,7 @@ bool PacketPeer::is_object_decoding_allowed() const {
return allow_object_decoding;
}
-Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) const {
+Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) {
const uint8_t *buffer;
int buffer_size;
@@ -78,7 +78,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) const {
+Error PacketPeer::get_var(Variant &r_variant) {
const uint8_t *buffer;
int buffer_size;
@@ -107,7 +107,7 @@ Error PacketPeer::put_var(const Variant &p_packet) {
return put_packet(buf, len);
}
-Variant PacketPeer::_bnd_get_var() const {
+Variant PacketPeer::_bnd_get_var() {
Variant var;
get_var(var);
@@ -117,7 +117,7 @@ Variant PacketPeer::_bnd_get_var() const {
Error PacketPeer::_put_packet(const PoolVector<uint8_t> &p_buffer) {
return put_packet_buffer(p_buffer);
}
-PoolVector<uint8_t> PacketPeer::_get_packet() const {
+PoolVector<uint8_t> PacketPeer::_get_packet() {
PoolVector<uint8_t> raw;
last_get_error = get_packet_buffer(raw);
@@ -202,7 +202,7 @@ int PacketPeerStream::get_available_packet_count() const {
return count;
}
-Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) const {
+Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);
_poll_buffer();
diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h
index b08d44ad8a..a6d363ec12 100644
--- a/core/io/packet_peer.h
+++ b/core/io/packet_peer.h
@@ -37,13 +37,13 @@ class PacketPeer : public Reference {
GDCLASS(PacketPeer, Reference);
- Variant _bnd_get_var() const;
+ Variant _bnd_get_var();
void _bnd_put_var(const Variant &p_var);
static void _bind_methods();
Error _put_packet(const PoolVector<uint8_t> &p_buffer);
- PoolVector<uint8_t> _get_packet() const;
+ PoolVector<uint8_t> _get_packet();
Error _get_packet_error() const;
mutable Error last_get_error;
@@ -52,17 +52,17 @@ class PacketPeer : public Reference {
public:
virtual int get_available_packet_count() const = 0;
- virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) const = 0; ///< buffer is GONE after next get_packet
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) = 0; ///< buffer is GONE after next get_packet
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) = 0;
virtual int get_max_packet_size() const = 0;
/* helpers / binders */
- virtual Error get_packet_buffer(PoolVector<uint8_t> &r_buffer) const;
+ 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) const;
+ virtual Error get_var(Variant &r_variant);
virtual Error put_var(const Variant &p_packet);
void set_allow_object_decoding(bool p_enable);
@@ -91,7 +91,7 @@ protected:
public:
virtual int get_available_packet_count() const;
- virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) const;
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size);
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
virtual int get_max_packet_size() const;
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index df0d41ea9d..92fdbc1581 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -104,7 +104,7 @@ StringName ResourceInteractiveLoaderBinary::_get_string() {
uint32_t id = f->get_32();
if (id & 0x80000000) {
- int len = id & 0x7FFFFFFF;
+ uint32_t len = id & 0x7FFFFFFF;
if (len > str_buf.size()) {
str_buf.resize(len);
}
@@ -734,6 +734,7 @@ Error ResourceInteractiveLoaderBinary::poll() {
for (int i = 0; i < pc; i++) {
StringName name = _get_string();
+
if (name == StringName()) {
error = ERR_FILE_CORRUPT;
ERR_FAIL_V(ERR_FILE_CORRUPT);
@@ -902,7 +903,9 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
ExtResource er;
er.type = get_unicode_string();
+
er.path = get_unicode_string();
+
external_resources.push_back(er);
}
@@ -1271,7 +1274,7 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
-void ResourceFormatSaverBinaryInstance::_pad_buffer(int p_bytes) {
+void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes) {
int extra = 4 - (p_bytes % 4);
if (extra < 4) {
@@ -1280,7 +1283,12 @@ void ResourceFormatSaverBinaryInstance::_pad_buffer(int p_bytes) {
}
}
-void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property, const PropertyInfo &p_hint) {
+void ResourceFormatSaverBinaryInstance::_write_variant(const Variant &p_property, const PropertyInfo &p_hint) {
+
+ write_variant(f, p_property, resource_set, external_resources, string_map, p_hint);
+}
+
+void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
switch (p_property.get_type()) {
@@ -1327,7 +1335,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
f->store_32(VARIANT_STRING);
String val = p_property;
- save_unicode_string(val);
+ save_unicode_string(f, val);
} break;
case Variant::VECTOR2: {
@@ -1453,10 +1461,20 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
if (np.is_absolute())
snc |= 0x8000;
f->store_16(snc);
- for (int i = 0; i < np.get_name_count(); i++)
- f->store_32(get_string_index(np.get_name(i)));
- for (int i = 0; i < np.get_subname_count(); i++)
- f->store_32(get_string_index(np.get_subname(i)));
+ for (int i = 0; i < np.get_name_count(); i++) {
+ if (string_map.has(np.get_name(i))) {
+ f->store_32(string_map[np.get_name(i)]);
+ } else {
+ save_unicode_string(f, np.get_name(i), true);
+ }
+ }
+ for (int i = 0; i < np.get_subname_count(); i++) {
+ if (string_map.has(np.get_subname(i))) {
+ f->store_32(string_map[np.get_subname(i)]);
+ } else {
+ save_unicode_string(f, np.get_subname(i), true);
+ }
+ }
} break;
case Variant::_RID: {
@@ -1508,8 +1526,8 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
continue;
*/
- write_variant(E->get());
- write_variant(d[E->get()]);
+ write_variant(f, E->get(), resource_set, external_resources, string_map);
+ write_variant(f, d[E->get()], resource_set, external_resources, string_map);
}
} break;
@@ -1520,7 +1538,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
f->store_32(uint32_t(a.size()));
for (int i = 0; i < a.size(); i++) {
- write_variant(a[i]);
+ write_variant(f, a[i], resource_set, external_resources, string_map);
}
} break;
@@ -1532,7 +1550,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
f->store_32(len);
PoolVector<uint8_t>::Read r = arr.read();
f->store_buffer(r.ptr(), len);
- _pad_buffer(len);
+ _pad_buffer(f, len);
} break;
case Variant::POOL_INT_ARRAY: {
@@ -1566,7 +1584,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
f->store_32(len);
PoolVector<String>::Read r = arr.read();
for (int i = 0; i < len; i++) {
- save_unicode_string(r[i]);
+ save_unicode_string(f, r[i]);
}
} break;
@@ -1693,10 +1711,14 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
}
}
-void ResourceFormatSaverBinaryInstance::save_unicode_string(const String &p_string) {
+void ResourceFormatSaverBinaryInstance::save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len) {
CharString utf8 = p_string.utf8();
- f->store_32(utf8.length() + 1);
+ if (p_bit_on_len) {
+ f->store_32(utf8.length() + 1 | 0x80000000);
+ } else {
+ f->store_32(utf8.length() + 1);
+ }
f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
}
@@ -1763,7 +1785,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
return ERR_CANT_CREATE;
}
- save_unicode_string(p_resource->get_class());
+ save_unicode_string(f, p_resource->get_class());
f->store_64(0); //offset to import metadata
for (int i = 0; i < 14; i++)
f->store_32(0); // reserved
@@ -1800,7 +1822,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
f->store_32(strings.size()); //string table size
for (int i = 0; i < strings.size(); i++) {
- save_unicode_string(strings[i]);
+ save_unicode_string(f, strings[i]);
}
// save external resource table
@@ -1814,10 +1836,10 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
for (int i = 0; i < save_order.size(); i++) {
- save_unicode_string(save_order[i]->get_save_class());
+ save_unicode_string(f, save_order[i]->get_save_class());
String path = save_order[i]->get_path();
path = relative_paths ? local_path.path_to_file(path) : path;
- save_unicode_string(path);
+ save_unicode_string(f, path);
}
// save internal resource table
f->store_32(saved_resources.size()); //amount of internal resources
@@ -1853,7 +1875,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
used_indices.insert(new_subindex);
}
- save_unicode_string("local://" + itos(r->get_subindex()));
+ save_unicode_string(f, "local://" + itos(r->get_subindex()));
if (takeover_paths) {
r->set_path(p_path + "::" + itos(r->get_subindex()), true);
}
@@ -1861,7 +1883,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
r->set_edited(false);
#endif
} else {
- save_unicode_string(r->get_path()); //actual external
+ save_unicode_string(f, r->get_path()); //actual external
}
ofs_pos.push_back(f->get_position());
f->store_64(0); //offset in 64 bits
@@ -1875,14 +1897,14 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
ResourceData &rd = E->get();
ofs_table.push_back(f->get_position());
- save_unicode_string(rd.type);
+ save_unicode_string(f, rd.type);
f->store_32(rd.properties.size());
for (List<Property>::Element *F = rd.properties.front(); F; F = F->next()) {
Property &p = F->get();
f->store_32(p.name_idx);
- write_variant(p.value, F->get().pi);
+ _write_variant(p.value, F->get().pi);
}
}
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 687da0a9b4..176b8350cf 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -140,14 +140,15 @@ class ResourceFormatSaverBinaryInstance {
List<Property> properties;
};
- void _pad_buffer(int p_bytes);
- void write_variant(const Variant &p_property, const PropertyInfo &p_hint = PropertyInfo());
+ static void _pad_buffer(FileAccess *f, int p_bytes);
+ void _write_variant(const Variant &p_property, const PropertyInfo &p_hint = PropertyInfo());
void _find_resources(const Variant &p_variant, bool p_main = false);
- void save_unicode_string(const String &p_string);
+ static void save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false);
int get_string_index(const String &p_string);
public:
Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
+ static void write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
};
class ResourceFormatSaverBinary : public ResourceFormatSaver {
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 3a0708851e..1bf7d000c3 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -734,7 +734,7 @@ Vector<String> String::split_spaces() const {
return ret;
}
-Vector<String> String::split(const String &p_splitter, bool p_allow_empty) const {
+Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const {
Vector<String> ret;
int from = 0;
@@ -745,8 +745,21 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty) const
int end = find(p_splitter, from);
if (end < 0)
end = len;
- if (p_allow_empty || (end > from))
- ret.push_back(substr(from, end - from));
+ if (p_allow_empty || (end > from)) {
+ if (p_maxsplit <= 0)
+ ret.push_back(substr(from, end - from));
+ else if (p_maxsplit > 0) {
+
+ // Put rest of the string and leave cycle.
+ if (p_maxsplit == ret.size()) {
+ ret.push_back(substr(from, len));
+ break;
+ }
+
+ // Otherwise, push items until positive limit is reached.
+ ret.push_back(substr(from, end - from));
+ }
+ }
if (end == len)
break;
diff --git a/core/ustring.h b/core/ustring.h
index 9c24133b55..6541642bd1 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -162,7 +162,7 @@ public:
String get_slice(String p_splitter, int p_slice) const;
String get_slicec(CharType p_splitter, int p_slice) const;
- Vector<String> split(const String &p_splitter, bool p_allow_empty = true) const;
+ Vector<String> split(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const;
Vector<String> split_spaces() const;
Vector<float> split_floats(const String &p_splitter, bool p_allow_empty = true) const;
Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index f66cce85c9..2b99a60ba5 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -254,7 +254,7 @@ struct _VariantCall {
VCALL_LOCALMEM2R(String, replacen);
VCALL_LOCALMEM2R(String, insert);
VCALL_LOCALMEM0R(String, capitalize);
- VCALL_LOCALMEM2R(String, split);
+ VCALL_LOCALMEM3R(String, split);
VCALL_LOCALMEM2R(String, split_floats);
VCALL_LOCALMEM0R(String, to_upper);
VCALL_LOCALMEM0R(String, to_lower);
@@ -1446,7 +1446,7 @@ void register_variant_methods() {
ADDFUNC2R(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", varray());
ADDFUNC2R(STRING, STRING, String, insert, INT, "position", STRING, "what", varray());
ADDFUNC0R(STRING, STRING, String, capitalize, varray());
- ADDFUNC2R(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", varray(true));
+ ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0));
ADDFUNC2R(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true));
ADDFUNC0R(STRING, STRING, String, to_upper, varray());
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 93b01a466b..dd248d18f7 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -38,6 +38,7 @@
<argument index="1" name="to_animation" type="Animation">
</argument>
<description>
+ Adds a new track that is a copy of the given track from [code]to_animation[/code].
</description>
</method>
<method name="find_track" qualifiers="const">
@@ -260,6 +261,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the track at index [code]idx[/code] is enabled.
</description>
</method>
<method name="track_is_imported" qualifiers="const">
@@ -319,6 +321,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Enables/disables the given track. Tracks are enabled by default.
</description>
</method>
<method name="track_set_imported">
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index cf0b482b07..bd20cfcf5d 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -36,7 +36,7 @@
<argument index="4" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
<description>
- Draw a string character using a custom font. Returns the advance, depending on the char width and kerning with an optional next char.
+ Draws a string character using a custom font. Returns the advance, depending on the char width and kerning with an optional next char.
</description>
</method>
<method name="draw_circle">
@@ -49,7 +49,7 @@
<argument index="2" name="color" type="Color">
</argument>
<description>
- Draw a colored circle.
+ Draws a colored circle.
</description>
</method>
<method name="draw_colored_polygon">
@@ -68,7 +68,7 @@
<argument index="5" name="antialiased" type="bool" default="false">
</argument>
<description>
- Draw a colored polygon of any amount of points, convex or concave.
+ Draws a colored polygon of any amount of points, convex or concave.
</description>
</method>
<method name="draw_line">
@@ -85,7 +85,7 @@
<argument index="4" name="antialiased" type="bool" default="false">
</argument>
<description>
- Draw a line from a 2D point to another, with a given color and width. It can be optionally antialiased.
+ Draws a line from a 2D point to another, with a given color and width. It can be optionally antialiased.
</description>
</method>
<method name="draw_multiline">
@@ -100,6 +100,7 @@
<argument index="3" name="antialiased" type="bool" default="false">
</argument>
<description>
+ Draws multiple, parallel lines with a uniform [code]color[/code] and [code]width[/code] and optional antialiasing.
</description>
</method>
<method name="draw_multiline_colors">
@@ -114,6 +115,7 @@
<argument index="3" name="antialiased" type="bool" default="false">
</argument>
<description>
+ Draws multiple, parallel lines with a uniform [code]width[/code], segment-by-segment coloring, and optional antialiasing. Colors assigned to line segments match by index between [code]points[/code] and [code]colors[/code].
</description>
</method>
<method name="draw_polygon">
@@ -132,7 +134,7 @@
<argument index="5" name="antialiased" type="bool" default="false">
</argument>
<description>
- Draw a polygon of any amount of points, convex or concave.
+ Draws a polygon of any amount of points, convex or concave.
</description>
</method>
<method name="draw_polyline">
@@ -147,7 +149,7 @@
<argument index="3" name="antialiased" type="bool" default="false">
</argument>
<description>
- Draw a polyline with a uniform [code]color[/code] and [code]width[/code] and optional antialiasing.
+ Draws interconnected line segments with a uniform [code]color[/code] and [code]width[/code] and optional antialiasing.
</description>
</method>
<method name="draw_polyline_colors">
@@ -162,7 +164,7 @@
<argument index="3" name="antialiased" type="bool" default="false">
</argument>
<description>
- Draw a polyline with a uniform [code]width[/code], segment-by-segment coloring, and optional antialiasing. Colors assigned to line segments match by index between [code]points[/code] and [code]colors[/code].
+ Draws interconnected line segments with a uniform [code]width[/code], segment-by-segment coloring, and optional antialiasing. Colors assigned to line segments match by index between [code]points[/code] and [code]colors[/code].
</description>
</method>
<method name="draw_primitive">
@@ -181,7 +183,7 @@
<argument index="5" name="normal_map" type="Texture" default="null">
</argument>
<description>
- Draw a custom primitive, 1 point for a point, 2 points for a line, 3 points for a triangle and 4 points for a quad.
+ Draws a custom primitive, 1 point for a point, 2 points for a line, 3 points for a triangle and 4 points for a quad.
</description>
</method>
<method name="draw_rect">
@@ -194,7 +196,7 @@
<argument index="2" name="filled" type="bool" default="true">
</argument>
<description>
- Draw a colored rectangle.
+ Draws a colored rectangle.
</description>
</method>
<method name="draw_set_transform">
@@ -233,7 +235,7 @@
<argument index="4" name="clip_w" type="int" default="-1">
</argument>
<description>
- Draw a string using a custom font.
+ Draws a string using a custom font.
</description>
</method>
<method name="draw_style_box">
@@ -244,7 +246,7 @@
<argument index="1" name="rect" type="Rect2">
</argument>
<description>
- Draw a styled rectangle.
+ Draws a styled rectangle.
</description>
</method>
<method name="draw_texture">
@@ -259,7 +261,7 @@
<argument index="3" name="normal_map" type="Texture" default="null">
</argument>
<description>
- Draw a texture at a given position.
+ Draws a texture at a given position.
</description>
</method>
<method name="draw_texture_rect">
@@ -278,7 +280,7 @@
<argument index="5" name="normal_map" type="Texture" default="null">
</argument>
<description>
- Draw a textured rectangle at a given position, optionally modulated by a color. Transpose swaps the x and y coordinates when reading the texture.
+ Draws a textured rectangle at a given position, optionally modulated by a color. Transpose swaps the x and y coordinates when reading the texture.
</description>
</method>
<method name="draw_texture_rect_region">
@@ -299,7 +301,7 @@
<argument index="6" name="clip_uv" type="bool" default="true">
</argument>
<description>
- Draw a textured rectangle region at a given position, optionally modulated by a color. Transpose swaps the x and y coordinates when reading the texture.
+ Draws a textured rectangle region at a given position, optionally modulated by a color. Transpose swaps the x and y coordinates when reading the texture.
</description>
</method>
<method name="get_canvas" qualifiers="const">
diff --git a/doc/classes/Curve.xml b/doc/classes/Curve.xml
index 3e1158ca3b..f7ef9a182c 100644
--- a/doc/classes/Curve.xml
+++ b/doc/classes/Curve.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Curve" inherits="Resource" category="Core" version="3.0-beta">
<brief_description>
+ A mathematic curve.
</brief_description>
<description>
+ A curve that can be saved and re-used for other objects. By default it ranges between [code]0[/code] and [code]1[/code] on the y-axis and positions points relative to the [code]0.5[/code] y-position.
</description>
<tutorials>
</tutorials>
@@ -23,24 +25,28 @@
<argument index="4" name="right_mode" type="int" enum="Curve.TangentMode" default="0">
</argument>
<description>
+ Adds a point to the curve. For each side, if the [code]*_mode[/code] is [code]TANGENT_LINEAR[/code], the [code]*_tangent[/code] angle (in degrees) uses the slope of the curve halfway to the adjacent point. Allows custom assignments to the [code]*_tangent[/code] angle if [code]*_mode[/code] is set to [code]TANGENT_FREE[/code].
</description>
</method>
<method name="bake">
<return type="void">
</return>
<description>
+ Recomputes the baked cache of points for the curve.
</description>
</method>
<method name="clean_dupes">
<return type="void">
</return>
<description>
+ Removes points that are closer than [code]CMP_EPSILON[/code] (0.00001) units to their neighbor on the curve.
</description>
</method>
<method name="clear_points">
<return type="void">
</return>
<description>
+ Removes all points from the curve.
</description>
</method>
<method name="get_point_left_mode" qualifiers="const">
@@ -49,6 +55,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Returns the left [code]TangentMode[/code] for the point at [code]index[/code].
</description>
</method>
<method name="get_point_left_tangent" qualifiers="const">
@@ -57,6 +64,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Returns the left tangent angle (in degrees) for the point at [code]index[/code].
</description>
</method>
<method name="get_point_position" qualifiers="const">
@@ -65,6 +73,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Returns the curve coordinates for the point at [code]index[/code].
</description>
</method>
<method name="get_point_right_mode" qualifiers="const">
@@ -73,6 +82,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Returns the right [code]TangentMode[/code] for the point at [code]index[/code].
</description>
</method>
<method name="get_point_right_tangent" qualifiers="const">
@@ -81,6 +91,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Returns the right tangent angle (in degrees) for the point at [code]index[/code].
</description>
</method>
<method name="interpolate" qualifiers="const">
@@ -89,12 +100,14 @@
<argument index="0" name="offset" type="float">
</argument>
<description>
+ Returns the y value for the point that would exist at x-position [code]offset[/code] along the curve.
</description>
</method>
<method name="interpolate_baked">
<return type="float">
</return>
<argument index="0" name="offset" type="float">
+ Returns the y value for the point that would exist at x-position [code]offset[/code] along the curve using the baked cache. Bakes the curve's points if not already baked.
</argument>
<description>
</description>
@@ -105,6 +118,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Removes the point at [code]index[/code] from the curve.
</description>
</method>
<method name="set_point_left_mode">
@@ -115,6 +129,7 @@
<argument index="1" name="mode" type="int" enum="Curve.TangentMode">
</argument>
<description>
+ Sets the left [code]TangentMode[/code] for the point at [code]index[/code] to [code]mode[/code].
</description>
</method>
<method name="set_point_left_tangent">
@@ -125,6 +140,7 @@
<argument index="1" name="tangent" type="float">
</argument>
<description>
+ Sets the left tangent angle for the point at [code]index[/code] to [code]tangent[/code].
</description>
</method>
<method name="set_point_offset">
@@ -135,6 +151,7 @@
<argument index="1" name="offset" type="float">
</argument>
<description>
+ Sets the offset from [code]0.5[/code]
</description>
</method>
<method name="set_point_right_mode">
@@ -145,6 +162,7 @@
<argument index="1" name="mode" type="int" enum="Curve.TangentMode">
</argument>
<description>
+ Sets the right [code]TangentMode[/code] for the point at [code]index[/code] to [code]mode[/code].
</description>
</method>
<method name="set_point_right_tangent">
@@ -155,6 +173,7 @@
<argument index="1" name="tangent" type="float">
</argument>
<description>
+ Sets the right tangent angle for the point at [code]index[/code] to [code]tangent[/code].
</description>
</method>
<method name="set_point_value">
@@ -165,29 +184,37 @@
<argument index="1" name="y" type="float">
</argument>
<description>
+ Assigns the vertical position [code]y[/code] to the point at [code]index[/code].
</description>
</method>
</methods>
<members>
<member name="bake_resolution" type="int" setter="set_bake_resolution" getter="get_bake_resolution">
+ The number of points to include in the baked (i.e. cached) curve data.
</member>
<member name="max_value" type="float" setter="set_max_value" getter="get_max_value">
+ The maximum value the curve can reach. Default value: [code]1[/code].
</member>
<member name="min_value" type="float" setter="set_min_value" getter="get_min_value">
+ The minimum value the curve can reach. Default value: [code]0[/code].
</member>
</members>
<signals>
<signal name="range_changed">
<description>
+ Emitted when [member max_value] or [member min_value] is changed.
</description>
</signal>
</signals>
<constants>
<constant name="TANGENT_FREE" value="0" enum="TangentMode">
+ The tangent on this side of the point is user-defined.
</constant>
<constant name="TANGENT_LINEAR" value="1" enum="TangentMode">
+ The curve calculates the tangent on this side of the point as the slope halfway towards the adjacent point.
</constant>
<constant name="TANGENT_MODE_COUNT" value="2" enum="TangentMode">
+ The total number of available tangent modes.
</constant>
</constants>
</class>
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index e30ae85617..91d7a9bed8 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -32,6 +32,7 @@
<return type="void">
</return>
<description>
+ Removes all points from the curve.
</description>
</method>
<method name="get_baked_length" qualifiers="const">
@@ -203,6 +204,7 @@
</methods>
<members>
<member name="bake_interval" type="float" setter="set_bake_interval" getter="get_bake_interval">
+ The distance in meters between two adjacent cached points. Changing it forces the cache to be recomputed the next time the [method get_baked_points] or [method get_baked_length] function is called. The smaller the distance, the more points in the cache and the more memory it will consume, so use with care.
</member>
</members>
<constants>
diff --git a/doc/classes/Navigation.xml b/doc/classes/Navigation.xml
index 4bfe964a4d..995cb5b179 100644
--- a/doc/classes/Navigation.xml
+++ b/doc/classes/Navigation.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Navigation" inherits="Spatial" category="Core" version="3.0-beta">
<brief_description>
+ A collection of [code]NavigationMesh[/code] resources and methods used for pathfinding.
</brief_description>
<description>
+ The Navigation node is used for basic or advanced navigation. By default it will automatically collect all child [code]NavigationMesh[/code] resources, but they can also be added on the fly through scripting. It can be used for generating a simple path between two points or it can be used to ensure that a navigation agent is angled perfectly to the terrain it is navigating.
</description>
<tutorials>
</tutorials>
@@ -15,6 +17,7 @@
<argument index="0" name="to_point" type="Vector3">
</argument>
<description>
+ Returns the closest navigation point to the point passed.
</description>
</method>
<method name="get_closest_point_normal">
@@ -23,6 +26,7 @@
<argument index="0" name="to_point" type="Vector3">
</argument>
<description>
+ Returns the surface normal of the navigation mesh at the point passed. For instance, if the point passed was at a 45 degree slope it would return something like (0.5,0.5,0). This is useful for rotating a navigation agent in accordance with the [code]NavigationMesh[/code].
</description>
</method>
<method name="get_closest_point_owner">
@@ -31,6 +35,7 @@
<argument index="0" name="to_point" type="Vector3">
</argument>
<description>
+ Returns the nearest [code]NavigationMeshInstance[/code] to the point passed.
</description>
</method>
<method name="get_closest_point_to_segment">
@@ -43,6 +48,7 @@
<argument index="2" name="use_collision" type="bool" default="false">
</argument>
<description>
+ Returns the nearest point to the line segment passed. The third optional parameter takes collisions into account.
</description>
</method>
<method name="get_simple_path">
@@ -55,6 +61,7 @@
<argument index="2" name="optimize" type="bool" default="true">
</argument>
<description>
+ Returns a path of points as a [code]PoolVector3Array[/code]. If [code]optimize[/code] is false the [code]NavigationMesh[/code] agent properties will be taken into account, otherwise it will return the nearest path and ignore agent radius, height, etc.
</description>
</method>
<method name="navmesh_create">
@@ -67,6 +74,7 @@
<argument index="2" name="owner" type="Object" default="null">
</argument>
<description>
+ Adds a [code]NavigationMesh[/code] to the list of NavigationMesh's in this node. Returns an id. Its position, rotation and scale are associated with the [code]Transform[/code] passed. The [code]Node[/code] (or [code]Object[/code]) that owns this node is an optional parameter.
</description>
</method>
<method name="navmesh_remove">
@@ -75,6 +83,7 @@
<argument index="0" name="id" type="int">
</argument>
<description>
+ Removes a [code]NavigationMesh[/code] from the list of NavigationMesh's in this node.
</description>
</method>
<method name="navmesh_set_transform">
@@ -85,11 +94,13 @@
<argument index="1" name="xform" type="Transform">
</argument>
<description>
+ Associates a [code]NavigationMesh[/code]'s id with a [code]Transform[/code]. Its position, rotation and scale are based on the [code]Transform[/code] passed.
</description>
</method>
</methods>
<members>
<member name="up_vector" type="Vector3" setter="set_up_vector" getter="get_up_vector">
+ Defines which direction is up. The default defines 0,1,0 as up which is the world up direction. To make this a ceiling use 0,-1,0 to define down as up.
</member>
</members>
<constants>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index 78e9f3cd3f..8bbd52b417 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -662,8 +662,11 @@
</argument>
<argument index="1" name="allow_empty" type="bool" default="True">
</argument>
+ <argument index="2" name="maxsplit" type="int" default="0">
+ </argument>
<description>
Splits the string by a divisor string and returns an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",".
+ If [code]maxsplit[/code] is given, at most maxsplit number of splits occur, and the remainder of the string is returned as the final element of the list (thus, the list will have at most maxsplit+1 elements)
</description>
</method>
<method name="split_floats">
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 21102e8c25..101978548d 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -812,6 +812,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
//for light
actions[VS::SHADER_SPATIAL].renames["VIEW"] = "view";
actions[VS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color";
+ actions[VS::SHADER_SPATIAL].renames["LIGHT"] = "light";
actions[VS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation";
actions[VS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light";
actions[VS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light";
diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp
index 61d2737555..f6742d8114 100644
--- a/drivers/unix/packet_peer_udp_posix.cpp
+++ b/drivers/unix/packet_peer_udp_posix.cpp
@@ -65,7 +65,7 @@ int PacketPeerUDPPosix::get_available_packet_count() const {
return queue_count;
}
-Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer, int &r_buffer_size) const {
+Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
Error err = const_cast<PacketPeerUDPPosix *>(this)->_poll(false);
if (err != OK)
diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h
index e580d336b2..ad7be5bbe0 100644
--- a/drivers/unix/packet_peer_udp_posix.h
+++ b/drivers/unix/packet_peer_udp_posix.h
@@ -41,12 +41,12 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
PACKET_BUFFER_SIZE = 65536
};
- mutable RingBuffer<uint8_t> rb;
+ RingBuffer<uint8_t> rb;
uint8_t recv_buffer[PACKET_BUFFER_SIZE];
- mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE];
- mutable IP_Address packet_ip;
- mutable int packet_port;
- mutable int queue_count;
+ uint8_t packet_buffer[PACKET_BUFFER_SIZE];
+ IP_Address packet_ip;
+ int packet_port;
+ int queue_count;
int sockfd;
bool sock_blocking;
IP::Type sock_type;
@@ -62,7 +62,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
public:
virtual int get_available_packet_count() const;
- virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) const;
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size);
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
virtual int get_max_packet_size() const;
diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/drivers/windows/packet_peer_udp_winsock.cpp
index d414ec891e..119ee68bd2 100644
--- a/platform/windows/packet_peer_udp_winsock.cpp
+++ b/drivers/windows/packet_peer_udp_winsock.cpp
@@ -27,6 +27,8 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifdef WINDOWS_ENABLED
+
#include "packet_peer_udp_winsock.h"
#include <winsock2.h>
@@ -43,7 +45,7 @@ int PacketPeerUDPWinsock::get_available_packet_count() const {
return queue_count;
}
-Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer, int &r_buffer_size) const {
+Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
Error err = const_cast<PacketPeerUDPWinsock *>(this)->_poll(false);
if (err != OK)
@@ -291,3 +293,5 @@ PacketPeerUDPWinsock::~PacketPeerUDPWinsock() {
close();
}
+
+#endif
diff --git a/platform/windows/packet_peer_udp_winsock.h b/drivers/windows/packet_peer_udp_winsock.h
index 8a6951fd6e..8ce2cff741 100644
--- a/platform/windows/packet_peer_udp_winsock.h
+++ b/drivers/windows/packet_peer_udp_winsock.h
@@ -27,6 +27,8 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifdef WINDOWS_ENABLED
+
#ifndef PACKET_PEER_UDP_WINSOCK_H
#define PACKET_PEER_UDP_WINSOCK_H
@@ -39,12 +41,12 @@ class PacketPeerUDPWinsock : public PacketPeerUDP {
PACKET_BUFFER_SIZE = 65536
};
- mutable RingBuffer<uint8_t> rb;
+ RingBuffer<uint8_t> rb;
uint8_t recv_buffer[PACKET_BUFFER_SIZE];
- mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE];
- mutable IP_Address packet_ip;
- mutable int packet_port;
- mutable int queue_count;
+ uint8_t packet_buffer[PACKET_BUFFER_SIZE];
+ IP_Address packet_ip;
+ int packet_port;
+ int queue_count;
int sockfd;
bool sock_blocking;
IP::Type sock_type;
@@ -62,7 +64,7 @@ class PacketPeerUDPWinsock : public PacketPeerUDP {
public:
virtual int get_available_packet_count() const;
- virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) const;
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size);
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
virtual int get_max_packet_size() const;
@@ -82,3 +84,5 @@ public:
~PacketPeerUDPWinsock();
};
#endif // PACKET_PEER_UDP_WINSOCK_H
+
+#endif
diff --git a/platform/windows/stream_peer_winsock.cpp b/drivers/windows/stream_peer_tcp_winsock.cpp
index 8b83215325..f4cd38079d 100644
--- a/platform/windows/stream_peer_winsock.cpp
+++ b/drivers/windows/stream_peer_tcp_winsock.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* stream_peer_winsock.cpp */
+/* stream_peer_tcp_winsock.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -29,7 +29,7 @@
/*************************************************************************/
#ifdef WINDOWS_ENABLED
-#include "stream_peer_winsock.h"
+#include "stream_peer_tcp_winsock.h"
#include <winsock2.h>
#include <ws2tcpip.h>
@@ -38,14 +38,14 @@
int winsock_refcount = 0;
-StreamPeerTCP *StreamPeerWinsock::_create() {
+StreamPeerTCP *StreamPeerTCPWinsock::_create() {
- return memnew(StreamPeerWinsock);
+ return memnew(StreamPeerTCPWinsock);
};
-void StreamPeerWinsock::make_default() {
+void StreamPeerTCPWinsock::make_default() {
- StreamPeerTCP::_create = StreamPeerWinsock::_create;
+ StreamPeerTCP::_create = StreamPeerTCPWinsock::_create;
if (winsock_refcount == 0) {
WSADATA data;
@@ -54,7 +54,7 @@ void StreamPeerWinsock::make_default() {
++winsock_refcount;
};
-void StreamPeerWinsock::cleanup() {
+void StreamPeerTCPWinsock::cleanup() {
--winsock_refcount;
if (winsock_refcount == 0) {
@@ -63,7 +63,7 @@ void StreamPeerWinsock::cleanup() {
};
};
-Error StreamPeerWinsock::_block(int p_sockfd, bool p_read, bool p_write) const {
+Error StreamPeerTCPWinsock::_block(int p_sockfd, bool p_read, bool p_write) const {
fd_set read, write;
FD_ZERO(&read);
@@ -78,7 +78,7 @@ Error StreamPeerWinsock::_block(int p_sockfd, bool p_read, bool p_write) const {
return ret < 0 ? FAILED : OK;
};
-Error StreamPeerWinsock::_poll_connection() const {
+Error StreamPeerTCPWinsock::_poll_connection() const {
ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == INVALID_SOCKET, FAILED);
@@ -108,7 +108,7 @@ Error StreamPeerWinsock::_poll_connection() const {
return OK;
};
-Error StreamPeerWinsock::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
+Error StreamPeerTCPWinsock::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
if (status == STATUS_NONE || status == STATUS_ERROR) {
@@ -166,7 +166,7 @@ Error StreamPeerWinsock::write(const uint8_t *p_data, int p_bytes, int &r_sent,
return OK;
};
-Error StreamPeerWinsock::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
+Error StreamPeerTCPWinsock::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
if (!is_connected_to_host()) {
@@ -224,29 +224,29 @@ Error StreamPeerWinsock::read(uint8_t *p_buffer, int p_bytes, int &r_received, b
return OK;
};
-Error StreamPeerWinsock::put_data(const uint8_t *p_data, int p_bytes) {
+Error StreamPeerTCPWinsock::put_data(const uint8_t *p_data, int p_bytes) {
int total;
return write(p_data, p_bytes, total, true);
};
-Error StreamPeerWinsock::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
+Error StreamPeerTCPWinsock::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
return write(p_data, p_bytes, r_sent, false);
};
-Error StreamPeerWinsock::get_data(uint8_t *p_buffer, int p_bytes) {
+Error StreamPeerTCPWinsock::get_data(uint8_t *p_buffer, int p_bytes) {
int total;
return read(p_buffer, p_bytes, total, true);
};
-Error StreamPeerWinsock::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
+Error StreamPeerTCPWinsock::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
return read(p_buffer, p_bytes, r_received, false);
};
-StreamPeerTCP::Status StreamPeerWinsock::get_status() const {
+StreamPeerTCP::Status StreamPeerTCPWinsock::get_status() const {
if (status == STATUS_CONNECTING) {
_poll_connection();
@@ -255,7 +255,7 @@ StreamPeerTCP::Status StreamPeerWinsock::get_status() const {
return status;
};
-bool StreamPeerWinsock::is_connected_to_host() const {
+bool StreamPeerTCPWinsock::is_connected_to_host() const {
if (status == STATUS_NONE || status == STATUS_ERROR) {
@@ -268,7 +268,7 @@ bool StreamPeerWinsock::is_connected_to_host() const {
return (sockfd != INVALID_SOCKET);
};
-void StreamPeerWinsock::disconnect_from_host() {
+void StreamPeerTCPWinsock::disconnect_from_host() {
if (sockfd != INVALID_SOCKET)
closesocket(sockfd);
@@ -281,7 +281,7 @@ void StreamPeerWinsock::disconnect_from_host() {
peer_port = 0;
};
-void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) {
+void StreamPeerTCPWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) {
sockfd = p_sockfd;
sock_type = p_sock_type;
@@ -290,7 +290,7 @@ void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port,
peer_port = p_port;
};
-Error StreamPeerWinsock::connect_to_host(const IP_Address &p_host, uint16_t p_port) {
+Error StreamPeerTCPWinsock::connect_to_host(const IP_Address &p_host, uint16_t p_port) {
ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER);
@@ -331,13 +331,13 @@ Error StreamPeerWinsock::connect_to_host(const IP_Address &p_host, uint16_t p_po
return OK;
};
-void StreamPeerWinsock::set_nodelay(bool p_enabled) {
+void StreamPeerTCPWinsock::set_nodelay(bool p_enabled) {
ERR_FAIL_COND(!is_connected_to_host());
int flag = p_enabled ? 1 : 0;
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
}
-int StreamPeerWinsock::get_available_bytes() const {
+int StreamPeerTCPWinsock::get_available_bytes() const {
unsigned long len;
int ret = ioctlsocket(sockfd, FIONREAD, &len);
@@ -345,17 +345,17 @@ int StreamPeerWinsock::get_available_bytes() const {
return len;
}
-IP_Address StreamPeerWinsock::get_connected_host() const {
+IP_Address StreamPeerTCPWinsock::get_connected_host() const {
return peer_host;
};
-uint16_t StreamPeerWinsock::get_connected_port() const {
+uint16_t StreamPeerTCPWinsock::get_connected_port() const {
return peer_port;
};
-StreamPeerWinsock::StreamPeerWinsock() {
+StreamPeerTCPWinsock::StreamPeerTCPWinsock() {
sock_type = IP::TYPE_NONE;
sockfd = INVALID_SOCKET;
@@ -363,7 +363,7 @@ StreamPeerWinsock::StreamPeerWinsock() {
peer_port = 0;
};
-StreamPeerWinsock::~StreamPeerWinsock() {
+StreamPeerTCPWinsock::~StreamPeerTCPWinsock() {
disconnect_from_host();
};
diff --git a/platform/windows/stream_peer_winsock.h b/drivers/windows/stream_peer_tcp_winsock.h
index 26e2a3e4c9..fef457c43f 100644
--- a/platform/windows/stream_peer_winsock.h
+++ b/drivers/windows/stream_peer_tcp_winsock.h
@@ -29,15 +29,15 @@
/*************************************************************************/
#ifdef WINDOWS_ENABLED
-#ifndef STREAM_PEER_WINSOCK_H
-#define STREAM_PEER_WINSOCK_H
+#ifndef STREAM_PEER_TCP_WINSOCK_H
+#define STREAM_PEER_TCP_WINSOCK_H
#include "error_list.h"
#include "core/io/ip_address.h"
#include "core/io/stream_peer_tcp.h"
-class StreamPeerWinsock : public StreamPeerTCP {
+class StreamPeerTCPWinsock : public StreamPeerTCP {
protected:
mutable Status status;
@@ -82,10 +82,10 @@ public:
virtual void set_nodelay(bool p_enabled);
- StreamPeerWinsock();
- ~StreamPeerWinsock();
+ StreamPeerTCPWinsock();
+ ~StreamPeerTCPWinsock();
};
-#endif // TCP_SOCKET_POSIX_H
+#endif // STREAM_PEER_TCP_WINSOCK_H
#endif
diff --git a/platform/windows/tcp_server_winsock.cpp b/drivers/windows/tcp_server_winsock.cpp
index de300befa7..49de279793 100644
--- a/platform/windows/tcp_server_winsock.cpp
+++ b/drivers/windows/tcp_server_winsock.cpp
@@ -27,9 +27,11 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifdef WINDOWS_ENABLED
+
#include "tcp_server_winsock.h"
-#include "stream_peer_winsock.h"
+#include "stream_peer_tcp_winsock.h"
#include <winsock2.h>
#include <ws2tcpip.h>
@@ -151,7 +153,7 @@ Ref<StreamPeerTCP> TCPServerWinsock::take_connection() {
int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size);
ERR_FAIL_COND_V(fd == INVALID_SOCKET, NULL);
- Ref<StreamPeerWinsock> conn = memnew(StreamPeerWinsock);
+ Ref<StreamPeerTCPWinsock> conn = memnew(StreamPeerTCPWinsock);
IP_Address ip;
int port;
_set_ip_addr_port(ip, port, &their_addr);
@@ -181,3 +183,5 @@ TCPServerWinsock::~TCPServerWinsock() {
stop();
};
+
+#endif
diff --git a/platform/windows/tcp_server_winsock.h b/drivers/windows/tcp_server_winsock.h
index a3e01098ed..fd16480167 100644
--- a/platform/windows/tcp_server_winsock.h
+++ b/drivers/windows/tcp_server_winsock.h
@@ -27,6 +27,8 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifdef WINDOWS_ENABLED
+
#ifndef TCP_SERVER_WINSOCK_H
#define TCP_SERVER_WINSOCK_H
@@ -54,3 +56,5 @@ public:
};
#endif
+
+#endif
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 3f618c3199..b330f5d177 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -39,10 +39,10 @@
#include "io/zip_io.h"
#include "os/file_access.h"
#include "project_settings.h"
+#include "scene/resources/scene_format_text.h"
#include "script_language.h"
-#include "version.h"
-
#include "thirdparty/misc/md5.h"
+#include "version.h"
static int _get_pad(int p_alignment, int p_n) {
@@ -1399,3 +1399,30 @@ EditorExportPlatformPC::EditorExportPlatformPC() {
chmod_flags = -1;
}
+
+///////////////////////
+
+void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) {
+
+ String extension = p_path.get_extension().to_lower();
+ if (extension != "tres" && extension != "tscn") {
+ return;
+ }
+
+ print_line("exporting " + p_path);
+
+ bool convert = GLOBAL_GET("editor/convert_text_resources_to_binary_on_export");
+ if (!convert)
+ return;
+ String tmp_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("file.res");
+ Error err = ResourceFormatLoaderText::convert_file_to_binary(p_path, tmp_path);
+ ERR_FAIL_COND(err != OK);
+ Vector<uint8_t> data = FileAccess::get_file_as_array(tmp_path);
+ ERR_FAIL_COND(data.size() == 0);
+ add_file(p_path + ".converted.res", data, true);
+}
+
+EditorExportTextSceneToBinaryPlugin::EditorExportTextSceneToBinaryPlugin() {
+
+ GLOBAL_DEF("editor/convert_text_resources_to_binary_on_export", false);
+}
diff --git a/editor/editor_export.h b/editor/editor_export.h
index 215a770a12..8b1cf4bcff 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -408,4 +408,13 @@ public:
EditorExportPlatformPC();
};
+class EditorExportTextSceneToBinaryPlugin : public EditorExportPlugin {
+
+ GDCLASS(EditorExportTextSceneToBinaryPlugin, EditorExportPlugin)
+
+public:
+ virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features);
+ EditorExportTextSceneToBinaryPlugin();
+};
+
#endif // EDITOR_IMPORT_EXPORT_H
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 91767d55b1..cb8407386d 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -5718,6 +5718,11 @@ EditorNode::EditorNode() {
editor_plugins_force_over = memnew(EditorPluginList);
editor_plugins_force_input_forwarding = memnew(EditorPluginList);
+ Ref<EditorExportTextSceneToBinaryPlugin> export_text_to_binary_plugin;
+ export_text_to_binary_plugin.instance();
+
+ EditorExport::get_singleton()->add_export_plugin(export_text_to_binary_plugin);
+
_edit_current();
current = NULL;
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index b390070b4a..bd6efee2db 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -161,7 +161,7 @@ void ShaderTextEditor::_load_theme_settings() {
for (const Map<StringName, ShaderLanguage::FunctionInfo>::Element *E = ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())).front(); E; E = E->next()) {
- for (const Map<StringName, ShaderLanguage::DataType>::Element *F = E->get().built_ins.front(); F; F = F->next()) {
+ for (const Map<StringName, ShaderLanguage::BuiltInInfo>::Element *F = E->get().built_ins.front(); F; F = F->next()) {
keywords.push_back(F->key());
}
}
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 3cab14b0c4..f99a2eafdd 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -459,7 +459,7 @@ void ScriptCreateDialog::_update_dialog() {
script_ok = false;
}
}
- if (has_named_classes && (!is_class_name_valid)) {
+ if (has_named_classes && (is_new_script_created && !is_class_name_valid)) {
_msg_script_valid(false, TTR("Invalid class name"));
script_ok = false;
}
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 8c91a1a5de..f637e77d56 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -635,7 +635,7 @@ static const char *s_ControllerMappings[] = {
"d81d0b00000000000000504944564944,BUFFALO BSGP1601 Series ,x:b4,a:b5,b:b3,y:b2,back:b12,start:b13,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b6,rightshoulder:b9,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"d81d0f00000000000000504944564944,iBUFFALO BSGP1204 Series,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"d81d1000000000000000504944564944,iBUFFALO BSGP1204P Series,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
- "ff113133000000000000504944564944,Gembird JPD-DualForce,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11,",
+ "ff113133000000000000504944564944,SVEN X-PAD,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,",
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"__XINPUT_DEVICE__,XInput Gamepad,a:b12,b:b13,x:b14,y:b15,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpdown:b1,dpleft:b2,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,",
#endif
@@ -684,7 +684,7 @@ static const char *s_ControllerMappings[] = {
"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"030000000d0f00000d00000000010000,hori,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5,",
"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7",
- "030000000d0f00002200000011010000,HORI CO.,LTD. REAL ARCADE Pro.V3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,",
+ "030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,",
"030000000d0f00004d00000011010000,HORI Gem Pad 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,",
"030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,",
@@ -698,8 +698,8 @@ static const char *s_ControllerMappings[] = {
"03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
"030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
- "030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
- "030000004c050000c405000011810000,Sony Computer Entertainment Wireless Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:h0.1,rightshoulder:b5,rightx:a3,start:b9,righty:a4,dpleft:h0.8,lefttrigger:a2,x:b3,dpup:h0.1,back:b8,leftstick:b11,leftshoulder:b4,y:b2,a:b0,dpright:h0.2,righttrigger:a5,b:b1,",
+ "030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
+ "030000004c050000c405000011810000,Sony DualShock 4,a:b0,b:b1,y:b2,x:b3,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
"030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
"030000004c050000cc09000011810000,Sony DualShock 4 (CUH-ZCT2U) (USB),a:b0,b:b1,y:b2,x:b3,leftshoulder:b4,rightshoulder:b5,back:b8,start:b9,guide:b10,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
@@ -718,7 +718,7 @@ static const char *s_ControllerMappings[] = {
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
"030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e040000d102000001010000,Microsoft X-Box One pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
@@ -734,7 +734,7 @@ static const char *s_ControllerMappings[] = {
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"030000006f0e00000103000000020000,Logic3 Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "030000006f0e00001304000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "030000006f0e00001304000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
"030000006f0e00001f01000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000006f0e00002801000011010000,PDP Rock Candy Wireless Controller for PS3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b0,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,dpright:h0.2,righttrigger:b7,b:b2,",
@@ -742,13 +742,13 @@ static const char *s_ControllerMappings[] = {
"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"03000000780000000600000010010000,Microntek USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,",
- "03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "03000000790000001100000010010000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
+ "03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "03000000790000001100000010010000,RetroLink Saturn Classic Controller,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
"030000008916000001fd000024010000,Razer Onza Classic Edition,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
- "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
"030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,x:b1,a:b0,b:b4,y:b5,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,",
"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,",
@@ -761,7 +761,7 @@ static const char *s_ControllerMappings[] = {
"03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
"03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,x:b13,y:b11,back:b4,start:b5,leftstick:b14,rightstick:b15,leftshoulder:b9,rightshoulder:b8,dpup:b0,dpdown:b2,dpleft:b3,dpright:b1,leftx:a1,lefty:a0,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,y:b0,x:b1,b:b3,a:b4,leftshoulder:b2,rightshoulder:b5,back:b6,start:b7,guide:b9,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftx:a0,lefty:a1,",
- "03000000c9110000f055000011010000,HJC Game GAMEPAD,x:b2,a:b0,b:b1,y:b3,back:b4,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,",
+ "03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,",
"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,",
"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,",
"03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
@@ -778,7 +778,7 @@ static const char *s_ControllerMappings[] = {
"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,",
- "050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "050000004c050000c405000000010000,Sony DualShock 4 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
"050000004c050000cc09000000810000,Sony DualShock 4 (CUH-ZCT2U) (Bluetooth),a:b0,b:b1,y:b2,x:b3,leftshoulder:b4,rightshoulder:b5,back:b8,start:b9,guide:b10,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,",
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index ce485956b4..396bebf0ea 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -386,7 +386,7 @@ int NetworkedMultiplayerENet::get_available_packet_count() const {
return incoming_packets.size();
}
-Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer, int &r_buffer_size) const {
+Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
ERR_FAIL_COND_V(incoming_packets.size() == 0, ERR_UNAVAILABLE);
@@ -480,7 +480,7 @@ int NetworkedMultiplayerENet::get_max_packet_size() const {
return 1 << 24; //anything is good
}
-void NetworkedMultiplayerENet::_pop_current_packet() const {
+void NetworkedMultiplayerENet::_pop_current_packet() {
if (current_packet.packet) {
enet_packet_destroy(current_packet.packet);
diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h
index 81d517147d..d7bc5c7849 100644
--- a/modules/enet/networked_multiplayer_enet.h
+++ b/modules/enet/networked_multiplayer_enet.h
@@ -86,12 +86,12 @@ private:
CompressionMode compression_mode;
- mutable List<Packet> incoming_packets;
+ List<Packet> incoming_packets;
- mutable Packet current_packet;
+ Packet current_packet;
uint32_t _gen_unique_id() const;
- void _pop_current_packet() const;
+ void _pop_current_packet();
Vector<uint8_t> src_compressor_mem;
Vector<uint8_t> dst_compressor_mem;
@@ -123,7 +123,7 @@ public:
virtual bool is_server() const;
virtual int get_available_packet_count() const;
- virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) const; ///< buffer is GONE after next get_packet
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size); ///< buffer is GONE after next get_packet
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
virtual int get_max_packet_size() const;
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 31f3b0b77b..b7b2553435 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -5533,6 +5533,12 @@
]
},
{
+ "name": "godot_get_stack_bottom",
+ "return_type": "void *",
+ "arguments": [
+ ]
+ },
+ {
"name": "godot_method_bind_get_method",
"return_type": "godot_method_bind *",
"arguments": [
@@ -5569,6 +5575,12 @@
]
},
{
+ "name": "godot_get_global_constants",
+ "return_type": "godot_dictionary",
+ "arguments": [
+ ]
+ },
+ {
"name": "godot_register_native_call_type",
"return_type": "void",
"arguments": [
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 5bfdf1dac3..ab66bf123e 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -186,6 +186,11 @@ class GridMap : public Spatial {
Vector3 _get_offset() const;
+ struct BakedMesh {
+ Ref<Mesh> mesh;
+ Transform transform;
+ };
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
diff --git a/modules/thekla_unwrap/SCsub b/modules/thekla_unwrap/SCsub
index b489fcc9e7..c57bf326ea 100644
--- a/modules/thekla_unwrap/SCsub
+++ b/modules/thekla_unwrap/SCsub
@@ -67,7 +67,7 @@ if env['builtin_thekla_atlas']:
if env.msvc:
env_thekla_unwrap.Append(CCFLAGS=["-DNV_OS_WIN32", "-DNV_CC_MSVC", "-DPOSH_COMPILER_MSVC" ])
else:
- env_thekla_unwrap.Append(CCFLAGS=["-DNV_OS_MINGW", "-DNV_CC_GNUC", "-DPOSH_COMPILER_GCC"])
+ env_thekla_unwrap.Append(CCFLAGS=["-DNV_OS_MINGW", "-DNV_CC_GNUC", "-DPOSH_COMPILER_GCC", "-U__STRICT_ANSI__"])
env.Append(LIBS=["dbghelp"])
# Godot source files
diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp
index 0b105dcb40..b170ba6f35 100644
--- a/platform/javascript/http_client_javascript.cpp
+++ b/platform/javascript/http_client_javascript.cpp
@@ -37,16 +37,31 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl,
WARN_PRINT("Disabling HTTPClient's host verification is not supported for the HTML5 platform, host will be verified");
}
+ port = p_port;
+ use_tls = p_ssl;
+
host = p_host;
- if (host.begins_with("http://")) {
- host.replace_first("http://", "");
- } else if (host.begins_with("https://")) {
- host.replace_first("https://", "");
+
+ String host_lower = host.to_lower();
+ if (host_lower.begins_with("http://")) {
+ host = host.substr(7, host.length() - 7);
+ } else if (host_lower.begins_with("https://")) {
+ use_tls = true;
+ host = host.substr(8, host.length() - 8);
+ }
+
+ ERR_FAIL_COND_V(host.length() < HOST_MIN_LEN, ERR_INVALID_PARAMETER);
+
+ if (port < 0) {
+ if (use_tls) {
+ port = PORT_HTTPS;
+ } else {
+ port = PORT_HTTP;
+ }
}
status = host.is_valid_ip_address() ? STATUS_CONNECTING : STATUS_RESOLVING;
- port = p_port;
- use_tls = p_ssl;
+
return OK;
}
@@ -68,17 +83,7 @@ Error HTTPClient::prepare_request(Method p_method, const String &p_url, const Ve
ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(host.empty(), ERR_UNCONFIGURED);
ERR_FAIL_COND_V(port < 0, ERR_UNCONFIGURED);
-
- static const char *_methods[HTTPClient::METHOD_MAX] = {
- "GET",
- "HEAD",
- "POST",
- "PUT",
- "DELETE",
- "OPTIONS",
- "TRACE",
- "CONNECT"
- };
+ ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER);
String url = (use_tls ? "https://" : "http://") + host + ":" + itos(port) + "/" + p_url;
godot_xhr_reset(xhr_id);
diff --git a/platform/uwp/SCsub b/platform/uwp/SCsub
index f0d69fef33..fb0c4a92ae 100644
--- a/platform/uwp/SCsub
+++ b/platform/uwp/SCsub
@@ -4,9 +4,6 @@ Import('env')
files = [
'thread_uwp.cpp',
- '#platform/windows/tcp_server_winsock.cpp',
- '#platform/windows/packet_peer_udp_winsock.cpp',
- '#platform/windows/stream_peer_winsock.cpp',
'#platform/windows/key_mapping_win.cpp',
'#platform/windows/windows_terminal_logger.cpp',
'joypad_uwp.cpp',
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 659f162724..3018ac0bef 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -34,13 +34,13 @@
#include "drivers/windows/dir_access_windows.h"
#include "drivers/windows/file_access_windows.h"
#include "drivers/windows/mutex_windows.h"
+#include "drivers/windows/packet_peer_udp_winsock.h"
#include "drivers/windows/rw_lock_windows.h"
#include "drivers/windows/semaphore_windows.h"
+#include "drivers/windows/stream_peer_tcp_winsock.h"
+#include "drivers/windows/tcp_server_winsock.h"
#include "io/marshalls.h"
#include "main/main.h"
-#include "platform/windows/packet_peer_udp_winsock.h"
-#include "platform/windows/stream_peer_winsock.h"
-#include "platform/windows/tcp_server_winsock.h"
#include "platform/windows/windows_terminal_logger.h"
#include "project_settings.h"
#include "servers/audio_server.h"
@@ -163,7 +163,7 @@ void OSUWP::initialize_core() {
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
TCPServerWinsock::make_default();
- StreamPeerWinsock::make_default();
+ StreamPeerTCPWinsock::make_default();
PacketPeerUDPWinsock::make_default();
// We need to know how often the clock is updated
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index 135ccd902a..5030f4b3e0 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -19,9 +19,6 @@ common_win = [
"os_windows.cpp",
"ctxgl_procaddr.cpp",
"key_mapping_win.cpp",
- "tcp_server_winsock.cpp",
- "packet_peer_udp_winsock.cpp",
- "stream_peer_winsock.cpp",
"joypad.cpp",
"power_windows.cpp",
"windows_terminal_logger.cpp"
diff --git a/platform/windows/context_gl_win.cpp b/platform/windows/context_gl_win.cpp
index 81aa18dd23..ccb0a41d13 100644
--- a/platform/windows/context_gl_win.cpp
+++ b/platform/windows/context_gl_win.cpp
@@ -181,8 +181,6 @@ Error ContextGL_Win::initialize() {
MessageBox(NULL, "Can't Activate The GL 3.3 Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return ERR_CANT_CREATE; // Return FALSE
}
-
- printf("Activated GL 3.3 context");
}
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index bc8be7f034..01eb50e69c 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -269,7 +269,7 @@ def configure(env):
if (env["openmp"]):
env.Append(CPPFLAGS=['-fopenmp'])
- env.Append(LIBS=['gomp'])
+ env.Append(LINKFLAGS=['-fopenmp'])
## Compile flags
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 5916c8f06c..6cab683e83 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -34,19 +34,19 @@
#include "drivers/windows/dir_access_windows.h"
#include "drivers/windows/file_access_windows.h"
#include "drivers/windows/mutex_windows.h"
+#include "drivers/windows/packet_peer_udp_winsock.h"
#include "drivers/windows/rw_lock_windows.h"
#include "drivers/windows/semaphore_windows.h"
+#include "drivers/windows/stream_peer_tcp_winsock.h"
+#include "drivers/windows/tcp_server_winsock.h"
#include "drivers/windows/thread_windows.h"
#include "io/marshalls.h"
#include "joypad.h"
#include "lang_table.h"
#include "main/main.h"
-#include "packet_peer_udp_winsock.h"
#include "servers/audio_server.h"
#include "servers/visual/visual_server_raster.h"
#include "servers/visual/visual_server_wrap_mt.h"
-#include "stream_peer_winsock.h"
-#include "tcp_server_winsock.h"
#include "version_generated.gen.h"
#include "windows_terminal_logger.h"
@@ -196,7 +196,7 @@ void OS_Windows::initialize_core() {
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
TCPServerWinsock::make_default();
- StreamPeerWinsock::make_default();
+ StreamPeerTCPWinsock::make_default();
PacketPeerUDPWinsock::make_default();
// We need to know how often the clock is updated
@@ -1253,7 +1253,7 @@ void OS_Windows::finalize_core() {
memdelete(process_map);
TCPServerWinsock::cleanup();
- StreamPeerWinsock::cleanup();
+ StreamPeerTCPWinsock::cleanup();
}
void OS_Windows::alert(const String &p_alert, const String &p_title) {
diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp
index 8af8c2f7da..3d9bb73181 100644
--- a/scene/3d/baked_lightmap.cpp
+++ b/scene/3d/baked_lightmap.cpp
@@ -175,6 +175,7 @@ BakedLightmap::Subdiv BakedLightmap::get_capture_subdiv() const {
void BakedLightmap::set_extents(const Vector3 &p_extents) {
extents = p_extents;
+ update_gizmo();
}
Vector3 BakedLightmap::get_extents() const {
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index d4912339da..9a55073bb6 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -289,10 +289,17 @@ bool WindowDialog::get_resizable() const {
Size2 WindowDialog::get_minimum_size() const {
Ref<Font> font = get_font("title_font", "WindowDialog");
- int msx = close_button->get_combined_minimum_size().x;
- msx += font->get_string_size(title).x;
- return Size2(msx, 1);
+ const int button_width = close_button->get_combined_minimum_size().x;
+ const int title_width = font->get_string_size(title).x;
+ const int padding = button_width / 2;
+ const int button_area = button_width + padding;
+
+ // as the title gets centered, title_width + close_button_width is not enough.
+ // we want a width w, such that w / 2 - title_width / 2 >= button_area, i.e.
+ // w >= 2 * button_area + title_width
+
+ return Size2(2 * button_area + title_width, 1);
}
TextureButton *WindowDialog::get_close_button() {
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 05c6e9f77e..6fbc58a38a 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -31,6 +31,11 @@
#include "os/keyboard.h"
#include "os/os.h"
#include "scene/scene_string_names.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_node.h"
+#endif
+
RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) {
if (p_free) {
@@ -370,7 +375,11 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
Color uc = color;
uc.a *= 0.5;
int uy = y + lh - fh + ascent + 2;
- VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + pofs, uy), p_ofs + Point2(align_ofs + pofs + cw, uy), uc);
+ float underline_width = 1.0;
+#ifdef TOOLS_ENABLED
+ underline_width *= EDSCALE;
+#endif
+ VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + pofs, uy), p_ofs + Point2(align_ofs + pofs + cw, uy), uc, underline_width);
}
ofs += cw;
}
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 665ae8b6dd..70b8616af1 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -184,10 +184,10 @@ void Slider::_notification(int p_what) {
focus->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height)));
*/
if (ticks > 1) {
- int tickarea = size.height - tick->get_height();
+ int grabber_offset = (grabber->get_size().height / 2 - tick->get_height() / 2);
for (int i = 0; i < ticks; i++) {
if (!ticks_on_borders && (i == 0 || i + 1 == ticks)) continue;
- int ofs = i * tickarea / (ticks - 1);
+ int ofs = (i * areasize / (ticks - 1)) + grabber_offset;
tick->draw(ci, Point2i((size.width - widget_width) / 2, ofs));
}
}
@@ -205,10 +205,10 @@ void Slider::_notification(int p_what) {
*/
if (ticks > 1) {
- int tickarea = size.width - tick->get_width();
+ int grabber_offset = (grabber->get_size().width / 2 - tick->get_width() / 2);
for (int i = 0; i < ticks; i++) {
if ((!ticks_on_borders) && ((i == 0) || ((i + 1) == ticks))) continue;
- int ofs = i * tickarea / (ticks - 1);
+ int ofs = (i * areasize / (ticks - 1)) + grabber_offset;
tick->draw(ci, Point2i(ofs, (size.height - widget_height) / 2));
}
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index ab12d123ba..b5b42e8f29 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -30,6 +30,7 @@
#include "tree.h"
#include <limits.h>
+#include "math_funcs.h"
#include "os/input.h"
#include "os/keyboard.h"
#include "os/os.h"
@@ -37,6 +38,10 @@
#include "project_settings.h"
#include "scene/main/viewport.h"
+#ifdef TOOLS_ENABLED
+#include "editor/editor_node.h"
+#endif
+
void TreeItem::move_to_top() {
if (!parent || parent->childs == this)
@@ -1412,9 +1417,14 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (c->get_children() != NULL)
root_pos -= Point2i(cache.arrow->get_width(), 0);
+ float line_width = 1.0;
+#ifdef TOOLS_ENABLED
+ line_width *= EDSCALE;
+#endif
+
Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs;
- VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x, root_pos.y), cache.relationship_line_color);
- VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), parent_pos, cache.relationship_line_color);
+ VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
+ VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), parent_pos, cache.relationship_line_color, line_width);
}
int child_h = draw_item(children_pos, p_draw_ofs, p_draw_size, c);
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 672e893f1b..4afdb56f86 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -36,7 +36,6 @@ void HTTPRequest::_redirect_request(const String &p_new_url) {
Error HTTPRequest::_request() {
- //print_line("Requesting:\n\tURL: "+url+"\n\tString: "+request_string+"\n\tPort: "+itos(port)+"\n\tSSL: "+itos(use_ssl)+"\n\tValidate SSL: "+itos(validate_ssl));
return client->connect_to_host(url, port, use_ssl, validate_ssl);
}
@@ -54,37 +53,32 @@ Error HTTPRequest::_parse_url(const String &p_url) {
downloaded = 0;
redirections = 0;
- //print_line("1 url: "+url);
- if (url.begins_with("http://")) {
-
+ String url_lower = url.to_lower();
+ if (url_lower.begins_with("http://")) {
url = url.substr(7, url.length() - 7);
- //print_line("no SSL");
-
- } else if (url.begins_with("https://")) {
+ } else if (url_lower.begins_with("https://")) {
url = url.substr(8, url.length() - 8);
use_ssl = true;
port = 443;
- //print_line("yes SSL");
} else {
ERR_EXPLAIN("Malformed URL");
ERR_FAIL_V(ERR_INVALID_PARAMETER);
}
- //print_line("2 url: "+url);
+ if (url.length() < 1) {
+ ERR_EXPLAIN("URL too short");
+ ERR_FAIL_V(ERR_INVALID_PARAMETER);
+ }
int slash_pos = url.find("/");
if (slash_pos != -1) {
request_string = url.substr(slash_pos, url.length());
url = url.substr(0, slash_pos);
- //print_line("request string: "+request_string);
} else {
request_string = "/";
- //print_line("no request");
}
- //print_line("3 url: "+url);
-
int colon_pos = url.find(":");
if (colon_pos != -1) {
port = url.substr(colon_pos + 1, url.length()).to_int();
@@ -92,8 +86,6 @@ Error HTTPRequest::_parse_url(const String &p_url) {
ERR_FAIL_COND_V(port < 1 || port > 65535, ERR_INVALID_PARAMETER);
}
- //print_line("4 url: "+url);
-
return OK;
}
@@ -198,10 +190,8 @@ void HTTPRequest::cancel_request() {
}
client->close();
body.resize(0);
- //downloaded=0;
got_response = false;
response_code = -1;
- //body_len=-1;
request_sent = false;
requesting = false;
}
@@ -221,12 +211,12 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
response_headers.resize(0);
downloaded = 0;
for (List<String>::Element *E = rheaders.front(); E; E = E->next()) {
- //print_line("HEADER: "+E->get());
response_headers.push_back(E->get());
}
if (response_code == 301 || response_code == 302) {
- //redirect
+ // Handle redirect
+
if (max_redirects >= 0 && redirections >= max_redirects) {
call_deferred("_request_done", RESULT_REDIRECT_LIMIT_REACHED, response_code, response_headers, PoolByteArray());
@@ -242,15 +232,13 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
}
}
- //print_line("NEW LOCATION: "+new_request);
-
if (new_request != "") {
- //process redirect
+ // Process redirect
client->close();
- int new_redirs = redirections + 1; //because _request() will clear it
+ int new_redirs = redirections + 1; // Because _request() will clear it
Error err;
if (new_request.begins_with("http")) {
- //new url, request all again
+ // New url, request all again
err = _parse_url(new_request);
} else {
request_string = new_request;
@@ -258,7 +246,6 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
err = _request();
- //print_line("new connection: "+itos(err));
if (err == OK) {
request_sent = false;
got_response = false;
@@ -280,11 +267,11 @@ bool HTTPRequest::_update_connection() {
switch (client->get_status()) {
case HTTPClient::STATUS_DISCONNECTED: {
call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PoolStringArray(), PoolByteArray());
- return true; //end it, since it's doing something
+ return true; // End it, since it's doing something
} break;
case HTTPClient::STATUS_RESOLVING: {
client->poll();
- //must wait
+ // Must wait
return false;
} break;
case HTTPClient::STATUS_CANT_RESOLVE: {
@@ -294,9 +281,9 @@ bool HTTPRequest::_update_connection() {
} break;
case HTTPClient::STATUS_CONNECTING: {
client->poll();
- //must wait
+ // Must wait
return false;
- } break; //connecting to ip
+ } break; // Connecting to IP
case HTTPClient::STATUS_CANT_CONNECT: {
call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PoolStringArray(), PoolByteArray());
@@ -309,7 +296,7 @@ bool HTTPRequest::_update_connection() {
if (!got_response) {
- //no body
+ // No body
bool ret_value;
@@ -320,16 +307,16 @@ bool HTTPRequest::_update_connection() {
return true;
}
if (got_response && body_len < 0) {
- //chunked transfer is done
+ // Chunked transfer is done
call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body);
return true;
}
call_deferred("_request_done", RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PoolByteArray());
return true;
- //request migh have been done
+ // Request migh have been done
} else {
- //did not request yet, do request
+ // Did not request yet, do request
Error err = client->request(method, request_string, headers, request_data);
if (err != OK) {
@@ -340,13 +327,13 @@ bool HTTPRequest::_update_connection() {
request_sent = true;
return false;
}
- } break; //connected: { } break requests only accepted here
+ } break; // Connected: break requests only accepted here
case HTTPClient::STATUS_REQUESTING: {
- //must wait, it's requesting
+ // Must wait, still requesting
client->poll();
return false;
- } break; // request in progress
+ } break; // Request in progress
case HTTPClient::STATUS_BODY: {
if (!got_response) {
@@ -363,7 +350,7 @@ bool HTTPRequest::_update_connection() {
}
if (client->is_response_chunked()) {
- body_len = -1; //no body len because chunked, change your webserver configuration if you want body len
+ body_len = -1; // No body len because chunked, change your webserver configuration if you want body len
} else {
body_len = client->get_response_body_length();
@@ -383,7 +370,6 @@ bool HTTPRequest::_update_connection() {
}
}
- //print_line("BODY: "+itos(body.size()));
client->poll();
PoolByteArray chunk = client->read_response_body_chunk();
@@ -411,15 +397,11 @@ bool HTTPRequest::_update_connection() {
call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body);
return true;
}
- /*if (body.size()>=body_len) {
- call_deferred("_request_done",RESULT_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray());
- return true;
- }*/
}
return false;
- } break; // request resulted in body: { } break which must be read
+ } break; // Request resulted in body: break which must be read
case HTTPClient::STATUS_CONNECTION_ERROR: {
call_deferred("_request_done", RESULT_CONNECTION_ERROR, 0, PoolStringArray(), PoolByteArray());
return true;
@@ -449,7 +431,7 @@ void HTTPRequest::_notification(int p_what) {
if (done) {
set_process_internal(false);
- //cancel_request(); called from _request done now
+ // cancel_request(); called from _request done now
}
}
@@ -543,7 +525,7 @@ void HTTPRequest::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_threads"), "set_use_threads", "is_using_threads");
ADD_PROPERTY(PropertyInfo(Variant::INT, "body_size_limit", PROPERTY_HINT_RANGE, "-1,2000000000"), "set_body_size_limit", "get_body_size_limit");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_redirects", PROPERTY_HINT_RANGE, "-1,1024"), "set_max_redirects", "get_max_redirects");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_redirects", PROPERTY_HINT_RANGE, "-1,64"), "set_max_redirects", "get_max_redirects");
ADD_SIGNAL(MethodInfo("request_completed", PropertyInfo(Variant::INT, "result"), PropertyInfo(Variant::INT, "response_code"), PropertyInfo(Variant::POOL_STRING_ARRAY, "headers"), PropertyInfo(Variant::POOL_BYTE_ARRAY, "body")));
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 790ff5f7ef..ab5a79c40d 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -42,7 +42,6 @@ class HTTPRequest : public Node {
public:
enum Result {
RESULT_SUCCESS,
- //RESULT_NO_BODY,
RESULT_CHUNKED_BODY_SIZE_MISMATCH,
RESULT_CANT_CONNECT,
RESULT_CANT_RESOLVE,
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 4635de81e8..f5d7043a40 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1421,7 +1421,7 @@ void Viewport::_gui_show_tooltip() {
gui.tooltip_label->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_TOP));
gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -ttp->get_margin(MARGIN_RIGHT));
gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -ttp->get_margin(MARGIN_BOTTOM));
- gui.tooltip_label->set_text(tooltip);
+ gui.tooltip_label->set_text(tooltip.strip_edges());
Rect2 r(gui.tooltip_pos + Point2(10, 10), gui.tooltip_label->get_combined_minimum_size() + ttp->get_minimum_size());
Rect2 vr = gui.tooltip_label->get_viewport_rect();
if (r.size.x + r.position.x > vr.size.x)
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index fe23fbf6b3..aebbb5b562 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/scene/resources/scene_format_text.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "scene_format_text.h"
-
+#include "core/io/resource_format_binary.h"
#include "os/dir_access.h"
#include "project_settings.h"
#include "version.h"
@@ -53,6 +53,60 @@ Ref<Resource> ResourceInteractiveLoaderText::get_resource() {
return resource;
}
+Error ResourceInteractiveLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
+
+ VariantParser::Token token;
+ VariantParser::get_token(p_stream, token, line, r_err_str);
+ if (token.type != VariantParser::TK_NUMBER) {
+ r_err_str = "Expected number (sub-resource index)";
+ return ERR_PARSE_ERROR;
+ }
+
+ int index = token.value;
+
+ if (!p_data->resource_map.has(index)) {
+ Ref<DummyResource> dr;
+ dr.instance();
+ dr->set_subindex(index);
+ p_data->resource_map[index] = dr;
+ p_data->resource_set.insert(dr);
+ }
+
+ r_res = p_data->resource_map[index];
+
+ VariantParser::get_token(p_stream, token, line, r_err_str);
+ if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
+ r_err_str = "Expected ')'";
+ return ERR_PARSE_ERROR;
+ }
+
+ return OK;
+}
+
+Error ResourceInteractiveLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
+
+ VariantParser::Token token;
+ VariantParser::get_token(p_stream, token, line, r_err_str);
+ if (token.type != VariantParser::TK_NUMBER) {
+ r_err_str = "Expected number (sub-resource index)";
+ return ERR_PARSE_ERROR;
+ }
+
+ int id = token.value;
+
+ ERR_FAIL_COND_V(!p_data->rev_external_resources.has(id), ERR_PARSE_ERROR);
+
+ r_res = p_data->rev_external_resources[id];
+
+ VariantParser::get_token(p_stream, token, line, r_err_str);
+ if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
+ r_err_str = "Expected ')'";
+ return ERR_PARSE_ERROR;
+ }
+
+ return OK;
+}
+
Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
VariantParser::Token token;
@@ -131,6 +185,203 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream *
return OK;
}
+Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::ResourceParser &parser) {
+ Ref<PackedScene> packed_scene;
+ packed_scene.instance();
+
+ while (true) {
+
+ if (next_tag.name == "node") {
+
+ int parent = -1;
+ int owner = -1;
+ int type = -1;
+ int name = -1;
+ int instance = -1;
+ //int base_scene=-1;
+
+ if (next_tag.fields.has("name")) {
+ name = packed_scene->get_state()->add_name(next_tag.fields["name"]);
+ }
+
+ if (next_tag.fields.has("parent")) {
+ NodePath np = next_tag.fields["parent"];
+ np.prepend_period(); //compatible to how it manages paths internally
+ parent = packed_scene->get_state()->add_node_path(np);
+ }
+
+ if (next_tag.fields.has("type")) {
+ type = packed_scene->get_state()->add_name(next_tag.fields["type"]);
+ } else {
+ type = SceneState::TYPE_INSTANCED; //no type? assume this was instanced
+ }
+
+ if (next_tag.fields.has("instance")) {
+
+ instance = packed_scene->get_state()->add_value(next_tag.fields["instance"]);
+
+ if (packed_scene->get_state()->get_node_count() == 0 && parent == -1) {
+ packed_scene->get_state()->set_base_scene(instance);
+ instance = -1;
+ }
+ }
+
+ if (next_tag.fields.has("instance_placeholder")) {
+
+ String path = next_tag.fields["instance_placeholder"];
+
+ int path_v = packed_scene->get_state()->add_value(path);
+
+ if (packed_scene->get_state()->get_node_count() == 0) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Instance Placeholder can't be used for inheritance.";
+ _printerr();
+ return Ref<PackedScene>();
+ }
+
+ instance = path_v | SceneState::FLAG_INSTANCE_IS_PLACEHOLDER;
+ }
+
+ if (next_tag.fields.has("owner")) {
+ owner = packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
+ } else {
+ if (parent != -1 && !(type == SceneState::TYPE_INSTANCED && instance == -1))
+ owner = 0; //if no owner, owner is root
+ }
+
+ int node_id = packed_scene->get_state()->add_node(parent, owner, type, name, instance);
+
+ if (next_tag.fields.has("groups")) {
+
+ Array groups = next_tag.fields["groups"];
+ for (int i = 0; i < groups.size(); i++) {
+ packed_scene->get_state()->add_node_group(node_id, packed_scene->get_state()->add_name(groups[i]));
+ }
+ }
+
+ while (true) {
+
+ String assign;
+ Variant value;
+
+ error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &parser);
+
+ if (error) {
+ if (error != ERR_FILE_EOF) {
+ _printerr();
+ return Ref<PackedScene>();
+ } else {
+ return packed_scene;
+ }
+ }
+
+ if (assign != String()) {
+ int nameidx = packed_scene->get_state()->add_name(assign);
+ int valueidx = packed_scene->get_state()->add_value(value);
+ packed_scene->get_state()->add_node_property(node_id, nameidx, valueidx);
+ //it's assignment
+ } else if (next_tag.name != String()) {
+ break;
+ }
+ }
+ } else if (next_tag.name == "connection") {
+
+ if (!next_tag.fields.has("from")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "missing 'from' field fron connection tag";
+ return Ref<PackedScene>();
+ }
+
+ if (!next_tag.fields.has("to")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "missing 'to' field fron connection tag";
+ return Ref<PackedScene>();
+ }
+
+ if (!next_tag.fields.has("signal")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "missing 'signal' field fron connection tag";
+ return Ref<PackedScene>();
+ }
+
+ if (!next_tag.fields.has("method")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "missing 'method' field fron connection tag";
+ return Ref<PackedScene>();
+ }
+
+ NodePath from = next_tag.fields["from"];
+ NodePath to = next_tag.fields["to"];
+ StringName method = next_tag.fields["method"];
+ StringName signal = next_tag.fields["signal"];
+ int flags = CONNECT_PERSIST;
+ Array binds;
+
+ if (next_tag.fields.has("flags")) {
+ flags = next_tag.fields["flags"];
+ }
+
+ if (next_tag.fields.has("binds")) {
+ binds = next_tag.fields["binds"];
+ }
+
+ Vector<int> bind_ints;
+ for (int i = 0; i < binds.size(); i++) {
+ bind_ints.push_back(packed_scene->get_state()->add_value(binds[i]));
+ }
+
+ packed_scene->get_state()->add_connection(
+ packed_scene->get_state()->add_node_path(from.simplified()),
+ packed_scene->get_state()->add_node_path(to.simplified()),
+ packed_scene->get_state()->add_name(signal),
+ packed_scene->get_state()->add_name(method),
+ flags,
+ bind_ints);
+
+ error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &parser);
+
+ if (error) {
+ if (error != ERR_FILE_EOF) {
+ _printerr();
+ return Ref<PackedScene>();
+ } else {
+ return packed_scene;
+ }
+ }
+ } else if (next_tag.name == "editable") {
+
+ if (!next_tag.fields.has("path")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "missing 'path' field fron connection tag";
+ _printerr();
+ return Ref<PackedScene>();
+ }
+
+ NodePath path = next_tag.fields["path"];
+
+ packed_scene->get_state()->add_editable_instance(path.simplified());
+
+ error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &parser);
+
+ if (error) {
+ if (error != ERR_FILE_EOF) {
+ _printerr();
+ return Ref<PackedScene>();
+ } else {
+ return packed_scene;
+ }
+ }
+ } else {
+
+ error = ERR_FILE_CORRUPT;
+ _printerr();
+ return Ref<PackedScene>();
+ }
+ }
+
+ return packed_scene;
+}
+
Error ResourceInteractiveLoaderText::poll() {
if (error != OK)
@@ -364,231 +615,21 @@ Error ResourceInteractiveLoaderText::poll() {
return error;
}
- /*
- int add_name(const StringName& p_name);
- int add_value(const Variant& p_value);
- int add_node_path(const NodePath& p_path);
- int add_node(int p_parent,int p_owner,int p_type,int p_name, int p_instance);
- void add_node_property(int p_node,int p_name,int p_value);
- void add_node_group(int p_node,int p_group);
- void set_base_scene(int p_idx);
- void add_connection(int p_from,int p_to, int p_signal, int p_method, int p_flags,const Vector<int>& p_binds);
- void add_editable_instance(const NodePath& p_path);
-
- */
-
- int parent = -1;
- int owner = -1;
- int type = -1;
- int name = -1;
- int instance = -1;
- //int base_scene=-1;
-
- if (next_tag.fields.has("name")) {
- name = packed_scene->get_state()->add_name(next_tag.fields["name"]);
- }
-
- if (next_tag.fields.has("parent")) {
- NodePath np = next_tag.fields["parent"];
- np.prepend_period(); //compatible to how it manages paths internally
- parent = packed_scene->get_state()->add_node_path(np);
- }
-
- if (next_tag.fields.has("type")) {
- type = packed_scene->get_state()->add_name(next_tag.fields["type"]);
- } else {
- type = SceneState::TYPE_INSTANCED; //no type? assume this was instanced
- }
-
- if (next_tag.fields.has("instance")) {
-
- instance = packed_scene->get_state()->add_value(next_tag.fields["instance"]);
-
- if (packed_scene->get_state()->get_node_count() == 0 && parent == -1) {
- packed_scene->get_state()->set_base_scene(instance);
- instance = -1;
- }
- }
-
- if (next_tag.fields.has("instance_placeholder")) {
-
- String path = next_tag.fields["instance_placeholder"];
-
- int path_v = packed_scene->get_state()->add_value(path);
-
- if (packed_scene->get_state()->get_node_count() == 0) {
- error = ERR_FILE_CORRUPT;
- error_text = "Instance Placeholder can't be used for inheritance.";
- _printerr();
- return error;
- }
-
- instance = path_v | SceneState::FLAG_INSTANCE_IS_PLACEHOLDER;
- }
-
- if (next_tag.fields.has("owner")) {
- owner = packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
- } else {
- if (parent != -1 && !(type == SceneState::TYPE_INSTANCED && instance == -1))
- owner = 0; //if no owner, owner is root
- }
-
- int node_id = packed_scene->get_state()->add_node(parent, owner, type, name, instance);
-
- if (next_tag.fields.has("groups")) {
-
- Array groups = next_tag.fields["groups"];
- for (int i = 0; i < groups.size(); i++) {
- packed_scene->get_state()->add_node_group(node_id, packed_scene->get_state()->add_name(groups[i]));
- }
- }
-
- while (true) {
-
- String assign;
- Variant value;
-
- error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
-
- if (error) {
- if (error != ERR_FILE_EOF) {
- _printerr();
- } else {
- resource = packed_scene;
- if (!ResourceCache::has(res_path)) {
- packed_scene->set_path(res_path);
- }
- }
- return error;
- }
-
- if (assign != String()) {
- int nameidx = packed_scene->get_state()->add_name(assign);
- int valueidx = packed_scene->get_state()->add_value(value);
- packed_scene->get_state()->add_node_property(node_id, nameidx, valueidx);
- //it's assignment
- } else if (next_tag.name != String()) {
-
- error = OK;
- return error;
- } else {
-
- resource = packed_scene;
- error = ERR_FILE_EOF;
- return error;
- }
- }
-
- return OK;
-
- } else if (next_tag.name == "connection") {
-
- if (!is_scene) {
-
- error_text += "found the 'connection' tag on a resource file!";
- _printerr();
- error = ERR_FILE_CORRUPT;
- return error;
- }
-
- if (!next_tag.fields.has("from")) {
- error = ERR_FILE_CORRUPT;
- error_text = "missing 'from' field fron connection tag";
- return error;
- }
-
- if (!next_tag.fields.has("to")) {
- error = ERR_FILE_CORRUPT;
- error_text = "missing 'to' field fron connection tag";
- return error;
- }
-
- if (!next_tag.fields.has("signal")) {
- error = ERR_FILE_CORRUPT;
- error_text = "missing 'signal' field fron connection tag";
- return error;
- }
-
- if (!next_tag.fields.has("method")) {
- error = ERR_FILE_CORRUPT;
- error_text = "missing 'method' field fron connection tag";
- return error;
- }
-
- NodePath from = next_tag.fields["from"];
- NodePath to = next_tag.fields["to"];
- StringName method = next_tag.fields["method"];
- StringName signal = next_tag.fields["signal"];
- int flags = CONNECT_PERSIST;
- Array binds;
-
- if (next_tag.fields.has("flags")) {
- flags = next_tag.fields["flags"];
- }
-
- if (next_tag.fields.has("binds")) {
- binds = next_tag.fields["binds"];
- }
-
- Vector<int> bind_ints;
- for (int i = 0; i < binds.size(); i++) {
- bind_ints.push_back(packed_scene->get_state()->add_value(binds[i]));
- }
-
- packed_scene->get_state()->add_connection(
- packed_scene->get_state()->add_node_path(from.simplified()),
- packed_scene->get_state()->add_node_path(to.simplified()),
- packed_scene->get_state()->add_name(signal),
- packed_scene->get_state()->add_name(method),
- flags,
- bind_ints);
-
- error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
-
- if (error) {
- if (error != ERR_FILE_EOF) {
- _printerr();
- } else {
- resource = packed_scene;
- }
- }
-
- return error;
- } else if (next_tag.name == "editable") {
+ Ref<PackedScene> packed_scene = _parse_node_tag(rp);
- if (!is_scene) {
-
- error_text += "found the 'editable' tag on a resource file!";
- _printerr();
- error = ERR_FILE_CORRUPT;
+ if (!packed_scene.is_valid())
return error;
- }
- if (!next_tag.fields.has("path")) {
- error = ERR_FILE_CORRUPT;
- error_text = "missing 'path' field fron connection tag";
- _printerr();
- return error;
+ error = OK;
+ //get it here
+ resource = packed_scene;
+ if (!ResourceCache::has(res_path)) {
+ packed_scene->set_path(res_path);
}
- NodePath path = next_tag.fields["path"];
-
- packed_scene->get_state()->add_editable_instance(path.simplified());
-
- error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
-
- if (error) {
- if (error != ERR_FILE_EOF) {
- _printerr();
- } else {
- resource = packed_scene;
- }
- }
-
- return error;
+ return ERR_FILE_EOF;
} else {
-
error_text += "Unknown tag in file: " + next_tag.name;
_printerr();
error = ERR_FILE_CORRUPT;
@@ -804,7 +845,6 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f, bool p_skip_first_tag)
if (tag.name == "gd_scene") {
is_scene = true;
- packed_scene.instance();
} else if (tag.name == "gd_resource") {
if (!tag.fields.has("type")) {
@@ -846,6 +886,281 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f, bool p_skip_first_tag)
rp.userdata = this;
}
+static void bs_save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false) {
+
+ CharString utf8 = p_string.utf8();
+ if (p_bit_on_len) {
+ f->store_32(utf8.length() + 1 | 0x80000000);
+ } else {
+ f->store_32(utf8.length() + 1);
+ }
+ f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
+}
+
+Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) {
+
+ if (error)
+ return error;
+
+ FileAccessRef wf = FileAccess::open(p_path, FileAccess::WRITE);
+ if (!wf) {
+ return ERR_CANT_OPEN;
+ }
+
+ //save header compressed
+ static const uint8_t header[4] = { 'R', 'S', 'R', 'C' };
+ wf->store_buffer(header, 4);
+
+ wf->store_32(0); //endianness, little endian
+ wf->store_32(0); //64 bits file, false for now
+ wf->store_32(VERSION_MAJOR);
+ wf->store_32(VERSION_MINOR);
+ static const int save_format_version = 3; //use format version 3 for saving
+ wf->store_32(save_format_version);
+
+ bs_save_unicode_string(wf.f, is_scene ? "PackedScene" : resource_type);
+ wf->store_64(0); //offset to import metadata, this is no longer used
+ for (int i = 0; i < 14; i++)
+ wf->store_32(0); // reserved
+
+ wf->store_32(0); //string table size, will not be in use
+ size_t ext_res_count_pos = wf->get_position();
+
+ wf->store_32(0); //zero ext resources, still parsing them
+
+ //go with external resources
+
+ DummyReadData dummy_read;
+ VariantParser::ResourceParser rp;
+ rp.ext_func = _parse_ext_resource_dummys;
+ rp.sub_func = _parse_sub_resource_dummys;
+ rp.userdata = &dummy_read;
+
+ while (next_tag.name == "ext_resource") {
+
+ if (!next_tag.fields.has("path")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Missing 'path' in external resource tag";
+ _printerr();
+ return error;
+ }
+
+ if (!next_tag.fields.has("type")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Missing 'type' in external resource tag";
+ _printerr();
+ return error;
+ }
+
+ if (!next_tag.fields.has("id")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Missing 'id' in external resource tag";
+ _printerr();
+ return error;
+ }
+
+ String path = next_tag.fields["path"];
+ String type = next_tag.fields["type"];
+ int index = next_tag.fields["id"];
+
+ bs_save_unicode_string(wf.f, type);
+ bs_save_unicode_string(wf.f, path);
+
+ int lindex = dummy_read.external_resources.size();
+ Ref<DummyResource> dr;
+ dr.instance();
+ dr->set_path("res://dummy" + itos(lindex)); //anything is good to detect it for saving as external
+ dummy_read.external_resources[dr] = lindex;
+ dummy_read.rev_external_resources[index] = dr;
+
+ error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
+
+ if (error) {
+ _printerr();
+ return error;
+ }
+ }
+
+ // save external resource table
+ wf->seek(ext_res_count_pos);
+ wf->store_32(dummy_read.external_resources.size());
+ wf->seek_end();
+
+ //now, save resources to a separate file, for now
+
+ size_t sub_res_count_pos = wf->get_position();
+ wf->store_32(0); //zero sub resources, still parsing them
+
+ String temp_file = p_path + ".temp";
+ FileAccessRef wf2 = FileAccess::open(temp_file, FileAccess::WRITE);
+ if (!wf2) {
+ return ERR_CANT_OPEN;
+ }
+
+ Vector<size_t> local_offsets;
+ Vector<size_t> local_pointers_pos;
+
+ while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
+
+ String type;
+ int id = -1;
+ bool main_res;
+
+ if (next_tag.name == "sub_resource") {
+ if (!next_tag.fields.has("type")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Missing 'type' in external resource tag";
+ _printerr();
+ return error;
+ }
+
+ if (!next_tag.fields.has("id")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Missing 'index' in external resource tag";
+ _printerr();
+ return error;
+ }
+
+ type = next_tag.fields["type"];
+ id = next_tag.fields["id"];
+ main_res = false;
+ } else {
+ type = res_type;
+ id = 0; //used for last anyway
+ main_res = true;
+ }
+
+ local_offsets.push_back(wf2->get_position());
+
+ bs_save_unicode_string(wf, "local://" + itos(id));
+ local_pointers_pos.push_back(wf->get_position());
+ wf->store_64(0); //temp local offset
+
+ bs_save_unicode_string(wf2, type);
+ size_t propcount_ofs = wf2->get_position();
+ wf2->store_32(0);
+
+ int prop_count = 0;
+
+ while (true) {
+
+ String assign;
+ Variant value;
+
+ error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
+
+ if (error) {
+ if (main_res && error == ERR_FILE_EOF) {
+ next_tag.name = ""; //exit
+ break;
+ }
+
+ _printerr();
+ return error;
+ }
+
+ if (assign != String()) {
+
+ Map<StringName, int> empty_string_map; //unused
+ bs_save_unicode_string(wf2, assign, true);
+ ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_set, dummy_read.external_resources, empty_string_map);
+ prop_count++;
+
+ } else if (next_tag.name != String()) {
+
+ error = OK;
+ break;
+ } else {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Premature end of file while parsing [sub_resource]";
+ _printerr();
+ return error;
+ }
+ }
+
+ wf2->seek(propcount_ofs);
+ wf2->store_32(prop_count);
+ wf2->seek_end();
+ }
+
+ if (next_tag.name == "node") {
+ //this is a node, must save one more!
+
+ if (!is_scene) {
+
+ error_text += "found the 'node' tag on a resource file!";
+ _printerr();
+ error = ERR_FILE_CORRUPT;
+ return error;
+ }
+
+ Ref<PackedScene> packed_scene = _parse_node_tag(rp);
+
+ if (!packed_scene.is_valid())
+ return error;
+
+ error = OK;
+ //get it here
+ List<PropertyInfo> props;
+ packed_scene->get_property_list(&props);
+
+ bs_save_unicode_string(wf, "local://0");
+ local_pointers_pos.push_back(wf->get_position());
+ wf->store_64(0); //temp local offset
+
+ local_offsets.push_back(wf2->get_position());
+ bs_save_unicode_string(wf2, "PackedScene");
+ size_t propcount_ofs = wf2->get_position();
+ wf2->store_32(0);
+
+ int prop_count = 0;
+
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
+ continue;
+
+ String name = E->get().name;
+ Variant value = packed_scene->get(name);
+
+ Map<StringName, int> empty_string_map; //unused
+ bs_save_unicode_string(wf2, name, true);
+ ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_set, dummy_read.external_resources, empty_string_map);
+ prop_count++;
+ }
+
+ wf2->seek(propcount_ofs);
+ wf2->store_32(prop_count);
+ wf2->seek_end();
+ }
+
+ wf2->close();
+
+ size_t offset_from = wf->get_position();
+ wf->seek(sub_res_count_pos); //plus one because the saved one
+ wf->store_32(local_offsets.size());
+
+ for (int i = 0; i < local_offsets.size(); i++) {
+ wf->seek(local_pointers_pos[i]);
+ wf->store_64(local_offsets[i] + offset_from);
+ }
+
+ wf->seek_end();
+
+ Vector<uint8_t> data = FileAccess::get_file_as_array(temp_file);
+ wf->store_buffer(data.ptr(), data.size());
+ {
+ DirAccessRef dar = DirAccess::open(temp_file.get_base_dir());
+ dar->remove(temp_file);
+ }
+
+ wf->store_buffer((const uint8_t *)"RSRC", 4); //magic at end
+
+ wf->close();
+
+ return OK;
+}
+
String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) {
error = OK;
@@ -991,6 +1306,25 @@ Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const
return ria->rename_dependencies(f, p_path, p_map);
}
+Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, const String &p_dst_path) {
+
+ Error err;
+ FileAccess *f = FileAccess::open(p_src_path, FileAccess::READ, &err);
+
+ if (err != OK) {
+
+ ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
+ }
+
+ Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText);
+ String path = p_src_path;
+ ria->local_path = ProjectSettings::get_singleton()->localize_path(path);
+ ria->res_path = ria->local_path;
+ //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
+ ria->open(f);
+ return ria->save_as_binary(f, p_dst_path);
+}
+
/*****************************************************************************************************/
/*****************************************************************************************************/
/*****************************************************************************************************/
diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h
index a72a62037c..5d3c2004c1 100644
--- a/scene/resources/scene_format_text.h
+++ b/scene/resources/scene_format_text.h
@@ -78,9 +78,26 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader {
Error _parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
Error _parse_ext_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
- VariantParser::ResourceParser rp;
+ // for converter
+ class DummyResource : public Resource {
+ public:
+ };
- Ref<PackedScene> packed_scene;
+ struct DummyReadData {
+
+ Map<RES, int> external_resources;
+ Map<int, RES> rev_external_resources;
+ Set<RES> resource_set;
+ Map<int, RES> resource_map;
+ };
+
+ static Error _parse_sub_resource_dummys(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return _parse_sub_resource_dummy((DummyReadData *)(p_self), p_stream, r_res, line, r_err_str); }
+ static Error _parse_ext_resource_dummys(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return _parse_ext_resource_dummy((DummyReadData *)(p_self), p_stream, r_res, line, r_err_str); }
+
+ static Error _parse_sub_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
+ static Error _parse_ext_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
+
+ VariantParser::ResourceParser rp;
friend class ResourceFormatLoaderText;
@@ -89,6 +106,8 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader {
RES resource;
+ Ref<PackedScene> _parse_node_tag(VariantParser::ResourceParser &parser);
+
public:
virtual void set_local_path(const String &p_local_path);
virtual Ref<Resource> get_resource();
@@ -102,6 +121,7 @@ public:
void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
Error rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map);
+ Error save_as_binary(FileAccess *p_f, const String &p_path);
ResourceInteractiveLoaderText();
~ResourceInteractiveLoaderText();
};
@@ -115,6 +135,8 @@ public:
virtual String get_resource_type(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
+
+ static Error convert_file_to_binary(const String &p_src_path, const String &p_dst_path);
};
class ResourceFormatSaverTextInstance {
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index e10a57c571..c69bbb9343 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -755,12 +755,12 @@ void ShaderLanguage::clear() {
}
}
-bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type) {
+bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type) {
if (p_builtin_types.has(p_identifier)) {
if (r_data_type) {
- *r_data_type = p_builtin_types[p_identifier];
+ *r_data_type = p_builtin_types[p_identifier].type;
}
if (r_type) {
*r_type = IDENTIFIER_BUILTIN_VAR;
@@ -2008,7 +2008,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
return false;
}
-bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) {
+bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) {
TkPos pos = _get_tkpos();
Token tk = _get_token();
@@ -2261,7 +2261,48 @@ bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionT
return false;
}
-ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types) {
+bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
+ switch (p_op) {
+ case OP_ASSIGN:
+ case OP_ASSIGN_ADD:
+ case OP_ASSIGN_SUB:
+ case OP_ASSIGN_MUL:
+ case OP_ASSIGN_DIV:
+ case OP_ASSIGN_MOD:
+ case OP_ASSIGN_SHIFT_LEFT:
+ case OP_ASSIGN_SHIFT_RIGHT:
+ case OP_ASSIGN_BIT_AND:
+ case OP_ASSIGN_BIT_OR:
+ case OP_ASSIGN_BIT_XOR:
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types) {
+
+ if (p_node->type == Node::TYPE_OPERATOR) {
+
+ OperatorNode *op = static_cast<OperatorNode *>(p_node);
+ if (op->type == OP_INDEX) {
+ return _validate_assign(op->arguments[0], p_builtin_types);
+ }
+ }
+
+ if (p_node->type == Node::TYPE_VARIABLE) {
+
+ VariableNode *var = static_cast<VariableNode *>(p_node);
+ if (p_builtin_types.has(var->name) && p_builtin_types[var->name].constant) {
+ return false; //ops not valid
+ }
+ }
+ return true;
+}
+
+ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
Vector<Expression> expression;
//Vector<TokenType> operators;
@@ -2765,6 +2806,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Invalid base type for increment/decrement operator");
return NULL;
}
+
+ if (!_validate_assign(expr, p_builtin_types)) {
+ _set_error("Invalid use of increment/decrement operator in constant expression.");
+ return NULL;
+ }
expr = op;
} else {
@@ -2948,6 +2994,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
OperatorNode *op = alloc_node<OperatorNode>();
op->op = expression[i].op;
+ if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_builtin_types)) {
+
+ _set_error("Can't use increment/decrement operator in constant expression.");
+ return NULL;
+ }
op->arguments.push_back(expression[i + 1].node);
expression[i].is_op = false;
@@ -3019,6 +3070,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_V(NULL);
}
+ if (_is_operator_assign(op->op) && !_validate_assign(expression[next_op - 1].node, p_builtin_types)) {
+
+ _set_error("Assignment to constant expression.");
+ return NULL;
+ }
+
if (expression[next_op + 1].is_op) {
// this is not invalid and can really appear
// but it becomes invalid anyway because no binary op
@@ -3142,7 +3199,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
return p_node;
}
-ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types) {
+ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
ShaderLanguage::Node *expr = _parse_expression(p_block, p_builtin_types);
if (!expr) //errored
@@ -3153,7 +3210,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_
return expr;
}
-Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) {
+Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) {
while (true) {
@@ -3636,7 +3693,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
name = tk.text;
- if (_find_identifier(NULL, Map<StringName, DataType>(), name)) {
+ if (_find_identifier(NULL, Map<StringName, BuiltInInfo>(), name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -3660,7 +3717,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
- Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, DataType>());
+ Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>());
if (!expr)
return ERR_PARSE_ERROR;
if (expr->type != Node::TYPE_CONSTANT) {
@@ -3841,7 +3898,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (_find_identifier(NULL, Map<StringName, DataType>(), name)) {
+ if (_find_identifier(NULL, Map<StringName, BuiltInInfo>(), name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -3852,7 +3909,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- Map<StringName, DataType> builtin_types;
+ Map<StringName, BuiltInInfo> builtin_types;
if (p_functions.has(name)) {
builtin_types = p_functions[name].built_ins;
}
@@ -4109,7 +4166,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
if (comp_ident && skip_function != StringName() && p_functions.has(skip_function)) {
- for (Map<StringName, DataType>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) {
+ for (Map<StringName, BuiltInInfo>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) {
matches.insert(E->key());
}
}
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index e092bf931f..4cf8560990 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -537,8 +537,18 @@ public:
static void get_keyword_list(List<String> *r_keywords);
static void get_builtin_funcs(List<String> *r_keywords);
+ struct BuiltInInfo {
+ DataType type;
+ bool constant;
+ BuiltInInfo() {}
+ BuiltInInfo(DataType p_type, bool p_constant = false) {
+ type = p_type;
+ constant = p_constant;
+ }
+ };
+
struct FunctionInfo {
- Map<StringName, DataType> built_ins;
+ Map<StringName, BuiltInInfo> built_ins;
bool can_discard;
};
@@ -601,7 +611,10 @@ private:
IDENTIFIER_BUILTIN_VAR,
};
- bool _find_identifier(const BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL);
+ bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL);
+
+ bool _is_operator_assign(Operator p_op) const;
+ bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types);
bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL);
@@ -625,14 +638,14 @@ private:
static const BuiltinFuncDef builtin_func_defs[];
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
- bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
+ bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
- Node *_parse_expression(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types);
+ Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
- Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types);
+ Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
- Error _parse_block(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
+ Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types);
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 7489ca7e3e..a25c5ca65e 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -45,6 +45,11 @@ const Set<String> &ShaderTypes::get_types() {
ShaderTypes *ShaderTypes::singleton = NULL;
+static ShaderLanguage::BuiltInInfo constt(ShaderLanguage::DataType p_type) {
+
+ return ShaderLanguage::BuiltInInfo(p_type, true);
+}
+
ShaderTypes::ShaderTypes() {
singleton = this;
@@ -58,32 +63,32 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = ShaderLanguage::TYPE_INT;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].can_discard = false;
//builtins
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = ShaderLanguage::TYPE_VEC4;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRONT_FACING"] = ShaderLanguage::TYPE_BOOL;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRONT_FACING"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["METALLIC"] = ShaderLanguage::TYPE_FLOAT;
@@ -103,33 +108,33 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SIDE"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SIDE"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].can_discard = true;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2;
-
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
+
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3;
@@ -177,38 +182,38 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["EXTRA_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = ShaderLanguage::TYPE_VEC4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["EXTRA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VEC"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_HEIGHT"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC4;
@@ -216,8 +221,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_SHADOW"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW"] = ShaderLanguage::TYPE_VEC4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true;
shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("skip_vertex_transform");
@@ -237,16 +242,16 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["MASS"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["ACTIVE"] = ShaderLanguage::TYPE_BOOL;
- shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RESTART"] = ShaderLanguage::TYPE_BOOL;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RESTART"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["CUSTOM"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["TRANSFORM"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["LIFETIME"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["DELTA"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["NUMBER"] = ShaderLanguage::TYPE_UINT;
- shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["INDEX"] = ShaderLanguage::TYPE_INT;
- shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["EMISSION_TRANSFORM"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RANDOM_SEED"] = ShaderLanguage::TYPE_UINT;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT);
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[VS::SHADER_PARTICLES].functions["vertex"].can_discard = false;
shader_modes[VS::SHADER_PARTICLES].modes.insert("billboard");
diff --git a/thirdparty/README.md b/thirdparty/README.md
index fbce76fcc7..8c50081782 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -62,8 +62,8 @@ Use UI font if exists, because it has tight vertical metrics and good for UI.
### Hack Regular
- Upstream: https://github.com/source-foundry/Hack
-- Version: 2.020
-- License: Hack Open Font License v2.0
+- Version: 3.000
+- License: MIT + Bitstream Vera License
### DroidSans*.ttf
@@ -272,7 +272,7 @@ Collection of single-file libraries used in Godot components.
### poshlib
- Upstream: http://poshlib.hookatooka.com/poshlib/trac.cgi (username guest, password guest123)
-- Version: 1.3.002
+- Version: 1.3.002
- License: MIT
Files extracted from the upstream source:
@@ -308,6 +308,10 @@ Files extracted from the upstream source:
- Relevant sources from src/
- License.txt
+Important: Some files have Godot-made changes, those
+changes are marked with `// -- GODOT --` comments.
+
+
## nanosvg
- Upstream: https://github.com/memononen/nanosvg
diff --git a/thirdparty/fonts/Hack_Regular.ttf b/thirdparty/fonts/Hack_Regular.ttf
index a35ea2e4f4..f342700811 100644
--- a/thirdparty/fonts/Hack_Regular.ttf
+++ b/thirdparty/fonts/Hack_Regular.ttf
Binary files differ
diff --git a/thirdparty/fonts/LICENSE_Hack.md b/thirdparty/fonts/LICENSE_Hack.md
index e9fc8a1f87..ddd23a2b81 100644
--- a/thirdparty/fonts/LICENSE_Hack.md
+++ b/thirdparty/fonts/LICENSE_Hack.md
@@ -1,49 +1,30 @@
-## License
+The work in the Hack project is Copyright 2017 Source Foundry Authors and licensed under the MIT License
-Hack Copyright 2015, Christopher Simpkins with Reserved Font Name "Hack".
+The work in the DejaVu project was committed to the public domain.
Bitstream Vera Sans Mono Copyright 2003 Bitstream Inc. and licensed under the Bitstream Vera License with Reserved Font Names "Bitstream" and "Vera"
-DejaVu modifications of the original Bitstream Vera Sans Mono typeface have been committed to the public domain.
+### MIT License
+Copyright (c) 2017 Source Foundry Authors
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
-This Font Software is licensed under the Hack Open Font License v2.0 and the Bitstream Vera License.
-
-These licenses are copied below.
-
-
-### Hack Open Font License v2.0
-
-(Version 1.0 - 06 September 2015)
-
-(Version 2.0 - 27 September 2015)
-
-Copyright 2015 by Christopher Simpkins. All Rights Reserved.
-
-DEFINITIONS
-
-"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
-
-PERMISSION AND CONDITIONS
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated source code, documentation, and binary files (the "Font Software"), to reproduce and distribute the modifications to the Bitstream Vera Font Software, including without limitation the rights to use, study, copy, merge, embed, modify, redistribute, and/or sell modified or unmodified copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
-
-(1) The above copyright notice and this permission notice shall be included in all modified and unmodified copies of the Font Software typefaces. These notices can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
-
-(2) The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing the word "Hack".
-
-(3) Neither the Font Software nor any of its individual components, in original or modified versions, may be sold by itself.
-
-TERMINATION
-
-This license becomes null and void if any of the above conditions are not met.
-
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
-
-Except as contained in this notice, the names of Christopher Simpkins and the Author(s) of the Font Software shall not be used to promote, endorse or advertise any modified version, except to acknowledge the contribution(s) of Christopher Simpkins and the Author(s) or with their explicit written permission. For further information, contact: chris at sourcefoundry dot org.
-
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
### BITSTREAM VERA LICENSE
diff --git a/thirdparty/thekla_atlas/nvcore/Debug.cpp b/thirdparty/thekla_atlas/nvcore/Debug.cpp
index 113c551de8..4980ffa916 100644
--- a/thirdparty/thekla_atlas/nvcore/Debug.cpp
+++ b/thirdparty/thekla_atlas/nvcore/Debug.cpp
@@ -14,6 +14,7 @@
# define VC_EXTRALEAN
# include <windows.h>
# include <direct.h>
+// -- GODOT start -
# include <crtdbg.h>
# if _MSC_VER < 1300
# define DECLSPEC_DEPRECATED
@@ -24,6 +25,7 @@
// VC7: ships with updated headers
# include <dbghelp.h>
# endif
+// -- GODOT end -
# pragma comment(lib,"dbghelp.lib")
#endif
@@ -107,8 +109,9 @@ namespace
#endif
-
+// -- GODOT start -
#if NV_OS_WIN32 || NV_OS_DURANGO
+// -- GODOT end -
// We should try to simplify the top level filter as much as possible.
// http://www.nynaeve.net/?p=128
@@ -391,8 +394,10 @@ namespace
#pragma warning(disable:4748)
static NV_NOINLINE int backtrace(void * trace[], int maxcount) {
CONTEXT ctx = { 0 };
+// -- GODOT start --
#if NV_CPU_X86 && !NV_CPU_X86_64
ctx.ContextFlags = CONTEXT_CONTROL;
+#if NV_CC_MSVC
_asm {
call x
x: pop eax
@@ -401,6 +406,13 @@ namespace
mov ctx.Esp, esp
}
#else
+ register long unsigned int ebp asm("ebp");
+ ctx.Eip = (DWORD) __builtin_return_address(0);
+ ctx.Ebp = ebp;
+ ctx.Esp = (DWORD) __builtin_frame_address(0);
+#endif
+// -- GODOT end --
+#else
RtlCaptureContext(&ctx); // Not implemented correctly in x86.
#endif
diff --git a/thirdparty/thekla_atlas/nvcore/DefsGnucWin32.h b/thirdparty/thekla_atlas/nvcore/DefsGnucWin32.h
index 4f97b90f3a..e1c8d6e4f8 100644
--- a/thirdparty/thekla_atlas/nvcore/DefsGnucWin32.h
+++ b/thirdparty/thekla_atlas/nvcore/DefsGnucWin32.h
@@ -19,7 +19,9 @@
#endif
#define NV_FASTCALL __attribute__((fastcall))
+// -- GODOT start -
#define NV_FORCEINLINE __attribute__((always_inline)) inline
+// -- GODOT end -
#define NV_DEPRECATED __attribute__((deprecated))
#if __GNUC__ > 2
diff --git a/thirdparty/thekla_atlas/nvmath/ftoi.h b/thirdparty/thekla_atlas/nvmath/ftoi.h
index bee15c0908..182c56d1c3 100644
--- a/thirdparty/thekla_atlas/nvmath/ftoi.h
+++ b/thirdparty/thekla_atlas/nvmath/ftoi.h
@@ -53,7 +53,10 @@ namespace nv
return (val<0) ? ftoi_ceil_xs(val) : ftoi_floor_xs(val);
}
-#if NV_CPU_X86 || NV_CPU_X86_64
+// -- GODOT start --
+//#if NV_CPU_X86 || NV_CPU_X86_64
+#if NV_USE_SSE
+// -- GODOT end --
NV_FORCEINLINE int ftoi_round_sse(float f) {
return _mm_cvt_ss2si(_mm_set_ss(f));
diff --git a/thirdparty/thekla_atlas/nvmath/nvmath.h b/thirdparty/thekla_atlas/nvmath/nvmath.h
index 695f452c1d..f2b69426e1 100644
--- a/thirdparty/thekla_atlas/nvmath/nvmath.h
+++ b/thirdparty/thekla_atlas/nvmath/nvmath.h
@@ -14,10 +14,12 @@
#include <float.h> // finite, isnan
#endif
-#if NV_CPU_X86 || NV_CPU_X86_64
- //#include <intrin.h>
- #include <xmmintrin.h>
-#endif
+// -- GODOT start --
+//#if NV_CPU_X86 || NV_CPU_X86_64
+// //#include <intrin.h>
+// #include <xmmintrin.h>
+//#endif
+// -- GODOT end --
@@ -65,6 +67,13 @@
#endif
+// -- GODOT start --
+#if NV_USE_SSE
+ //#include <intrin.h>
+ #include <xmmintrin.h>
+#endif
+// -- GODOT end --
+
#ifndef PI
#define PI float(3.1415926535897932384626433833)