diff options
215 files changed, 4730 insertions, 2374 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp index 7106bd0745..d36d0f4da0 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -190,32 +190,37 @@ void Input::VelocityTrack::update(const Vector2 &p_delta_p) { float delta_t = tdiff / 1000000.0; last_tick = tick; + if (delta_t > max_ref_frame) { + // First movement in a long time, reset and start again. + velocity = Vector2(); + accum = p_delta_p; + accum_t = 0; + return; + } + accum += p_delta_p; accum_t += delta_t; - if (accum_t > max_ref_frame * 10) { - accum_t = max_ref_frame * 10; + if (accum_t < min_ref_frame) { + // Not enough time has passed to calculate speed precisely. + return; } - while (accum_t >= min_ref_frame) { - float slice_t = min_ref_frame / accum_t; - Vector2 slice = accum * slice_t; - accum = accum - slice; - accum_t -= min_ref_frame; - - velocity = (slice / min_ref_frame).lerp(velocity, min_ref_frame / max_ref_frame); - } + velocity = accum / accum_t; + accum = Vector2(); + accum_t = 0; } void Input::VelocityTrack::reset() { last_tick = OS::get_singleton()->get_ticks_usec(); velocity = Vector2(); + accum = Vector2(); accum_t = 0; } Input::VelocityTrack::VelocityTrack() { min_ref_frame = 0.1; - max_ref_frame = 0.3; + max_ref_frame = 3.0; reset(); } @@ -719,7 +724,8 @@ Point2 Input::get_mouse_position() const { return mouse_pos; } -Point2 Input::get_last_mouse_velocity() const { +Point2 Input::get_last_mouse_velocity() { + mouse_velocity_track.update(Vector2()); return mouse_velocity_track.velocity; } diff --git a/core/input/input.h b/core/input/input.h index 80f260f30e..ab2cd377f4 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -270,7 +270,7 @@ public: Vector3 get_gyroscope() const; Point2 get_mouse_position() const; - Vector2 get_last_mouse_velocity() const; + Vector2 get_last_mouse_velocity(); MouseButton get_mouse_button_mask() const; void warp_mouse_position(const Vector2 &p_to); diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 4d0747c591..52b1120b2a 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -96,6 +96,17 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) { return query.substr(1); } +Error HTTPClient::verify_headers(const Vector<String> &p_headers) { + for (int i = 0; i < p_headers.size(); i++) { + String sanitized = p_headers[i].strip_edges(); + ERR_FAIL_COND_V_MSG(sanitized.is_empty(), ERR_INVALID_PARAMETER, "Invalid HTTP header at index " + itos(i) + ": empty."); + ERR_FAIL_COND_V_MSG(sanitized.find(":") < 1, ERR_INVALID_PARAMETER, + "Invalid HTTP header at index " + itos(i) + ": String must contain header-value pair, delimited by ':', but was: " + p_headers[i]); + } + + return OK; +} + Dictionary HTTPClient::_get_response_headers_as_dictionary() { List<String> rh; get_response_headers(&rh); diff --git a/core/io/http_client.h b/core/io/http_client.h index 90c859d685..de6045f647 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -165,6 +165,7 @@ public: static HTTPClient *create(); String query_string_from_dict(const Dictionary &p_dict); + Error verify_headers(const Vector<String> &p_headers); virtual Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_size) = 0; virtual Error connect_to_host(const String &p_host, int p_port = -1, bool p_ssl = false, bool p_verify_host = true) = 0; diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp index 6e4417e1ff..e61833ce7c 100644 --- a/core/io/http_client_tcp.cpp +++ b/core/io/http_client_tcp.cpp @@ -71,7 +71,7 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_ss connection = tcp_connection; if (ssl && https_proxy_port != -1) { - proxy_client.instantiate(); // Needs proxy negotiation + proxy_client.instantiate(); // Needs proxy negotiation. server_host = https_proxy_host; server_port = https_proxy_port; } else if (!ssl && http_proxy_port != -1) { @@ -83,7 +83,7 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_ss } if (server_host.is_valid_ip_address()) { - // Host contains valid IP + // Host contains valid IP. Error err = tcp_connection->connect_to_host(IPAddress(server_host), server_port); if (err) { status = STATUS_CANT_CONNECT; @@ -92,7 +92,7 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_ss status = STATUS_CONNECTING; } else { - // Host contains hostname and needs to be resolved to IP + // Host contains hostname and needs to be resolved to IP. resolving = IP::get_singleton()->resolve_hostname_queue_item(server_host); status = STATUS_RESOLVING; } @@ -124,7 +124,7 @@ Ref<StreamPeer> HTTPClientTCP::get_connection() const { static bool _check_request_url(HTTPClientTCP::Method p_method, const String &p_url) { switch (p_method) { case HTTPClientTCP::METHOD_CONNECT: { - // Authority in host:port format, as in RFC7231 + // Authority in host:port format, as in RFC7231. int pos = p_url.find_char(':'); return 0 < pos && pos < p_url.length() - 1; } @@ -135,7 +135,7 @@ static bool _check_request_url(HTTPClientTCP::Method p_method, const String &p_u [[fallthrough]]; } default: - // Absolute path or absolute URL + // Absolute path or absolute URL. return p_url.begins_with("/") || p_url.begins_with("http://") || p_url.begins_with("https://"); } } @@ -146,6 +146,11 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector< ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA); + Error err = verify_headers(p_headers); + if (err) { + return err; + } + String uri = p_url; if (!ssl && http_proxy_port != -1) { uri = vformat("http://%s:%d%s", conn_host, conn_port, p_url); @@ -173,7 +178,7 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector< } if (add_host) { if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) { - // Don't append the standard ports + // Don't append the standard ports. request += "Host: " + conn_host + "\r\n"; } else { request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n"; @@ -192,21 +197,12 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector< request += "\r\n"; CharString cs = request.utf8(); - Vector<uint8_t> data; - data.resize(cs.length() + p_body_size); - memcpy(data.ptrw(), cs.get_data(), cs.length()); + request_buffer->clear(); + request_buffer->put_data((const uint8_t *)cs.get_data(), cs.length()); if (p_body_size > 0) { - memcpy(data.ptrw() + cs.length(), p_body, p_body_size); - } - - // TODO Implement non-blocking requests. - Error err = connection->put_data(data.ptr(), data.size()); - - if (err) { - close(); - status = STATUS_CONNECTION_ERROR; - return err; + request_buffer->put_data(p_body, p_body_size); } + request_buffer->seek(0); status = STATUS_REQUESTING; head_request = p_method == METHOD_HEAD; @@ -257,6 +253,7 @@ void HTTPClientTCP::close() { ip_candidates.clear(); response_headers.clear(); response_str.clear(); + request_buffer->clear(); body_size = -1; body_left = 0; chunk_left = 0; @@ -274,7 +271,7 @@ Error HTTPClientTCP::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: { ip_candidates = IP::get_singleton()->get_resolve_item_addresses(resolving); @@ -356,7 +353,7 @@ Error HTTPClientTCP::poll() { } else if (ssl) { Ref<StreamPeerSSL> ssl; if (!handshaking) { - // Connect the StreamPeerSSL and start handshaking + // Connect the StreamPeerSSL and start handshaking. ssl = Ref<StreamPeerSSL>(StreamPeerSSL::create()); ssl->set_blocking_handshake_enabled(false); Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, conn_host); @@ -368,7 +365,7 @@ Error HTTPClientTCP::poll() { connection = ssl; handshaking = true; } else { - // We are already handshaking, which means we can use your already active SSL connection + // We are already handshaking, which means we can use your already active SSL connection. ssl = static_cast<Ref<StreamPeerSSL>>(connection); if (ssl.is_null()) { close(); @@ -376,22 +373,22 @@ Error HTTPClientTCP::poll() { return ERR_CANT_CONNECT; } - ssl->poll(); // Try to finish the handshake + ssl->poll(); // Try to finish the handshake. } if (ssl->get_status() == StreamPeerSSL::STATUS_CONNECTED) { - // Handshake has been successful + // Handshake has been successful. handshaking = false; ip_candidates.clear(); status = STATUS_CONNECTED; return OK; } else if (ssl->get_status() != StreamPeerSSL::STATUS_HANDSHAKING) { - // Handshake has failed + // Handshake has failed. close(); status = STATUS_SSL_HANDSHAKE_ERROR; return ERR_CANT_CONNECT; } - // ... we will need to poll more for handshake to finish + // ... we will need to poll more for handshake to finish. } else { ip_candidates.clear(); status = STATUS_CONNECTED; @@ -416,7 +413,7 @@ Error HTTPClientTCP::poll() { } break; case STATUS_BODY: case STATUS_CONNECTED: { - // Check if we are still connected + // Check if we are still connected. if (ssl) { Ref<StreamPeerSSL> tmp = connection; tmp->poll(); @@ -428,10 +425,34 @@ Error HTTPClientTCP::poll() { status = STATUS_CONNECTION_ERROR; return ERR_CONNECTION_ERROR; } - // Connection established, requests can now be made + // Connection established, requests can now be made. return OK; } break; case STATUS_REQUESTING: { + if (request_buffer->get_available_bytes()) { + int avail = request_buffer->get_available_bytes(); + int pos = request_buffer->get_position(); + const Vector<uint8_t> data = request_buffer->get_data_array(); + int wrote = 0; + Error err; + if (blocking) { + err = connection->put_data(data.ptr() + pos, avail); + wrote += avail; + } else { + err = connection->put_partial_data(data.ptr() + pos, avail, wrote); + } + if (err != OK) { + close(); + status = STATUS_CONNECTION_ERROR; + return ERR_CONNECTION_ERROR; + } + pos += wrote; + request_buffer->seek(pos); + if (avail - wrote > 0) { + return OK; + } + request_buffer->clear(); + } while (true) { uint8_t byte; int rec = 0; @@ -547,7 +568,7 @@ PackedByteArray HTTPClientTCP::read_response_body_chunk() { if (chunked) { while (true) { if (chunk_trailer_part) { - // We need to consume the trailer part too or keep-alive will break + // We need to consume the trailer part too or keep-alive will break. uint8_t b; int rec = 0; err = _get_http_data(&b, 1, rec); @@ -560,18 +581,18 @@ PackedByteArray HTTPClientTCP::read_response_body_chunk() { int cs = chunk.size(); if ((cs >= 2 && chunk[cs - 2] == '\r' && chunk[cs - 1] == '\n')) { if (cs == 2) { - // Finally over + // Finally over. chunk_trailer_part = false; status = STATUS_CONNECTED; chunk.clear(); break; } else { - // We do not process nor return the trailer data + // We do not process nor return the trailer data. chunk.clear(); } } } else if (chunk_left == 0) { - // Reading length + // Reading length. uint8_t b; int rec = 0; err = _get_http_data(&b, 1, rec); @@ -658,7 +679,7 @@ PackedByteArray HTTPClientTCP::read_response_body_chunk() { uint8_t *w = ret.ptrw(); err = _get_http_data(w + _offset, to_read, rec); } - if (rec <= 0) { // Ended up reading less + if (rec <= 0) { // Ended up reading less. ret.resize(_offset); break; } else { @@ -679,7 +700,7 @@ PackedByteArray HTTPClientTCP::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; } @@ -759,6 +780,7 @@ void HTTPClientTCP::set_https_proxy(const String &p_host, int p_port) { HTTPClientTCP::HTTPClientTCP() { tcp_connection.instantiate(); + request_buffer.instantiate(); } HTTPClient *(*HTTPClient::_create)() = HTTPClientTCP::_create_func; diff --git a/core/io/http_client_tcp.h b/core/io/http_client_tcp.h index 3fe8e2c0df..c10e0b1eca 100644 --- a/core/io/http_client_tcp.h +++ b/core/io/http_client_tcp.h @@ -38,13 +38,13 @@ private: Status status = STATUS_DISCONNECTED; IP::ResolverID resolving = IP::RESOLVER_INVALID_ID; Array ip_candidates; - int conn_port = -1; // Server to make requests to + int conn_port = -1; // Server to make requests to. String conn_host; - int server_port = -1; // Server to connect to (might be a proxy server) + int server_port = -1; // Server to connect to (might be a proxy server). String server_host; - int http_proxy_port = -1; // Proxy server for http requests + int http_proxy_port = -1; // Proxy server for http requests. String http_proxy_host; - int https_proxy_port = -1; // Proxy server for https requests + int https_proxy_port = -1; // Proxy server for https requests. String https_proxy_host; bool ssl = false; bool ssl_verify_host = false; @@ -62,9 +62,10 @@ private: int64_t body_left = 0; bool read_until_eof = false; + Ref<StreamPeerBuffer> request_buffer; Ref<StreamPeerTCP> tcp_connection; Ref<StreamPeer> connection; - Ref<HTTPClientTCP> proxy_client; // Negotiate with proxy server + Ref<HTTPClientTCP> proxy_client; // Negotiate with proxy server. int response_num = 0; Vector<String> response_headers; diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py index e961745d96..5de1b49026 100644 --- a/core/object/make_virtuals.py +++ b/core/object/make_virtuals.py @@ -123,9 +123,9 @@ def generate_version(argcount, const=False, returns=False): callargtext += "," callargtext += " m_ret& r_ret" s = s.replace("$CALLSIBEGIN", "Variant ret = ") - s = s.replace("$CALLSIRET", "r_ret = ret;") + s = s.replace("$CALLSIRET", "r_ret = VariantCaster<m_ret>::cast(ret);") s = s.replace("$CALLPTRRETPASS", "&ret") - s = s.replace("$CALLPTRRET", "r_ret = ret;") + s = s.replace("$CALLPTRRET", "r_ret = (m_ret)ret;") else: s = s.replace("$CALLSIBEGIN", "") s = s.replace("$CALLSIRET", "") diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h index fe541c8d4b..8e9fbbc0a4 100644 --- a/core/variant/native_ptr.h +++ b/core/variant/native_ptr.h @@ -53,22 +53,36 @@ struct GDNativePtr { operator Variant() const { return uint64_t(data); } }; -#define GDVIRTUAL_NATIVE_PTR(m_type) \ - template <> \ - struct GDNativeConstPtr<const m_type> { \ - const m_type *data = nullptr; \ - GDNativeConstPtr(const m_type *p_assign) { data = p_assign; } \ - static const char *get_name() { return "const " #m_type; } \ - operator const m_type *() const { return data; } \ - operator Variant() const { return uint64_t(data); } \ - }; \ - template <> \ - struct GDNativePtr<m_type> { \ - m_type *data = nullptr; \ - GDNativePtr(m_type *p_assign) { data = p_assign; } \ - static const char *get_name() { return #m_type; } \ - operator m_type *() const { return data; } \ - operator Variant() const { return uint64_t(data); } \ +#define GDVIRTUAL_NATIVE_PTR(m_type) \ + template <> \ + struct GDNativeConstPtr<const m_type> { \ + const m_type *data = nullptr; \ + GDNativeConstPtr() {} \ + GDNativeConstPtr(const m_type *p_assign) { data = p_assign; } \ + static const char *get_name() { return "const " #m_type; } \ + operator const m_type *() const { return data; } \ + operator Variant() const { return uint64_t(data); } \ + }; \ + template <> \ + struct VariantCaster<GDNativeConstPtr<const m_type>> { \ + static _FORCE_INLINE_ GDNativeConstPtr<const m_type> cast(const Variant &p_variant) { \ + return GDNativeConstPtr<const m_type>((const m_type *)p_variant.operator uint64_t()); \ + } \ + }; \ + template <> \ + struct GDNativePtr<m_type> { \ + m_type *data = nullptr; \ + GDNativePtr() {} \ + GDNativePtr(m_type *p_assign) { data = p_assign; } \ + static const char *get_name() { return #m_type; } \ + operator m_type *() const { return data; } \ + operator Variant() const { return uint64_t(data); } \ + }; \ + template <> \ + struct VariantCaster<GDNativePtr<m_type>> { \ + static _FORCE_INLINE_ GDNativePtr<m_type> cast(const Variant &p_variant) { \ + return GDNativePtr<m_type>((m_type *)p_variant.operator uint64_t()); \ + } \ }; template <class T> diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index 0f7e6799be..5280b7445d 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -31,7 +31,7 @@ <return type="bool" /> <argument index="0" name="area" type="Node" /> <description> - If [code]true[/code], the given area overlaps the Area2D. + Returns [code]true[/code] if the given [Area2D] intersects or overlaps this [Area2D], [code]false[/code] otherwise. [b]Note:[/b] The result of this test is not immediate after moving objects. For performance, the list of overlaps is updated once per frame and before the physics step. Consider using signals instead. </description> </method> @@ -39,9 +39,9 @@ <return type="bool" /> <argument index="0" name="body" type="Node" /> <description> - If [code]true[/code], the given physics body overlaps the Area2D. + Returns [code]true[/code] if the given physics body intersects or overlaps this [Area2D], [code]false[/code] otherwise. [b]Note:[/b] The result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead. - The [code]body[/code] argument can either be a [PhysicsBody2D] or a [TileMap] instance (while TileMaps are not physics bodies themselves, they register their tiles with collision shapes as a virtual physics body). + The [code]body[/code] argument can either be a [PhysicsBody2D] or a [TileMap] instance. While TileMaps are not physics bodies themselves, they register their tiles with collision shapes as a virtual physics body. </description> </method> </methods> diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index 450ed44307..4f456cb56d 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -29,7 +29,7 @@ <return type="bool" /> <argument index="0" name="area" type="Node" /> <description> - If [code]true[/code], the given area overlaps the Area3D. + Returns [code]true[/code] if the given [Area3D] intersects or overlaps this [Area3D], [code]false[/code] otherwise. [b]Note:[/b] The result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead. </description> </method> @@ -37,9 +37,9 @@ <return type="bool" /> <argument index="0" name="body" type="Node" /> <description> - If [code]true[/code], the given physics body overlaps the Area3D. + Returns [code]true[/code] if the given physics body intersects or overlaps this [Area3D], [code]false[/code] otherwise. [b]Note:[/b] The result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead. - The [code]body[/code] argument can either be a [PhysicsBody3D] or a [GridMap] instance (while GridMaps are not physics body themselves, they register their tiles with collision shapes as a virtual physics body). + The [code]body[/code] argument can either be a [PhysicsBody3D] or a [GridMap] instance. While GridMaps are not physics body themselves, they register their tiles with collision shapes as a virtual physics body. </description> </method> </methods> diff --git a/doc/classes/BoxMesh.xml b/doc/classes/BoxMesh.xml index af3365b6ea..bf499c8971 100644 --- a/doc/classes/BoxMesh.xml +++ b/doc/classes/BoxMesh.xml @@ -11,7 +11,7 @@ <tutorials> </tutorials> <members> - <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(1, 1, 1)"> The box's width, height and depth. </member> <member name="subdivide_depth" type="int" setter="set_subdivide_depth" getter="get_subdivide_depth" default="0"> diff --git a/doc/classes/BoxShape3D.xml b/doc/classes/BoxShape3D.xml index 3bfded6512..cf2bf2338b 100644 --- a/doc/classes/BoxShape3D.xml +++ b/doc/classes/BoxShape3D.xml @@ -12,7 +12,7 @@ <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> </tutorials> <members> - <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(1, 1, 1)"> The box's width, height and depth. </member> </members> diff --git a/doc/classes/CapsuleMesh.xml b/doc/classes/CapsuleMesh.xml index 3b4e60ce93..45dd64c174 100644 --- a/doc/classes/CapsuleMesh.xml +++ b/doc/classes/CapsuleMesh.xml @@ -9,13 +9,13 @@ <tutorials> </tutorials> <members> - <member name="height" type="float" setter="set_height" getter="get_height" default="3.0"> + <member name="height" type="float" setter="set_height" getter="get_height" default="2.0"> Total height of the capsule mesh (including the hemispherical ends). </member> <member name="radial_segments" type="int" setter="set_radial_segments" getter="get_radial_segments" default="64"> Number of radial segments on the capsule mesh. </member> - <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> + <member name="radius" type="float" setter="set_radius" getter="get_radius" default="0.5"> Radius of the capsule mesh. </member> <member name="rings" type="int" setter="set_rings" getter="get_rings" default="8"> diff --git a/doc/classes/CapsuleShape3D.xml b/doc/classes/CapsuleShape3D.xml index 8856ec3779..ba4ead4930 100644 --- a/doc/classes/CapsuleShape3D.xml +++ b/doc/classes/CapsuleShape3D.xml @@ -10,10 +10,10 @@ <link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link> </tutorials> <members> - <member name="height" type="float" setter="set_height" getter="get_height" default="3.0"> + <member name="height" type="float" setter="set_height" getter="get_height" default="2.0"> The capsule's height. </member> - <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> + <member name="radius" type="float" setter="set_radius" getter="get_radius" default="0.5"> The capsule's radius. </member> </members> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index d5551e1e04..b6c2dac33c 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -380,12 +380,6 @@ Returns the focus neighbor for the specified [enum Side]. A getter method for [member focus_neighbor_bottom], [member focus_neighbor_left], [member focus_neighbor_right] and [member focus_neighbor_top]. </description> </method> - <method name="get_focus_owner" qualifiers="const"> - <return type="Control" /> - <description> - Returns the control that has the keyboard focus or [code]null[/code] if none. - </description> - </method> <method name="get_global_rect" qualifiers="const"> <return type="Rect2" /> <description> diff --git a/doc/classes/CylinderMesh.xml b/doc/classes/CylinderMesh.xml index 077435990b..ce34cc91ad 100644 --- a/doc/classes/CylinderMesh.xml +++ b/doc/classes/CylinderMesh.xml @@ -9,7 +9,7 @@ <tutorials> </tutorials> <members> - <member name="bottom_radius" type="float" setter="set_bottom_radius" getter="get_bottom_radius" default="1.0"> + <member name="bottom_radius" type="float" setter="set_bottom_radius" getter="get_bottom_radius" default="0.5"> Bottom radius of the cylinder. If set to [code]0.0[/code], the bottom faces will not be generated, resulting in a conic shape. </member> <member name="height" type="float" setter="set_height" getter="get_height" default="2.0"> @@ -21,7 +21,7 @@ <member name="rings" type="int" setter="set_rings" getter="get_rings" default="4"> Number of edge rings along the height of the cylinder. Changing [member rings] does not have any visual impact unless a shader or procedural mesh tool is used to alter the vertex data. Higher values result in more subdivisions, which can be used to create smoother-looking effects with shaders or procedural mesh tools (at the cost of performance). When not altering the vertex data using a shader or procedural mesh tool, [member rings] should be kept to its default value. </member> - <member name="top_radius" type="float" setter="set_top_radius" getter="get_top_radius" default="1.0"> + <member name="top_radius" type="float" setter="set_top_radius" getter="get_top_radius" default="0.5"> Top radius of the cylinder. If set to [code]0.0[/code], the top faces will not be generated, resulting in a conic shape. </member> </members> diff --git a/doc/classes/CylinderShape3D.xml b/doc/classes/CylinderShape3D.xml index d40b96710b..6fa6c4d75e 100644 --- a/doc/classes/CylinderShape3D.xml +++ b/doc/classes/CylinderShape3D.xml @@ -15,7 +15,7 @@ <member name="height" type="float" setter="set_height" getter="get_height" default="2.0"> The cylinder's height. </member> - <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> + <member name="radius" type="float" setter="set_radius" getter="get_radius" default="0.5"> The cylinder's radius. </member> </members> diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 423e58f5c6..b5468755c1 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -141,10 +141,10 @@ Returns the strength of the joypad vibration: x is the strength of the weak motor, and y is the strength of the strong motor. </description> </method> - <method name="get_last_mouse_velocity" qualifiers="const"> + <method name="get_last_mouse_velocity"> <return type="Vector2" /> <description> - Returns the mouse velocity for the last time the cursor was moved, and this until the next frame where the mouse moves. This means that even if the mouse is not moving, this function will still return the value of the last motion. + Returns the last mouse velocity. To provide a precise and jitter-free velocity, mouse velocity is only calculated every 0.1s. Therefore, mouse velocity will lag mouse movements. </description> </method> <method name="get_magnetometer" qualifiers="const"> @@ -383,7 +383,8 @@ <return type="void" /> <argument index="0" name="to" type="Vector2" /> <description> - Sets the mouse position to the specified vector. + Sets the mouse position to the specified vector, provided in pixels and relative to an origin at the upper left corner of the game window. + Mouse position is clipped to the limits of the screen resolution, or to the limits of the game window if [enum MouseMode] is set to [code]MOUSE_MODE_CONFINED[/code] or [code]MOUSE_MODE_CONFINED_HIDDEN[/code]. </description> </method> </methods> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index f5f6ba8b6d..bdc3a09322 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -490,7 +490,7 @@ <argument index="0" name="property" type="String" /> <argument index="1" name="value" type="Variant" /> <description> - Assigns a new value to the given property. If the [code]property[/code] does not exist, nothing will happen. + Assigns a new value to the given property. If the [code]property[/code] does not exist or the given value's type doesn't match, nothing will happen. [b]Note:[/b] In C#, the property name must be specified as snake_case if it is defined by a built-in Godot node. This doesn't apply to user-defined properties where you should use the same convention as in the C# source (typically PascalCase). </description> </method> diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index 108c674ef7..eb1b0aada7 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -331,6 +331,13 @@ [b]Note:[/b] The indices of items after the removed item will be shifted by one. </description> </method> + <method name="set_current_index"> + <return type="void" /> + <argument index="0" name="index" type="int" /> + <description> + Sets the currently focused item as the given [code]index[/code]. + </description> + </method> <method name="set_item_accelerator"> <return type="void" /> <argument index="0" name="index" type="int" /> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 6f5135459f..95dffd3e28 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -372,6 +372,9 @@ </method> </methods> <members> + <member name="autowrap_mode" type="int" setter="set_autowrap_mode" getter="get_autowrap_mode" enum="RichTextLabel.AutowrapMode" default="3"> + If set to something other than [constant AUTOWRAP_OFF], the text gets wrapped inside the node's bounding rectangle. To see how each mode behaves, see [enum AutowrapMode]. + </member> <member name="bbcode_enabled" type="bool" setter="set_use_bbcode" getter="is_using_bbcode" default="false"> If [code]true[/code], the label uses BBCode formatting. </member> @@ -454,6 +457,18 @@ </signal> </signals> <constants> + <constant name="AUTOWRAP_OFF" value="0" enum="AutowrapMode"> + Autowrap is disabled. + </constant> + <constant name="AUTOWRAP_ARBITRARY" value="1" enum="AutowrapMode"> + Wraps the text inside the node's bounding rectangle by allowing to break lines at arbitrary positions, which is useful when very limited space is available. + </constant> + <constant name="AUTOWRAP_WORD" value="2" enum="AutowrapMode"> + Wraps the text inside the node's bounding rectangle by soft-breaking between words. + </constant> + <constant name="AUTOWRAP_WORD_SMART" value="3" enum="AutowrapMode"> + Behaves similarly to [constant AUTOWRAP_WORD], but force-breaks a word if that single word does not fit in one line. + </constant> <constant name="LIST_NUMBERS" value="0" enum="ListType"> Each list item has a number marker. </constant> diff --git a/doc/classes/StreamPeerBuffer.xml b/doc/classes/StreamPeerBuffer.xml index 989864760f..e335987ff5 100644 --- a/doc/classes/StreamPeerBuffer.xml +++ b/doc/classes/StreamPeerBuffer.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="StreamPeerBuffer" inherits="StreamPeer" version="4.0"> <brief_description> + Data buffer stream peer. </brief_description> <description> + Data buffer stream peer that uses a byte array as the stream. This object can be used to handle binary data from network sessions. To handle binary data stored in files, [File] can be used directly. + A [StreamPeerBuffer] object keeps an internal cursor which is the offset in bytes to the start of the buffer. Get and put operations are performed at the cursor position and will move the cursor accordingly. </description> <tutorials> </tutorials> @@ -10,38 +13,45 @@ <method name="clear"> <return type="void" /> <description> + Clears the [member data_array] and resets the cursor. </description> </method> <method name="duplicate" qualifiers="const"> <return type="StreamPeerBuffer" /> <description> + Returns a new [StreamPeerBuffer] with the same [member data_array] content. </description> </method> <method name="get_position" qualifiers="const"> <return type="int" /> <description> + Returns the current cursor position. </description> </method> <method name="get_size" qualifiers="const"> <return type="int" /> <description> + Returns the size of [member data_array]. </description> </method> <method name="resize"> <return type="void" /> <argument index="0" name="size" type="int" /> <description> + Resizes the [member data_array]. This [i]doesn't[/i] update the cursor. </description> </method> <method name="seek"> <return type="void" /> <argument index="0" name="position" type="int" /> <description> + Moves the cursor to the specified position. [code]position[/code] must be a valid index of [member data_array]. </description> </method> </methods> <members> <member name="data_array" type="PackedByteArray" setter="set_data_array" getter="get_data_array" default="PackedByteArray()"> + The underlying data buffer. Setting this value resets the cursor. </member> </members> </class> diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml index 5967340f8c..b500bd5658 100644 --- a/doc/classes/TextServerExtension.xml +++ b/doc/classes/TextServerExtension.xml @@ -202,7 +202,7 @@ </description> </method> <method name="_font_get_hinting" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="TextServer.Hinting" /> <argument index="0" name="font_rid" type="RID" /> <description> Returns the font hinting mode. Used by dynamic fonts only. @@ -1028,7 +1028,7 @@ </description> </method> <method name="_shaped_text_get_direction" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="TextServer.Direction" /> <argument index="0" name="shaped" type="RID" /> <description> Returns direction of the text. @@ -1051,9 +1051,8 @@ </description> </method> <method name="_shaped_text_get_ellipsis_glyphs" qualifiers="virtual const"> - <return type="void" /> + <return type="Glyph*" /> <argument index="0" name="shaped" type="RID" /> - <argument index="1" name="r_glyphs" type="void*" /> <description> Returns array of the glyphs in the ellipsis. </description> @@ -1073,9 +1072,8 @@ </description> </method> <method name="_shaped_text_get_glyphs" qualifiers="virtual const"> - <return type="void" /> + <return type="Glyph*" /> <argument index="0" name="shaped" type="RID" /> - <argument index="1" name="r_glyphs" type="void*" /> <description> Copies text glyphs in the visual order, into preallocated array of the size returned by [method _shaped_text_get_glyph_count]. </description> @@ -1089,7 +1087,7 @@ </description> </method> <method name="_shaped_text_get_inferred_direction" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="TextServer.Direction" /> <argument index="0" name="shaped" type="RID" /> <description> Returns direction of the text, inferred by the BiDi algorithm. @@ -1132,7 +1130,7 @@ </description> </method> <method name="_shaped_text_get_orientation" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="TextServer.Orientation" /> <argument index="0" name="shaped" type="RID" /> <description> Returns text orientation. @@ -1337,9 +1335,8 @@ </description> </method> <method name="_shaped_text_sort_logical" qualifiers="virtual"> - <return type="void" /> + <return type="Glyph*" /> <argument index="0" name="shaped" type="RID" /> - <argument index="1" name="r_glyphs" type="void*" /> <description> Copies text glyphs in the logical order, into preallocated array of the size returned by [method _shaped_text_get_glyph_count]. </description> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 4a11fbb489..1b37cab68e 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -107,6 +107,12 @@ Returns the drag data from the GUI, that was previously returned by [method Control._get_drag_data]. </description> </method> + <method name="gui_get_focus_owner"> + <return type="Control" /> + <description> + Returns the [Control] having the focus within this viewport. If no [Control] has the focus, returns null. + </description> + </method> <method name="gui_is_drag_successful" qualifiers="const"> <return type="bool" /> <description> @@ -119,6 +125,12 @@ Returns [code]true[/code] if the viewport is currently performing a drag operation. </description> </method> + <method name="gui_release_focus"> + <return type="void" /> + <description> + Removes the focus from the currently focussed [Control] within this viewport. If no [Control] has the focus, does nothing. + </description> + </method> <method name="is_embedding_subwindows" qualifiers="const"> <return type="bool" /> <description> diff --git a/doc/classes/VisualShaderNode.xml b/doc/classes/VisualShaderNode.xml index cebe7f215f..0067240820 100644 --- a/doc/classes/VisualShaderNode.xml +++ b/doc/classes/VisualShaderNode.xml @@ -47,6 +47,7 @@ <return type="void" /> <argument index="0" name="port" type="int" /> <argument index="1" name="value" type="Variant" /> + <argument index="2" name="prev_value" type="Variant" default="null" /> <description> Sets the default value for the selected input [code]port[/code]. </description> @@ -71,19 +72,22 @@ <constant name="PORT_TYPE_SCALAR_INT" value="1" enum="PortType"> Integer scalar. Translated to [code]int[/code] type in shader code. </constant> - <constant name="PORT_TYPE_VECTOR" value="2" enum="PortType"> + <constant name="PORT_TYPE_VECTOR_2D" value="2" enum="PortType"> + 2D vector of floating-point values. Translated to [code]vec2[/code] type in shader code. + </constant> + <constant name="PORT_TYPE_VECTOR" value="3" enum="PortType"> 3D vector of floating-point values. Translated to [code]vec3[/code] type in shader code. </constant> - <constant name="PORT_TYPE_BOOLEAN" value="3" enum="PortType"> + <constant name="PORT_TYPE_BOOLEAN" value="4" enum="PortType"> Boolean type. Translated to [code]bool[/code] type in shader code. </constant> - <constant name="PORT_TYPE_TRANSFORM" value="4" enum="PortType"> + <constant name="PORT_TYPE_TRANSFORM" value="5" enum="PortType"> Transform type. Translated to [code]mat4[/code] type in shader code. </constant> - <constant name="PORT_TYPE_SAMPLER" value="5" enum="PortType"> + <constant name="PORT_TYPE_SAMPLER" value="6" enum="PortType"> Sampler type. Translated to reference of sampler uniform in shader code. Can only be used for input ports in non-uniform nodes. </constant> - <constant name="PORT_TYPE_MAX" value="6" enum="PortType"> + <constant name="PORT_TYPE_MAX" value="7" enum="PortType"> Represents the size of the [enum PortType] enum. </constant> </constants> diff --git a/doc/classes/VisualShaderNodeClamp.xml b/doc/classes/VisualShaderNodeClamp.xml index a68cbbec49..7219ba14b7 100644 --- a/doc/classes/VisualShaderNodeClamp.xml +++ b/doc/classes/VisualShaderNodeClamp.xml @@ -20,10 +20,13 @@ <constant name="OP_TYPE_INT" value="1" enum="OpType"> An integer scalar. </constant> - <constant name="OP_TYPE_VECTOR" value="2" enum="OpType"> - A vector type. + <constant name="OP_TYPE_VECTOR_2D" value="2" enum="OpType"> + A 2D vector type. </constant> - <constant name="OP_TYPE_MAX" value="3" enum="OpType"> + <constant name="OP_TYPE_VECTOR_3D" value="3" enum="OpType"> + A 3D vector type. + </constant> + <constant name="OP_TYPE_MAX" value="4" enum="OpType"> Represents the size of the [enum OpType] enum. </constant> </constants> diff --git a/doc/classes/VisualShaderNodeCompare.xml b/doc/classes/VisualShaderNodeCompare.xml index 49bf952b31..ddd7f87cb8 100644 --- a/doc/classes/VisualShaderNodeCompare.xml +++ b/doc/classes/VisualShaderNodeCompare.xml @@ -10,7 +10,7 @@ </tutorials> <members> <member name="condition" type="int" setter="set_condition" getter="get_condition" enum="VisualShaderNodeCompare.Condition" default="0"> - Extra condition which is applied if [member type] is set to [constant CTYPE_VECTOR]. + Extra condition which is applied if [member type] is set to [constant CTYPE_VECTOR_3D]. </member> <member name="function" type="int" setter="set_function" getter="get_function" enum="VisualShaderNodeCompare.Function" default="0"> A comparison function. See [enum Function] for options. @@ -26,16 +26,19 @@ <constant name="CTYPE_SCALAR_INT" value="1" enum="ComparisonType"> An integer scalar. </constant> - <constant name="CTYPE_VECTOR" value="2" enum="ComparisonType"> + <constant name="CTYPE_VECTOR_2D" value="2" enum="ComparisonType"> + A 2D vector type. + </constant> + <constant name="CTYPE_VECTOR_3D" value="3" enum="ComparisonType"> A 3D vector type. </constant> - <constant name="CTYPE_BOOLEAN" value="3" enum="ComparisonType"> + <constant name="CTYPE_BOOLEAN" value="4" enum="ComparisonType"> A boolean type. </constant> - <constant name="CTYPE_TRANSFORM" value="4" enum="ComparisonType"> + <constant name="CTYPE_TRANSFORM" value="5" enum="ComparisonType"> A transform ([code]mat4[/code]) type. </constant> - <constant name="CTYPE_MAX" value="5" enum="ComparisonType"> + <constant name="CTYPE_MAX" value="6" enum="ComparisonType"> Represents the size of the [enum ComparisonType] enum. </constant> <constant name="FUNC_EQUAL" value="0" enum="Function"> diff --git a/doc/classes/VisualShaderNodeDerivativeFunc.xml b/doc/classes/VisualShaderNodeDerivativeFunc.xml index f7edac8597..704af44d04 100644 --- a/doc/classes/VisualShaderNodeDerivativeFunc.xml +++ b/doc/classes/VisualShaderNodeDerivativeFunc.xml @@ -20,10 +20,13 @@ <constant name="OP_TYPE_SCALAR" value="0" enum="OpType"> A floating-point scalar. </constant> - <constant name="OP_TYPE_VECTOR" value="1" enum="OpType"> + <constant name="OP_TYPE_VECTOR_2D" value="1" enum="OpType"> + A 2D vector type. + </constant> + <constant name="OP_TYPE_VECTOR_3D" value="2" enum="OpType"> A 3D vector type. </constant> - <constant name="OP_TYPE_MAX" value="2" enum="OpType"> + <constant name="OP_TYPE_MAX" value="3" enum="OpType"> Represents the size of the [enum OpType] enum. </constant> <constant name="FUNC_SUM" value="0" enum="Function"> diff --git a/doc/classes/VisualShaderNodeFaceForward.xml b/doc/classes/VisualShaderNodeFaceForward.xml index 80cb8aea4e..cd2b3972b7 100644 --- a/doc/classes/VisualShaderNodeFaceForward.xml +++ b/doc/classes/VisualShaderNodeFaceForward.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualShaderNodeFaceForward" inherits="VisualShaderNode" version="4.0"> +<class name="VisualShaderNodeFaceForward" inherits="VisualShaderNodeVectorBase" version="4.0"> <brief_description> Returns the vector that points in the same direction as a reference vector within the visual shader graph. </brief_description> diff --git a/doc/classes/VisualShaderNodeMix.xml b/doc/classes/VisualShaderNodeMix.xml index 1ef580a983..8a2f289a11 100644 --- a/doc/classes/VisualShaderNodeMix.xml +++ b/doc/classes/VisualShaderNodeMix.xml @@ -15,15 +15,21 @@ </members> <constants> <constant name="OP_TYPE_SCALAR" value="0" enum="OpType"> - A scalar type. + A floating-point scalar. </constant> - <constant name="OP_TYPE_VECTOR" value="1" enum="OpType"> - A vector type. + <constant name="OP_TYPE_VECTOR_2D" value="1" enum="OpType"> + A 2D vector type. </constant> - <constant name="OP_TYPE_VECTOR_SCALAR" value="2" enum="OpType"> - A vector type. [code]weight[/code] port is using a scalar type. + <constant name="OP_TYPE_VECTOR_2D_SCALAR" value="2" enum="OpType"> + The [code]a[/code] and [code]b[/code] ports use a 2D vector type. The [code]weight[/code] port uses a scalar type. </constant> - <constant name="OP_TYPE_MAX" value="3" enum="OpType"> + <constant name="OP_TYPE_VECTOR_3D" value="3" enum="OpType"> + A 3D vector type. + </constant> + <constant name="OP_TYPE_VECTOR_3D_SCALAR" value="4" enum="OpType"> + The [code]a[/code] and [code]b[/code] ports use a 3D vector type. The [code]weight[/code] port uses a scalar type. + </constant> + <constant name="OP_TYPE_MAX" value="5" enum="OpType"> Represents the size of the [enum OpType] enum. </constant> </constants> diff --git a/doc/classes/VisualShaderNodeMultiplyAdd.xml b/doc/classes/VisualShaderNodeMultiplyAdd.xml index a0e9aef703..a6168e4df1 100644 --- a/doc/classes/VisualShaderNodeMultiplyAdd.xml +++ b/doc/classes/VisualShaderNodeMultiplyAdd.xml @@ -15,12 +15,15 @@ </members> <constants> <constant name="OP_TYPE_SCALAR" value="0" enum="OpType"> - A scalar type. + A floating-point scalar type. </constant> - <constant name="OP_TYPE_VECTOR" value="1" enum="OpType"> - A vector type. + <constant name="OP_TYPE_VECTOR_2D" value="1" enum="OpType"> + A 2D vector type. </constant> - <constant name="OP_TYPE_MAX" value="2" enum="OpType"> + <constant name="OP_TYPE_VECTOR_3D" value="2" enum="OpType"> + A 3D vector type. + </constant> + <constant name="OP_TYPE_MAX" value="3" enum="OpType"> Represents the size of the [enum OpType] enum. </constant> </constants> diff --git a/doc/classes/VisualShaderNodeSmoothStep.xml b/doc/classes/VisualShaderNodeSmoothStep.xml index 2f8c7e0f33..714b9d8267 100644 --- a/doc/classes/VisualShaderNodeSmoothStep.xml +++ b/doc/classes/VisualShaderNodeSmoothStep.xml @@ -16,15 +16,21 @@ </members> <constants> <constant name="OP_TYPE_SCALAR" value="0" enum="OpType"> - A scalar type. + A floating-point scalar type. </constant> - <constant name="OP_TYPE_VECTOR" value="1" enum="OpType"> - A vector type. + <constant name="OP_TYPE_VECTOR_2D" value="1" enum="OpType"> + A 2D vector type. </constant> - <constant name="OP_TYPE_VECTOR_SCALAR" value="2" enum="OpType"> - A vector type. [code]edge0[/code] and [code]edge1[/code] are using a scalar type. + <constant name="OP_TYPE_VECTOR_2D_SCALAR" value="2" enum="OpType"> + The [code]x[/code] port uses a 2D vector type. The first two ports use a floating-point scalar type. </constant> - <constant name="OP_TYPE_MAX" value="3" enum="OpType"> + <constant name="OP_TYPE_VECTOR_3D" value="3" enum="OpType"> + A 3D vector type. + </constant> + <constant name="OP_TYPE_VECTOR_3D_SCALAR" value="4" enum="OpType"> + The [code]x[/code] port uses a 3D vector type. The first two ports use a floating-point scalar type. + </constant> + <constant name="OP_TYPE_MAX" value="5" enum="OpType"> Represents the size of the [enum OpType] enum. </constant> </constants> diff --git a/doc/classes/VisualShaderNodeStep.xml b/doc/classes/VisualShaderNodeStep.xml index 5d8b464814..f65c95ea9e 100644 --- a/doc/classes/VisualShaderNodeStep.xml +++ b/doc/classes/VisualShaderNodeStep.xml @@ -16,15 +16,21 @@ </members> <constants> <constant name="OP_TYPE_SCALAR" value="0" enum="OpType"> - A scalar type. + A floating-point scalar type. </constant> - <constant name="OP_TYPE_VECTOR" value="1" enum="OpType"> - A vector type. + <constant name="OP_TYPE_VECTOR_2D" value="1" enum="OpType"> + A 2D vector type. </constant> - <constant name="OP_TYPE_VECTOR_SCALAR" value="2" enum="OpType"> - A vector type. [code]edge[/code] port is using a scalar type. + <constant name="OP_TYPE_VECTOR_2D_SCALAR" value="2" enum="OpType"> + The [code]x[/code] port uses a 2D vector type, while the [code]edge[/code] port uses a floating-point scalar type. </constant> - <constant name="OP_TYPE_MAX" value="3" enum="OpType"> + <constant name="OP_TYPE_VECTOR_3D" value="3" enum="OpType"> + A 3D vector type. + </constant> + <constant name="OP_TYPE_VECTOR_3D_SCALAR" value="4" enum="OpType"> + The [code]x[/code] port uses a 3D vector type, while the [code]edge[/code] port uses a floating-point scalar type. + </constant> + <constant name="OP_TYPE_MAX" value="5" enum="OpType"> Represents the size of the [enum OpType] enum. </constant> </constants> diff --git a/doc/classes/VisualShaderNodeSwitch.xml b/doc/classes/VisualShaderNodeSwitch.xml index 921092cd07..71888ec2c3 100644 --- a/doc/classes/VisualShaderNodeSwitch.xml +++ b/doc/classes/VisualShaderNodeSwitch.xml @@ -20,16 +20,19 @@ <constant name="OP_TYPE_INT" value="1" enum="OpType"> An integer scalar. </constant> - <constant name="OP_TYPE_VECTOR" value="2" enum="OpType"> - A vector type. + <constant name="OP_TYPE_VECTOR_2D" value="2" enum="OpType"> + A 2D vector type. </constant> - <constant name="OP_TYPE_BOOLEAN" value="3" enum="OpType"> + <constant name="OP_TYPE_VECTOR_3D" value="3" enum="OpType"> + A 3D vector type. + </constant> + <constant name="OP_TYPE_BOOLEAN" value="4" enum="OpType"> A boolean type. </constant> - <constant name="OP_TYPE_TRANSFORM" value="4" enum="OpType"> + <constant name="OP_TYPE_TRANSFORM" value="5" enum="OpType"> A transform type. </constant> - <constant name="OP_TYPE_MAX" value="5" enum="OpType"> + <constant name="OP_TYPE_MAX" value="6" enum="OpType"> Represents the size of the [enum OpType] enum. </constant> </constants> diff --git a/doc/classes/VisualShaderNodeVec2Constant.xml b/doc/classes/VisualShaderNodeVec2Constant.xml new file mode 100644 index 0000000000..f897ab4091 --- /dev/null +++ b/doc/classes/VisualShaderNodeVec2Constant.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeVec2Constant" inherits="VisualShaderNodeConstant" version="4.0"> + <brief_description> + A [Vector2] constant to be used within the visual shader graph. + </brief_description> + <description> + A constant [Vector2], which can be used as an input node. + </description> + <tutorials> + </tutorials> + <members> + <member name="constant" type="Vector2" setter="set_constant" getter="get_constant" default="Vector2(0, 0)"> + A [Vector2] constant which represents the state of this node. + </member> + </members> +</class> diff --git a/doc/classes/VisualShaderNodeVec2Uniform.xml b/doc/classes/VisualShaderNodeVec2Uniform.xml new file mode 100644 index 0000000000..d5cf7e57c8 --- /dev/null +++ b/doc/classes/VisualShaderNodeVec2Uniform.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeVec2Uniform" inherits="VisualShaderNodeUniform" version="4.0"> + <brief_description> + A [Vector2] uniform to be used within the visual shader graph. + </brief_description> + <description> + Translated to [code]uniform vec2[/code] in the shader language. + </description> + <tutorials> + </tutorials> + <members> + <member name="default_value" type="Vector2" setter="set_default_value" getter="get_default_value" default="Vector2(0, 0)"> + A default value to be assigned within the shader. + </member> + <member name="default_value_enabled" type="bool" setter="set_default_value_enabled" getter="is_default_value_enabled" default="false"> + Enables usage of the [member default_value]. + </member> + </members> +</class> diff --git a/doc/classes/VisualShaderNodeVectorBase.xml b/doc/classes/VisualShaderNodeVectorBase.xml new file mode 100644 index 0000000000..8a560c1951 --- /dev/null +++ b/doc/classes/VisualShaderNodeVectorBase.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeVectorBase" inherits="VisualShaderNode" version="4.0"> + <brief_description> + A base type for the nodes using different vector types within the visual shader graph. + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <members> + <member name="op_type" type="int" setter="set_op_type" getter="get_op_type" enum="VisualShaderNodeVectorBase.OpType" default="1"> + A base type. + </member> + </members> + <constants> + <constant name="OP_TYPE_VECTOR_2D" value="0" enum="OpType"> + A 2D vector type. + </constant> + <constant name="OP_TYPE_VECTOR_3D" value="1" enum="OpType"> + A 3D vector type. + </constant> + <constant name="OP_TYPE_MAX" value="2" enum="OpType"> + Represents the size of the [enum OpType] enum. + </constant> + </constants> +</class> diff --git a/doc/classes/VisualShaderNodeVectorCompose.xml b/doc/classes/VisualShaderNodeVectorCompose.xml index ebc30d03f4..b8caf154f9 100644 --- a/doc/classes/VisualShaderNodeVectorCompose.xml +++ b/doc/classes/VisualShaderNodeVectorCompose.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualShaderNodeVectorCompose" inherits="VisualShaderNode" version="4.0"> +<class name="VisualShaderNodeVectorCompose" inherits="VisualShaderNodeVectorBase" version="4.0"> <brief_description> Composes a [Vector3] from three scalars within the visual shader graph. </brief_description> diff --git a/doc/classes/VisualShaderNodeVectorDecompose.xml b/doc/classes/VisualShaderNodeVectorDecompose.xml index 09986bf969..9ef9db0cfb 100644 --- a/doc/classes/VisualShaderNodeVectorDecompose.xml +++ b/doc/classes/VisualShaderNodeVectorDecompose.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualShaderNodeVectorDecompose" inherits="VisualShaderNode" version="4.0"> +<class name="VisualShaderNodeVectorDecompose" inherits="VisualShaderNodeVectorBase" version="4.0"> <brief_description> Decomposes a [Vector3] into three scalars within the visual shader graph. </brief_description> diff --git a/doc/classes/VisualShaderNodeVectorDistance.xml b/doc/classes/VisualShaderNodeVectorDistance.xml index 098787e583..c0d8ffe943 100644 --- a/doc/classes/VisualShaderNodeVectorDistance.xml +++ b/doc/classes/VisualShaderNodeVectorDistance.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualShaderNodeVectorDistance" inherits="VisualShaderNode" version="4.0"> +<class name="VisualShaderNodeVectorDistance" inherits="VisualShaderNodeVectorBase" version="4.0"> <brief_description> Returns the distance between two points. To be used within the visual shader graph. </brief_description> diff --git a/doc/classes/VisualShaderNodeVectorFunc.xml b/doc/classes/VisualShaderNodeVectorFunc.xml index 27ae82e11b..17a6418b94 100644 --- a/doc/classes/VisualShaderNodeVectorFunc.xml +++ b/doc/classes/VisualShaderNodeVectorFunc.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualShaderNodeVectorFunc" inherits="VisualShaderNode" version="4.0"> +<class name="VisualShaderNodeVectorFunc" inherits="VisualShaderNodeVectorBase" version="4.0"> <brief_description> A vector function to be used within the visual shader graph. </brief_description> diff --git a/doc/classes/VisualShaderNodeVectorLen.xml b/doc/classes/VisualShaderNodeVectorLen.xml index 165455e622..f1b6919bdc 100644 --- a/doc/classes/VisualShaderNodeVectorLen.xml +++ b/doc/classes/VisualShaderNodeVectorLen.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualShaderNodeVectorLen" inherits="VisualShaderNode" version="4.0"> +<class name="VisualShaderNodeVectorLen" inherits="VisualShaderNodeVectorBase" version="4.0"> <brief_description> Returns the length of a [Vector3] within the visual shader graph. </brief_description> diff --git a/doc/classes/VisualShaderNodeVectorOp.xml b/doc/classes/VisualShaderNodeVectorOp.xml index 5e8f0abda3..6a579abb9a 100644 --- a/doc/classes/VisualShaderNodeVectorOp.xml +++ b/doc/classes/VisualShaderNodeVectorOp.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualShaderNodeVectorOp" inherits="VisualShaderNode" version="4.0"> +<class name="VisualShaderNodeVectorOp" inherits="VisualShaderNodeVectorBase" version="4.0"> <brief_description> A vector operator to be used within the visual shader graph. </brief_description> diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 433866602b..e36d0b846b 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -3481,7 +3481,7 @@ void AnimationTrackEditor::_track_remove_request(int p_track) { void AnimationTrackEditor::_track_grab_focus(int p_track) { // Don't steal focus if not working with the track editor. - if (Object::cast_to<AnimationTrackEdit>(get_focus_owner())) { + if (Object::cast_to<AnimationTrackEdit>(get_viewport()->gui_get_focus_owner())) { track_edits[p_track]->grab_focus(); } } diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 0a269d960e..967f7e0d1f 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -122,7 +122,7 @@ void FindReplaceBar::unhandled_input(const Ref<InputEvent> &p_event) { return; } - Control *focus_owner = get_focus_owner(); + Control *focus_owner = get_viewport()->gui_get_focus_owner(); if (text_editor->has_focus() || (focus_owner && vbc_lineedit->is_ancestor_of(focus_owner))) { bool accepted = true; @@ -724,7 +724,7 @@ void CodeTextEditor::input(const Ref<InputEvent> &event) { } if (!text_editor->has_focus()) { - if ((find_replace_bar != nullptr && find_replace_bar->is_visible()) && (find_replace_bar->has_focus() || find_replace_bar->is_ancestor_of(get_focus_owner()))) { + if ((find_replace_bar != nullptr && find_replace_bar->is_visible()) && (find_replace_bar->has_focus() || find_replace_bar->is_ancestor_of(get_viewport()->gui_get_focus_owner()))) { if (ED_IS_SHORTCUT("script_text_editor/find_next", key_event)) { find_replace_bar->search_next(); accept_event(); diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index a2ed844b1b..21aa5153d1 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -540,13 +540,27 @@ ConnectDialog::~ConnectDialog() { // Originally copied and adapted from EditorProperty, try to keep style in sync. Control *ConnectionsDockTree::make_custom_tooltip(const String &p_text) const { EditorHelpBit *help_bit = memnew(EditorHelpBit); - help_bit->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"))); help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE); - String text = TTR("Signal:") + " [u][b]" + p_text.get_slice("::", 0) + "[/b][/u]"; - text += p_text.get_slice("::", 1).strip_edges() + "\n"; - text += p_text.get_slice("::", 2).strip_edges(); - help_bit->call_deferred(SNAME("set_text"), text); // Hack so it uses proper theme once inside scene. + // p_text is expected to be something like this: + // "gui_input::(event: InputEvent)::<Signal description>" + // with the latter being possibly empty. + PackedStringArray slices = p_text.split("::", false); + if (slices.size() < 2) { + // Shouldn't happen here, but just in case pass the text along. + help_bit->set_text(p_text); + return help_bit; + } + + String text = TTR("Signal:") + " [u][b]" + slices[0] + "[/b][/u]"; + text += slices[1].strip_edges() + "\n"; + if (slices.size() > 2) { + text += slices[2].strip_edges(); + } else { + text += "[i]" + TTR("No description.") + "[/i]"; + } + help_bit->set_text(text); + return help_bit; } diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index e2499c7c20..dfc95fb676 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1910,6 +1910,8 @@ DocTools *EditorHelp::get_doc_data() { return doc; } +//// EditorHelpBit /// + void EditorHelpBit::_go_to_help(String p_what) { EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT); ScriptEditor::get_singleton()->goto_help(p_what); @@ -1950,12 +1952,9 @@ void EditorHelpBit::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { rich_text->add_theme_color_override("selection_color", get_theme_color(SNAME("selection_color"), SNAME("EditorHelp"))); - } break; - - case NOTIFICATION_READY: { rich_text->clear(); _add_text_to_rt(text, rich_text); - + rich_text->reset_size(); // Force recalculating size after parsing bbcode. } break; } } @@ -1971,9 +1970,12 @@ EditorHelpBit::EditorHelpBit() { add_child(rich_text); rich_text->connect("meta_clicked", callable_mp(this, &EditorHelpBit::_meta_clicked)); rich_text->set_override_selected_font_color(false); - set_custom_minimum_size(Size2(0, 70 * EDSCALE)); + rich_text->set_fit_content_height(true); + set_custom_minimum_size(Size2(0, 50 * EDSCALE)); } +//// FindBar /// + FindBar::FindBar() { search_text = memnew(LineEdit); add_child(search_text); @@ -2126,7 +2128,7 @@ void FindBar::unhandled_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; if (k.is_valid()) { - if (k->is_pressed() && (rich_text_label->has_focus() || is_ancestor_of(get_focus_owner()))) { + if (k->is_pressed() && (rich_text_label->has_focus() || is_ancestor_of(get_viewport()->gui_get_focus_owner()))) { bool accepted = true; switch (k->get_keycode()) { diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 1259c97021..34cace0239 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -833,30 +833,42 @@ void EditorProperty::_update_pin_flags() { } } -Control *EditorProperty::make_custom_tooltip(const String &p_text) const { - tooltip_text = p_text; +static Control *make_help_bit(const String &p_text, bool p_property) { EditorHelpBit *help_bit = memnew(EditorHelpBit); - //help_bit->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"))); help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE); - String text; PackedStringArray slices = p_text.split("::", false); - if (!slices.is_empty()) { - String property_name = slices[0].strip_edges(); - text = TTR("Property:") + " [u][b]" + property_name + "[/b][/u]"; + if (slices.is_empty()) { + // Shouldn't happen here, but just in case pass the text along. + help_bit->set_text(p_text); + return help_bit; + } - if (slices.size() > 1) { - String property_doc = slices[1].strip_edges(); - if (property_name != property_doc) { - text += "\n" + property_doc; - } + String property_name = slices[0].strip_edges(); + String text; + if (p_property) { + text = TTR("Property:") + " "; + } + text += "[u][b]" + property_name + "[/b][/u]"; + + if (slices.size() > 1) { + String property_doc = slices[1].strip_edges(); + if (property_name != property_doc) { + text += "\n" + property_doc; } - help_bit->call_deferred(SNAME("set_text"), text); //hack so it uses proper theme once inside scene + } else { + text += "\n[i]" + TTR("No description.") + "[/i]"; } + help_bit->set_text(text); return help_bit; } +Control *EditorProperty::make_custom_tooltip(const String &p_text) const { + tooltip_text = p_text; + return make_help_bit(p_text, true); +} + String EditorProperty::get_tooltip_text() const { return tooltip_text; } @@ -1094,25 +1106,7 @@ void EditorInspectorCategory::_notification(int p_what) { Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) const { tooltip_text = p_text; - EditorHelpBit *help_bit = memnew(EditorHelpBit); - help_bit->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"))); - help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE); - - PackedStringArray slices = p_text.split("::", false); - if (!slices.is_empty()) { - String property_name = slices[0].strip_edges(); - String text = "[u][b]" + property_name + "[/b][/u]"; - - if (slices.size() > 1) { - String property_doc = slices[1].strip_edges(); - if (property_name != property_doc) { - text += "\n" + property_doc; - } - } - help_bit->call_deferred(SNAME("set_text"), text); //hack so it uses proper theme once inside scene - } - - return help_bit; + return make_help_bit(p_text, false); } Size2 EditorInspectorCategory::get_minimum_size() const { @@ -2305,7 +2299,7 @@ void EditorInspector::update_tree() { if (property_focusable != -1) { //check focusable is really focusable bool restore_focus = false; - Control *focused = get_focus_owner(); + Control *focused = get_viewport() ? get_viewport()->gui_get_focus_owner() : nullptr; if (focused) { Node *parent = focused->get_parent(); while (parent) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 75423f120d..076a774efa 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -93,6 +93,7 @@ #include "editor/editor_run_script.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_settings_dialog.h" #include "editor/editor_spin_slider.h" #include "editor/editor_themes.h" #include "editor/editor_toaster.h" @@ -190,7 +191,6 @@ #include "editor/project_settings_editor.h" #include "editor/quick_open.h" #include "editor/register_exporters.h" -#include "editor/settings_config_dialog.h" #include <stdio.h> #include <stdlib.h> @@ -822,8 +822,8 @@ void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_nam if (p_activate_name.length()) { set_addon_plugin_enabled(p_activate_name, true); } - project_settings->update_plugins(); - project_settings->hide(); + project_settings_editor->update_plugins(); + project_settings_editor->hide(); push_item(script.operator->()); } @@ -2773,7 +2773,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case RUN_SETTINGS: { - project_settings->popup_project_settings(); + project_settings_editor->popup_project_settings(); } break; case FILE_INSTALL_ANDROID_SOURCE: { if (p_confirmed) { @@ -2846,7 +2846,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { _update_update_spinner(); } break; case SETTINGS_PREFERENCES: { - settings_config_dialog->popup_edit_settings(); + editor_settings_dialog->popup_edit_settings(); } break; case SETTINGS_EDITOR_DATA_FOLDER: { OS::get_singleton()->shell_open(String("file://") + EditorPaths::get_singleton()->get_data_dir()); @@ -3240,7 +3240,7 @@ void EditorNode::_update_addon_config() { ProjectSettings::get_singleton()->set("editor_plugins/enabled", enabled_addons); } - project_settings->queue_save(); + project_settings_editor->queue_save(); } void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed) { @@ -6329,11 +6329,11 @@ EditorNode::EditorNode() { dependency_fixer = memnew(DependencyEditor); gui_base->add_child(dependency_fixer); - settings_config_dialog = memnew(EditorSettingsDialog); - gui_base->add_child(settings_config_dialog); + editor_settings_dialog = memnew(EditorSettingsDialog); + gui_base->add_child(editor_settings_dialog); - project_settings = memnew(ProjectSettingsEditor(&editor_data)); - gui_base->add_child(project_settings); + project_settings_editor = memnew(ProjectSettingsEditor(&editor_data)); + gui_base->add_child(project_settings_editor); scene_import_settings = memnew(SceneImportSettings); gui_base->add_child(scene_import_settings); diff --git a/editor/editor_node.h b/editor/editor_node.h index f8489777bd..5c013a18d9 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -323,8 +323,8 @@ private: ConfirmationDialog *install_android_build_template; ConfirmationDialog *remove_android_build_template; - EditorSettingsDialog *settings_config_dialog; - ProjectSettingsEditor *project_settings; + EditorSettingsDialog *editor_settings_dialog; + ProjectSettingsEditor *project_settings_editor; bool settings_changed = true; // make it update settings on first frame void _update_from_settings(); @@ -713,7 +713,7 @@ public: EditorPluginList *get_editor_plugins_force_over() { return editor_plugins_force_over; } EditorPluginList *get_editor_plugins_force_input_forwarding() { return editor_plugins_force_input_forwarding; } - ProjectSettingsEditor *get_project_settings() { return project_settings; } + ProjectSettingsEditor *get_project_settings() { return project_settings_editor; } static void add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); static void remove_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index d01775ac35..ef1ceebabf 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3318,9 +3318,9 @@ struct EditorPropertyRangeHint { bool angle_in_degrees = false; bool greater = true; bool lesser = true; - double min = -99999; - double max = 99999; - double step = 0; + double min = -99999.0; + double max = 99999.0; + double step = 1.0; String suffix; bool exp_range = false; bool hide_slider = true; @@ -3331,18 +3331,25 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri EditorPropertyRangeHint hint; hint.step = p_default_step; bool degrees = false; - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - hint.greater = false; //if using ranged, assume false by default + + if (p_hint == PROPERTY_HINT_RANGE) { + Vector<String> slices = p_hint_text.split(","); + ERR_FAIL_COND_V_MSG(slices.size() < 2, hint, + vformat("Invalid PROPERTY_HINT_RANGE with hint \"%s\": Missing required min and/or max values.", p_hint_text)); + + hint.greater = false; // If using ranged, assume false by default. hint.lesser = false; - hint.min = p_hint_text.get_slice(",", 0).to_float(); - hint.max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - hint.step = p_hint_text.get_slice(",", 2).to_float(); + hint.min = slices[0].to_float(); + hint.max = slices[1].to_float(); + + if (slices.size() >= 3 && slices[2].is_valid_float()) { + // Step is optional, could be something else if not a number. + hint.step = slices[2].to_float(); } hint.hide_slider = false; - for (int i = 2; i < p_hint_text.get_slice_count(","); i++) { - String slice = p_hint_text.get_slice(",", i).strip_edges(); + for (int i = 2; i < slices.size(); i++) { + String slice = slices[i].strip_edges(); if (slice == "radians") { hint.radians = true; } else if (slice == "degrees") { @@ -3365,6 +3372,9 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri hint.suffix = U"\u00B0"; } + ERR_FAIL_COND_V_MSG(hint.step == 0, hint, + vformat("Invalid PROPERTY_HINT_RANGE with hint \"%s\": Step cannot be 0.", p_hint_text)); + return hint; } @@ -3435,7 +3445,6 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyInteger *editor = memnew(EditorPropertyInteger); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); - editor->setup(hint.min, hint.max, hint.step, hint.greater, hint.lesser); return editor; diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 71a855b22c..cfed86d1ae 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -502,6 +502,16 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d } void EditorPropertyArray::_notification(int p_what) { + if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) { + change_type->clear(); + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + String type = Variant::get_type_name(Variant::Type(i)); + change_type->add_icon_item(get_theme_icon(type, SNAME("EditorIcons")), type, i); + } + change_type->add_separator(); + change_type->add_icon_item(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Remove Item"), Variant::VARIANT_MAX); + } + if (p_what == NOTIFICATION_DRAG_BEGIN) { if (is_visible_in_tree()) { if (_is_drop_valid(get_viewport()->gui_get_drag_data())) { @@ -691,13 +701,6 @@ EditorPropertyArray::EditorPropertyArray() { change_type = memnew(PopupMenu); add_child(change_type); change_type->connect("id_pressed", callable_mp(this, &EditorPropertyArray::_change_type_menu)); - - for (int i = 0; i < Variant::VARIANT_MAX; i++) { - String type = Variant::get_type_name(Variant::Type(i)); - change_type->add_item(type, i); - } - change_type->add_separator(); - change_type->add_item(TTR("Remove Item"), Variant::VARIANT_MAX); changing_type_index = -1; subtype = Variant::NIL; @@ -1119,10 +1122,11 @@ void EditorPropertyDictionary::update_property() { prop->update_property(); if (i == amount + 1) { - Button *butt_add_item = memnew(Button); - butt_add_item->set_text(TTR("Add Key/Value Pair")); - butt_add_item->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_add_key_value)); - add_vbox->add_child(butt_add_item); + button_add_item = memnew(Button); + button_add_item->set_text(TTR("Add Key/Value Pair")); + button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + button_add_item->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_add_key_value)); + add_vbox->add_child(button_add_item); } } @@ -1142,6 +1146,19 @@ void EditorPropertyDictionary::_object_id_selected(const StringName &p_property, } void EditorPropertyDictionary::_notification(int p_what) { + if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) { + change_type->clear(); + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + String type = Variant::get_type_name(Variant::Type(i)); + change_type->add_icon_item(get_theme_icon(type, SNAME("EditorIcons")), type, i); + } + change_type->add_separator(); + change_type->add_icon_item(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Remove Item"), Variant::VARIANT_MAX); + + if (Object::cast_to<Button>(button_add_item)) { + button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + } + } } void EditorPropertyDictionary::_edit_pressed() { @@ -1179,16 +1196,10 @@ EditorPropertyDictionary::EditorPropertyDictionary() { add_focusable(edit); vbox = nullptr; page_slider = nullptr; + button_add_item = nullptr; updating = false; change_type = memnew(PopupMenu); add_child(change_type); change_type->connect("id_pressed", callable_mp(this, &EditorPropertyDictionary::_change_type_menu)); - - for (int i = 0; i < Variant::VARIANT_MAX; i++) { - String type = Variant::get_type_name(Variant::Type(i)); - change_type->add_item(type, i); - } - change_type->add_separator(); - change_type->add_item(TTR("Remove Item"), Variant::VARIANT_MAX); changing_type_index = -1; } diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h index 4c31ba0b49..bb10cdf97e 100644 --- a/editor/editor_properties_array_dict.h +++ b/editor/editor_properties_array_dict.h @@ -147,6 +147,7 @@ class EditorPropertyDictionary : public EditorProperty { EditorSpinSlider *size_slider; EditorSpinSlider *page_slider; HBoxContainer *page_hbox; + Button *button_add_item; void _page_changed(double p_page); void _edit_pressed(); diff --git a/editor/settings_config_dialog.cpp b/editor/editor_settings_dialog.cpp index c4d361bd49..2520d662c5 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* settings_config_dialog.cpp */ +/* editor_settings_dialog.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "settings_config_dialog.h" +#include "editor_settings_dialog.h" #include "core/config/project_settings.h" #include "core/input/input_map.h" diff --git a/editor/settings_config_dialog.h b/editor/editor_settings_dialog.h index c3dfd736d5..f1c4ea7770 100644 --- a/editor/settings_config_dialog.h +++ b/editor/editor_settings_dialog.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* settings_config_dialog.h */ +/* editor_settings_dialog.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SETTINGS_CONFIG_DIALOG_H -#define SETTINGS_CONFIG_DIALOG_H +#ifndef EDITOR_SETTINGS_DIALOG_H +#define EDITOR_SETTINGS_DIALOG_H #include "editor/action_map_editor.h" #include "editor/editor_sectioned_inspector.h" @@ -128,4 +128,4 @@ public: ~EditorSettingsDialog(); }; -#endif // SETTINGS_CONFIG_DIALOG_H +#endif // EDITOR_SETTINGS_DIALOG_H diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index dff01cbf05..d496804bf2 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2507,7 +2507,7 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { _update_cursor(); // Grab focus - if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) { + if (!viewport->has_focus() && (!get_viewport()->gui_get_focus_owner() || !get_viewport()->gui_get_focus_owner()->is_text_field())) { viewport->call_deferred(SNAME("grab_focus")); } } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 4610171d68..0c0188e8d1 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1203,7 +1203,7 @@ Transform3D Node3DEditorViewport::_compute_transform(TransformMode p_mode, const } void Node3DEditorViewport::_surface_mouse_enter() { - if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) { + if (!surface->has_focus() && (!get_viewport()->gui_get_focus_owner() || !get_viewport()->gui_get_focus_owner()->is_text_field())) { surface->grab_focus(); } } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 914b548372..26227fa5bb 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1603,7 +1603,8 @@ void ScriptEditor::_notification(int p_what) { members_overview->connect("item_selected", callable_mp(this, &ScriptEditor::_members_overview_selected)); help_overview->connect("item_selected", callable_mp(this, &ScriptEditor::_help_overview_selected)); - script_split->connect("dragged", callable_mp(this, &ScriptEditor::_script_split_dragged)); + script_split->connect("dragged", callable_mp(this, &ScriptEditor::_split_dragged)); + list_split->connect("dragged", callable_mp(this, &ScriptEditor::_split_dragged)); EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &ScriptEditor::_editor_settings_changed)); EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &ScriptEditor::_filesystem_changed)); @@ -2809,7 +2810,7 @@ void ScriptEditor::_tree_changed() { call_deferred(SNAME("_update_script_connections")); } -void ScriptEditor::_script_split_dragged(float) { +void ScriptEditor::_split_dragged(float) { _save_layout(); } @@ -3199,8 +3200,12 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) { tab_container->get_child(i)->set_meta("__editor_pass", Variant()); } - if (p_layout->has_section_key("ScriptEditor", "split_offset")) { - script_split->set_split_offset(p_layout->get_value("ScriptEditor", "split_offset")); + if (p_layout->has_section_key("ScriptEditor", "script_split_offset")) { + script_split->set_split_offset(p_layout->get_value("ScriptEditor", "script_split_offset")); + } + + if (p_layout->has_section_key("ScriptEditor", "list_split_offset")) { + list_split->set_split_offset(p_layout->get_value("ScriptEditor", "list_split_offset")); } // Remove any deleted editors that have been removed between launches. @@ -3253,7 +3258,8 @@ void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) { p_layout->set_value("ScriptEditor", "open_scripts", scripts); p_layout->set_value("ScriptEditor", "open_help", helps); - p_layout->set_value("ScriptEditor", "split_offset", script_split->get_split_offset()); + p_layout->set_value("ScriptEditor", "script_split_offset", script_split->get_split_offset()); + p_layout->set_value("ScriptEditor", "list_split_offset", list_split->get_split_offset()); // Save the cache. script_editor_cache->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("script_editor_cache.cfg")); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 67a6a9da02..d754f1a378 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -418,7 +418,7 @@ class ScriptEditor : public PanelContainer { void _tree_changed(); - void _script_split_dragged(float); + void _split_dragged(float); Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index bc2739bdac..aaa09237cf 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -2226,7 +2226,7 @@ void ThemeTypeEditor::_update_type_list() { } updating = true; - Control *focused = get_focus_owner(); + Control *focused = get_viewport()->gui_get_focus_owner(); if (focused) { if (focusables.has(focused)) { // If focus is currently on one of the internal property editors, don't update. diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 61657397f1..9ab53bf5c3 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -202,6 +202,10 @@ void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_ case Variant::FLOAT: { button->set_text(String::num(p_value, 4)); } break; + case Variant::VECTOR2: { + Vector2 v = p_value; + button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3)); + } break; case Variant::VECTOR3: { Vector3 v = p_value; button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3)); @@ -358,10 +362,11 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { static Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1); - static const Color type_color[6] = { + static const Color type_color[7] = { Color(0.38, 0.85, 0.96), // scalar (float) Color(0.49, 0.78, 0.94), // scalar (int) - Color(0.84, 0.49, 0.93), // vector + Color(0.74, 0.57, 0.95), // vector2 + Color(0.84, 0.49, 0.93), // vector3 Color(0.55, 0.65, 0.94), // boolean Color(0.96, 0.66, 0.43), // transform Color(1.0, 1.0, 0.0), // sampler @@ -597,8 +602,15 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { int output_port_count = 0; for (int i = 0; i < vsnode->get_output_port_count(); i++) { if (vsnode->_is_output_port_expanded(i)) { - if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) { - output_port_count += 3; + switch (vsnode->get_output_port_type(i)) { + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + output_port_count += 2; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + output_port_count += 3; + } break; + default: + break; } } output_port_count++; @@ -608,10 +620,23 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { int expanded_port_counter = 0; for (int i = 0, j = 0; i < max_ports; i++, j++) { - if (expanded_type == VisualShaderNode::PORT_TYPE_VECTOR && expanded_port_counter >= 3) { - expanded_type = VisualShaderNode::PORT_TYPE_SCALAR; - expanded_port_counter = 0; - i -= 3; + switch (expanded_type) { + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + if (expanded_port_counter >= 2) { + expanded_type = VisualShaderNode::PORT_TYPE_SCALAR; + expanded_port_counter = 0; + i -= 2; + } + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + if (expanded_port_counter >= 3) { + expanded_type = VisualShaderNode::PORT_TYPE_SCALAR; + expanded_port_counter = 0; + i -= 3; + } + } break; + default: + break; } if (vsnode->is_port_separator(i)) { @@ -682,7 +707,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { hb->add_child(type_box); type_box->add_item(TTR("Float")); type_box->add_item(TTR("Int")); - type_box->add_item(TTR("Vector")); + type_box->add_item(TTR("Vector2")); + type_box->add_item(TTR("Vector3")); type_box->add_item(TTR("Boolean")); type_box->add_item(TTR("Transform")); type_box->add_item(TTR("Sampler")); @@ -743,7 +769,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { hb->add_child(type_box); type_box->add_item(TTR("Float")); type_box->add_item(TTR("Int")); - type_box->add_item(TTR("Vector")); + type_box->add_item(TTR("Vector2")); + type_box->add_item(TTR("Vector3")); type_box->add_item(TTR("Boolean")); type_box->add_item(TTR("Transform")); type_box->select(group_node->get_output_port_type(i)); @@ -805,31 +832,55 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { node->set_slot(idx, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]); if (vsnode->_is_output_port_expanded(i)) { - if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) { - port_offset++; - valid_left = (i + 1) < vsnode->get_input_port_count(); - port_left = VisualShaderNode::PORT_TYPE_SCALAR; - if (valid_left) { - port_left = vsnode->get_input_port_type(i + 1); - } - node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]); - port_offset++; + switch (vsnode->get_output_port_type(i)) { + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + port_offset++; + valid_left = (i + 1) < vsnode->get_input_port_count(); + port_left = VisualShaderNode::PORT_TYPE_SCALAR; + if (valid_left) { + port_left = vsnode->get_input_port_type(i + 1); + } + node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]); + port_offset++; - valid_left = (i + 2) < vsnode->get_input_port_count(); - port_left = VisualShaderNode::PORT_TYPE_SCALAR; - if (valid_left) { - port_left = vsnode->get_input_port_type(i + 2); - } - node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]); - port_offset++; + valid_left = (i + 2) < vsnode->get_input_port_count(); + port_left = VisualShaderNode::PORT_TYPE_SCALAR; + if (valid_left) { + port_left = vsnode->get_input_port_type(i + 2); + } + node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]); + + expanded_type = VisualShaderNode::PORT_TYPE_VECTOR_2D; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + port_offset++; + valid_left = (i + 1) < vsnode->get_input_port_count(); + port_left = VisualShaderNode::PORT_TYPE_SCALAR; + if (valid_left) { + port_left = vsnode->get_input_port_type(i + 1); + } + node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]); + port_offset++; - valid_left = (i + 3) < vsnode->get_input_port_count(); - port_left = VisualShaderNode::PORT_TYPE_SCALAR; - if (valid_left) { - port_left = vsnode->get_input_port_type(i + 3); - } - node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]); - expanded_type = VisualShaderNode::PORT_TYPE_VECTOR; + valid_left = (i + 2) < vsnode->get_input_port_count(); + port_left = VisualShaderNode::PORT_TYPE_SCALAR; + if (valid_left) { + port_left = vsnode->get_input_port_type(i + 2); + } + node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]); + port_offset++; + + valid_left = (i + 3) < vsnode->get_input_port_count(); + port_left = VisualShaderNode::PORT_TYPE_SCALAR; + if (valid_left) { + port_left = vsnode->get_input_port_type(i + 3); + } + node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]); + + expanded_type = VisualShaderNode::PORT_TYPE_VECTOR; + } break; + default: + break; } } } @@ -1378,6 +1429,9 @@ void VisualShaderEditor::_update_options_menu() { case VisualShaderNode::PORT_TYPE_SCALAR_INT: item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("int"), SNAME("EditorIcons"))); break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons"))); + break; case VisualShaderNode::PORT_TYPE_VECTOR: item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons"))); break; @@ -1476,6 +1530,7 @@ void VisualShaderEditor::_update_uniforms(bool p_update_refs) { if (uniform.is_valid()) { Ref<VisualShaderNodeFloatUniform> float_uniform = vsnode; Ref<VisualShaderNodeIntUniform> int_uniform = vsnode; + Ref<VisualShaderNodeVec2Uniform> vec2_uniform = vsnode; Ref<VisualShaderNodeVec3Uniform> vec3_uniform = vsnode; Ref<VisualShaderNodeColorUniform> color_uniform = vsnode; Ref<VisualShaderNodeBooleanUniform> bool_uniform = vsnode; @@ -1488,8 +1543,10 @@ void VisualShaderEditor::_update_uniforms(bool p_update_refs) { uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_INT; } else if (bool_uniform.is_valid()) { uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_BOOLEAN; + } else if (vec2_uniform.is_valid()) { + uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_VECTOR2; } else if (vec3_uniform.is_valid()) { - uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_VECTOR; + uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_VECTOR3; } else if (transform_uniform.is_valid()) { uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_TRANSFORM; } else if (color_uniform.is_valid()) { @@ -1728,8 +1785,15 @@ void VisualShaderEditor::_expand_output_port(int p_node, int p_port, bool p_expa undo_redo->add_undo_method(node.ptr(), "_set_output_port_expanded", p_port, !p_expand); int type_size = 0; - if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_VECTOR) { - type_size = 3; + switch (node->get_output_port_type(p_port)) { + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + type_size = 2; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + type_size = 3; + } break; + default: + break; } List<VisualShader::Connection> conns; @@ -2228,7 +2292,9 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, const Vector<Vari if (vecOp) { ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT); + ERR_FAIL_COND(p_ops[1].get_type() != Variant::INT); vecOp->set_operator((VisualShaderNodeVectorOp::Operator)(int)p_ops[0]); + vecOp->set_op_type((VisualShaderNodeVectorOp::OpType)(int)p_ops[1]); return; } } @@ -2239,7 +2305,9 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, const Vector<Vari if (vecFunc) { ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT); + ERR_FAIL_COND(p_ops[1].get_type() != Variant::INT); vecFunc->set_function((VisualShaderNodeVectorFunc::Function)(int)p_ops[0]); + vecFunc->set_op_type((VisualShaderNodeVectorFunc::OpType)(int)p_ops[1]); return; } } @@ -2310,7 +2378,29 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, const Vector<Vari } } - //UV_FUNC + // VECTOR_COMPOSE + { + VisualShaderNodeVectorCompose *vecCompose = Object::cast_to<VisualShaderNodeVectorCompose>(p_node); + + if (vecCompose) { + ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT); + vecCompose->set_op_type((VisualShaderNodeVectorCompose::OpType)(int)p_ops[0]); + return; + } + } + + // VECTOR_DECOMPOSE + { + VisualShaderNodeVectorDecompose *vecDecompose = Object::cast_to<VisualShaderNodeVectorDecompose>(p_node); + + if (vecDecompose) { + ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT); + vecDecompose->set_op_type((VisualShaderNodeVectorDecompose::OpType)(int)p_ops[0]); + return; + } + } + + // UV_FUNC { VisualShaderNodeUVFunc *uvFunc = Object::cast_to<VisualShaderNodeUVFunc>(p_node); @@ -2343,6 +2433,17 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, const Vector<Vari } } + // DISTANCE + { + VisualShaderNodeVectorDistance *dist = Object::cast_to<VisualShaderNodeVectorDistance>(p_node); + + if (dist) { + ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT); + dist->set_op_type((VisualShaderNodeVectorDistance::OpType)(int)p_ops[0]); + return; + } + } + // DERIVATIVE { VisualShaderNodeDerivativeFunc *derFunc = Object::cast_to<VisualShaderNodeDerivativeFunc>(p_node); @@ -2389,6 +2490,26 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, const Vector<Vari } } + // FACEFORWARD + { + VisualShaderNodeFaceForward *faceForward = Object::cast_to<VisualShaderNodeFaceForward>(p_node); + if (faceForward) { + ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT); + faceForward->set_op_type((VisualShaderNodeFaceForward::OpType)(int)p_ops[0]); + return; + } + } + + // LENGTH + { + VisualShaderNodeVectorLen *length = Object::cast_to<VisualShaderNodeVectorLen>(p_node); + if (length) { + ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT); + length->set_op_type((VisualShaderNodeVectorLen::OpType)(int)p_ops[0]); + return; + } + } + // SMOOTHSTEP { VisualShaderNodeSmoothStep *smoothStepFunc = Object::cast_to<VisualShaderNodeSmoothStep>(p_node); @@ -2524,6 +2645,9 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri case VisualShaderNode::PORT_TYPE_SCALAR_INT: initial_expression_code = "output0 = 1;"; break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: + initial_expression_code = "output0 = vec2(1.0, 1.0);"; + break; case VisualShaderNode::PORT_TYPE_VECTOR: initial_expression_code = "output0 = vec3(1.0, 1.0, 1.0);"; break; @@ -2934,6 +3058,25 @@ void VisualShaderEditor::_convert_constants_to_uniforms(bool p_vice_versa) { } } + // vec2 + if (!caught) { + if (!p_vice_versa) { + Ref<VisualShaderNodeVec2Constant> vec2_const = Object::cast_to<VisualShaderNodeVec2Constant>(node.ptr()); + if (vec2_const.is_valid()) { + _replace_node(type_id, node_id, "VisualShaderNodeVec2Constant", "VisualShaderNodeVec2Uniform"); + var = vec2_const->get_constant(); + caught = true; + } + } else { + Ref<VisualShaderNodeVec2Uniform> vec2_uniform = Object::cast_to<VisualShaderNodeVec2Uniform>(node.ptr()); + if (vec2_uniform.is_valid()) { + _replace_node(type_id, node_id, "VisualShaderNodeVec2Uniform", "VisualShaderNodeVec2Constant"); + var = vec2_uniform->get_default_value(); + caught = true; + } + } + } + // vec3 if (!caught) { if (!p_vice_versa) { @@ -4038,6 +4181,7 @@ VisualShaderEditor::VisualShaderEditor() { graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR); graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR_INT); graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_BOOLEAN); + graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_2D); graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR); graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_TRANSFORM); graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SAMPLER); @@ -4057,18 +4201,27 @@ VisualShaderEditor::VisualShaderEditor() { graph->connect("visibility_changed", callable_mp(this, &VisualShaderEditor::_visibility_changed)); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR_INT); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_2D); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_BOOLEAN); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR_INT); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_2D); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_BOOLEAN); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR_INT); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_2D); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_BOOLEAN); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_SCALAR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_SCALAR_INT); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_VECTOR_2D); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_VECTOR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_BOOLEAN); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR_INT); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_2D); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_BOOLEAN); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM); @@ -4314,6 +4467,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ColorConstant", "Color", "Variables", "VisualShaderNodeColorConstant", TTR("Color constant."))); add_options.push_back(AddOption("ColorUniform", "Color", "Variables", "VisualShaderNodeColorUniform", TTR("Color uniform."))); + // COMMON + + add_options.push_back(AddOption("DerivativeFunc", "Common", "", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) Derivative function."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); + // CONDITIONAL const String &compare_func_desc = TTR("Returns the boolean result of the %s comparison between two parameters."); @@ -4327,7 +4484,8 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("LessThan", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Less Than (<)")), { VisualShaderNodeCompare::FUNC_LESS_THAN }, VisualShaderNode::PORT_TYPE_BOOLEAN)); add_options.push_back(AddOption("LessThanEqual", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Less Than or Equal (<=)")), { VisualShaderNodeCompare::FUNC_LESS_THAN_EQUAL }, VisualShaderNode::PORT_TYPE_BOOLEAN)); add_options.push_back(AddOption("NotEqual", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Not Equal (!=)")), { VisualShaderNodeCompare::FUNC_NOT_EQUAL }, VisualShaderNode::PORT_TYPE_BOOLEAN)); - add_options.push_back(AddOption("Switch", "Conditional", "Functions", "VisualShaderNodeSwitch", TTR("Returns an associated vector if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_VECTOR }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Switch", "Conditional", "Functions", "VisualShaderNodeSwitch", TTR("Returns an associated 3D vector if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Switch2D", "Conditional", "Functions", "VisualShaderNodeSwitch", TTR("Returns an associated 2D vector if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); add_options.push_back(AddOption("SwitchBool", "Conditional", "Functions", "VisualShaderNodeSwitch", TTR("Returns an associated boolean if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_BOOLEAN }, VisualShaderNode::PORT_TYPE_BOOLEAN)); add_options.push_back(AddOption("SwitchFloat", "Conditional", "Functions", "VisualShaderNodeSwitch", TTR("Returns an associated floating-point scalar if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_FLOAT }, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("SwitchInt", "Conditional", "Functions", "VisualShaderNodeSwitch", TTR("Returns an associated integer scalar if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_INT }, VisualShaderNode::PORT_TYPE_SCALAR_INT)); @@ -4343,7 +4501,7 @@ VisualShaderEditor::VisualShaderEditor() { const String input_param_shader_modes = TTR("'%s' input parameter for all shader modes."); - // SPATIAL-FOR-ALL + // NODE3D-FOR-ALL add_options.push_back(AddOption("Camera", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "camera"), { "camera" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("InvCamera", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_camera"), { "inv_camera" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL)); @@ -4352,18 +4510,18 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("OutputIsSRGB", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "output_is_srgb"), { "output_is_srgb" }, VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Projection", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "projection"), { "projection" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("UV", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("UV2", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv2"), { "uv2" }, VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ViewportSize", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "viewport_size"), { "viewport_size" }, VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("UV", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("UV2", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv2"), { "uv2" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ViewportSize", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "viewport_size"), { "viewport_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("World", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "world"), { "world" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL)); // CANVASITEM-FOR-ALL add_options.push_back(AddOption("Alpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("TexturePixelSize", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "texture_pixel_size"), { "texture_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("TexturePixelSize", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "texture_pixel_size"), { "texture_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("UV", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("UV", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_CANVAS_ITEM)); // PARTICLES-FOR-ALL @@ -4419,9 +4577,9 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("DepthTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "depth_texture"), { "depth_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("FrontFacing", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing"), { "front_facing" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), { "screen_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("View", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); @@ -4446,21 +4604,21 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("InstanceCustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom_alpha"), { "instance_custom_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Screen", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "screen"), { "screen" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("World", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "world"), { "world" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("AtLightPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("NormalTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "normal_texture"), { "normal_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ScreenPixelSize", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size"), { "screen_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ScreenPixelSize", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size"), { "screen_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), { "screen_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("SpecularShininess", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("SpecularShininessAlpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess_alpha"), { "specular_shininess_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("SpecularShininessTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "specular_shininess_texture"), { "specular_shininess_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Texture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture"), { "texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); @@ -4470,8 +4628,8 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("LightPosition", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_position"), { "light_position" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("LightVertex", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "light_vertex"), { "light_vertex" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Normal", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "normal"), { "normal" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("PointCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ScreenUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("PointCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ScreenUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Shadow", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow"), { "shadow" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ShadowAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_alpha"), { "shadow_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("SpecularShininess", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); @@ -4506,8 +4664,8 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("QuarterResColor", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_color"), { "quarter_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("QuarterResAlpha", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_alpha"), { "quarter_res_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("Radiance", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "radiance"), { "radiance" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_SKY, Shader::MODE_SKY)); - add_options.push_back(AddOption("ScreenUV", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "screen_uv"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_SKY, Shader::MODE_SKY)); - add_options.push_back(AddOption("SkyCoords", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "sky_coords"), { "sky_coords" }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_SKY, Shader::MODE_SKY)); + add_options.push_back(AddOption("ScreenUV", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "screen_uv"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); + add_options.push_back(AddOption("SkyCoords", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "sky_coords"), { "sky_coords" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("Time", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "time"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY)); // FOG INPUTS @@ -4634,7 +4792,7 @@ VisualShaderEditor::VisualShaderEditor() { // TEXTURES - add_options.push_back(AddOption("UVFunc", "Textures", "Common", "VisualShaderNodeUVFunc", TTR("Function to be applied on texture coordinates."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("UVFunc", "Textures", "Common", "VisualShaderNodeUVFunc", TTR("Function to be applied on texture coordinates."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D)); cubemap_node_option_idx = add_options.size(); add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."))); @@ -4648,8 +4806,8 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Texture2DArray", "Textures", "Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."))); texture3d_node_option_idx = add_options.size(); add_options.push_back(AddOption("Texture3D", "Textures", "Functions", "VisualShaderNodeTexture3D", TTR("Perform the 3D texture lookup."))); - add_options.push_back(AddOption("UVPanning", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply panning function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_PANNING }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("UVScaling", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply scaling function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_SCALING }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("UVPanning", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply panning function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_PANNING }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("UVScaling", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply scaling function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_SCALING }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubemapUniform", TTR("Cubic texture uniform lookup."))); add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."))); @@ -4685,81 +4843,142 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("VectorFunc", "Vector", "Common", "VisualShaderNodeVectorFunc", TTR("Vector function."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("VectorOp", "Vector", "Common", "VisualShaderNodeVectorOp", TTR("Vector operator."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); - - add_options.push_back(AddOption("VectorCompose", "Vector", "Composition", "VisualShaderNodeVectorCompose", TTR("Composes vector from three scalars."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("VectorDecompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes vector to three scalars."))); - - add_options.push_back(AddOption("Abs", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ABS }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("ACos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOS }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("ACosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOSH }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("ASin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASIN }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("ASinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASINH }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("ATan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATAN }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("ATan2", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeVectorOp::OP_ATAN2 }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("ATanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATANH }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Ceil", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_CEIL }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Clamp", "Vector", "Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_VECTOR }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Cos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COS }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("CosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COSH }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Cross", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Calculates the cross product of two vectors."), { VisualShaderNodeVectorOp::OP_CROSS }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Degrees", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeVectorFunc::FUNC_DEGREES }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("DFdX", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); - add_options.push_back(AddOption("DFdY", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); - add_options.push_back(AddOption("Distance", "Vector", "Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("VectorCompose", "Vector", "Common", "VisualShaderNodeVectorCompose", TTR("Composes vector from three scalars."))); + add_options.push_back(AddOption("VectorDecompose", "Vector", "Common", "VisualShaderNodeVectorDecompose", TTR("Decomposes vector to three scalars."))); + + add_options.push_back(AddOption("Vector2Compose", "Vector", "Composition", "VisualShaderNodeVectorCompose", TTR("Composes 2D vector from three scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Vector2Decompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 2D vector to three scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_2D })); + add_options.push_back(AddOption("Vector3Compose", "Vector", "Composition", "VisualShaderNodeVectorCompose", TTR("Composes 3D vector from three scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Vector3Decompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 3D vector to three scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_3D })); + + add_options.push_back(AddOption("Abs", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Abs", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ACos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("ACos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ACosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("ACosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ASin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("ASin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ASinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("ASinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ATan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("ATan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ATan2", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("ATan2", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ATanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("ATanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Ceil", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_CEIL }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Ceil", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_CEIL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Clamp", "Vector", "Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Clamp", "Vector", "Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Cos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Cos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("CosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("CosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Cross", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Calculates the cross product of two vectors."), { VisualShaderNodeVectorOp::OP_CROSS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Degrees", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Degrees", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("DFdX", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); + add_options.push_back(AddOption("DFdX", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); + add_options.push_back(AddOption("DFdY", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); + add_options.push_back(AddOption("DFdY", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); + add_options.push_back(AddOption("Distance2D", "Vector", "Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), { VisualShaderNodeVectorDistance::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Distance3D", "Vector", "Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), { VisualShaderNodeVectorDistance::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("Dot", "Vector", "Functions", "VisualShaderNodeDotProduct", TTR("Calculates the dot product of two vectors."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); - add_options.push_back(AddOption("Exp", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Exp2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP2 }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("FaceForward", "Vector", "Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Floor", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_FLOOR }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Fract", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeVectorFunc::FUNC_FRAC }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("InverseSqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Length", "Vector", "Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); - add_options.push_back(AddOption("Log", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Log2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG2 }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Max", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), { VisualShaderNodeVectorOp::OP_MAX }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), { VisualShaderNodeVectorOp::OP_MIN }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors."), { VisualShaderNodeMix::OP_TYPE_VECTOR }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("MixS", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors using scalar."), { VisualShaderNodeMix::OP_TYPE_VECTOR_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("MultiplyAdd", "Vector", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), { VisualShaderNodeMultiplyAdd::OP_TYPE_VECTOR }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_NEGATE }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), { VisualShaderNodeVectorFunc::FUNC_NORMALIZE }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("OneMinus", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), { VisualShaderNodeVectorFunc::FUNC_ONEMINUS }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Pow", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeVectorOp::OP_POW }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Radians", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeVectorFunc::FUNC_RADIANS }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Exp", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Exp", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Exp2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Exp2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("FaceForward", "Vector", "Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), { VisualShaderNodeFaceForward::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("FaceForward", "Vector", "Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), { VisualShaderNodeFaceForward::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Floor", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Floor", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Fract", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeVectorFunc::FUNC_FRAC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Fract", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeVectorFunc::FUNC_FRAC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Fresnel", "Vector", "Functions", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("InverseSqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("InverseSqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Length", "Vector", "Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), { VisualShaderNodeVectorLen::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Length", "Vector", "Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), { VisualShaderNodeVectorLen::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Log", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Log", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Log2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Log2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Max", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), { VisualShaderNodeVectorOp::OP_MAX, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Max", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), { VisualShaderNodeVectorOp::OP_MAX, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), { VisualShaderNodeVectorOp::OP_MIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), { VisualShaderNodeVectorOp::OP_MIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors."), { VisualShaderNodeMix::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors."), { VisualShaderNodeMix::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("MixS", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors using scalar."), { VisualShaderNodeMix::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("MixS", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors using scalar."), { VisualShaderNodeMix::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("MultiplyAdd", "Vector", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), { VisualShaderNodeMultiplyAdd::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("MultiplyAdd", "Vector", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), { VisualShaderNodeMultiplyAdd::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), { VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), { VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("OneMinus", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), { VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("OneMinus", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), { VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Pow", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeVectorOp::OP_POW, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Pow", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeVectorOp::OP_POW, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Radians", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Radians", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("RoundEven", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Saturate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeVectorFunc::FUNC_SATURATE }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Sign", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIGN }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Sin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIN }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("SinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SINH }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Sqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SQRT }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("SmoothStep", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("SmoothStepS", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Step", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( vector(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("StepS", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Sum", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); - add_options.push_back(AddOption("Tan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TAN }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("TanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TANH }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Trunc", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TRUNC }, VisualShaderNode::PORT_TYPE_VECTOR)); - - add_options.push_back(AddOption("Add", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Adds vector to vector."), { VisualShaderNodeVectorOp::OP_ADD }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Divide", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Divides vector by vector."), { VisualShaderNodeVectorOp::OP_DIV }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Multiply", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Multiplies vector by vector."), { VisualShaderNodeVectorOp::OP_MUL }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Remainder", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two vectors."), { VisualShaderNodeVectorOp::OP_MOD }, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("Subtract", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Subtracts vector from vector."), { VisualShaderNodeVectorOp::OP_SUB }, VisualShaderNode::PORT_TYPE_VECTOR)); - - add_options.push_back(AddOption("VectorConstant", "Vector", "Variables", "VisualShaderNodeVec3Constant", TTR("Vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("VectorUniform", "Vector", "Variables", "VisualShaderNodeVec3Uniform", TTR("Vector uniform."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("RoundEven", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("RoundEven", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Saturate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Saturate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Sign", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Sign", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Sin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Sin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("SinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("SinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Sqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Sqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("SmoothStep", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("SmoothStep", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("SmoothStepS", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("SmoothStepS", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Step", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( vector(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Step", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( vector(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("StepS", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("StepS", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Sum", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); + add_options.push_back(AddOption("Sum", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); + add_options.push_back(AddOption("Tan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Tan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("TanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("TanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Trunc", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Trunc", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + + add_options.push_back(AddOption("Add", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Adds 2D vector to 2D vector."), { VisualShaderNodeVectorOp::OP_ADD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Add", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Adds 3D vector to 3D vector."), { VisualShaderNodeVectorOp::OP_ADD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Divide", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Divides 2D vector by 2D vector."), { VisualShaderNodeVectorOp::OP_DIV, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Divide", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Divides 3D vector by 3D vector."), { VisualShaderNodeVectorOp::OP_DIV, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Multiply", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Multiplies 2D vector by 2D vector."), { VisualShaderNodeVectorOp::OP_MUL, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Multiply", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Multiplies 3D vector by 3D vector."), { VisualShaderNodeVectorOp::OP_MUL, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Remainder", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two 2D vectors."), { VisualShaderNodeVectorOp::OP_MOD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Remainder", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two 3D vectors."), { VisualShaderNodeVectorOp::OP_MOD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Subtract", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Subtracts 2D vector from 2D vector."), { VisualShaderNodeVectorOp::OP_SUB, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Subtract", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Subtracts 3D vector from 3D vector."), { VisualShaderNodeVectorOp::OP_SUB, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR)); + + add_options.push_back(AddOption("Vector2Constant", "Vector", "Variables", "VisualShaderNodeVec2Constant", TTR("2D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Vector3Constant", "Vector", "Variables", "VisualShaderNodeVec3Constant", TTR("3D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Vector2Uniform", "Vector", "Variables", "VisualShaderNodeVec2Uniform", TTR("2D vector uniform."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("Vector3Uniform", "Vector", "Variables", "VisualShaderNodeVec3Uniform", TTR("3D vector uniform."), {}, VisualShaderNode::PORT_TYPE_VECTOR)); // SPECIAL add_options.push_back(AddOption("Comment", "Special", "", "VisualShaderNodeComment", TTR("A rectangular area with a description string for better graph organization."))); - add_options.push_back(AddOption("DerivativeFunc", "Special", "", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) Derivative function."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true)); add_options.push_back(AddOption("Expression", "Special", "", "VisualShaderNodeExpression", TTR("Custom Godot Shader Language expression, with custom amount of input and output ports. This is a direct injection of code into the vertex/fragment/light function, do not use it to write the function declarations inside."))); - add_options.push_back(AddOption("Fresnel", "Special", "", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("GlobalExpression", "Special", "", "VisualShaderNodeGlobalExpression", TTR("Custom Godot Shader Language expression, which is placed on top of the resulted shader. You can place various function definitions inside and call it later in the Expressions. You can also declare varyings, uniforms and constants."))); add_options.push_back(AddOption("UniformRef", "Special", "", "VisualShaderNodeUniformRef", TTR("A reference to an existing uniform."))); @@ -4847,9 +5066,10 @@ public: void setup(const Ref<VisualShaderNodeInput> &p_input) { input = p_input; - Ref<Texture2D> type_icon[6] = { + Ref<Texture2D> type_icon[7] = { EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("int"), SNAME("EditorIcons")), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")), @@ -4895,10 +5115,11 @@ public: void setup(const Ref<VisualShaderNodeUniformRef> &p_uniform_ref) { uniform_ref = p_uniform_ref; - Ref<Texture2D> type_icon[7] = { + Ref<Texture2D> type_icon[8] = { EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("int"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")), diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 22b866c1cb..c0ff1d72ee 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "editor/editor_export.h" +#include "editor/editor_log.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" @@ -47,7 +48,8 @@ void ProjectSettingsEditor::popup_project_settings() { } _add_feature_overrides(); - inspector->update_category_list(); + general_settings_inspector->update_category_list(); + set_process_unhandled_input(true); localization_editor->update_translations(); autoload_settings->update_autoload(); @@ -74,7 +76,7 @@ void ProjectSettingsEditor::_setting_edited(const String &p_name) { void ProjectSettingsEditor::_advanced_toggled(bool p_button_pressed) { EditorSettings::get_singleton()->set_project_metadata("project_settings", "advanced_mode", p_button_pressed); - inspector->set_restrict_to_basic_settings(!p_button_pressed); + general_settings_inspector->set_restrict_to_basic_settings(!p_button_pressed); } void ProjectSettingsEditor::_setting_selected(const String &p_path) { @@ -82,7 +84,7 @@ void ProjectSettingsEditor::_setting_selected(const String &p_path) { return; } - property_box->set_text(inspector->get_current_section() + "/" + p_path); + property_box->set_text(general_settings_inspector->get_current_section() + "/" + p_path); _update_property_box(); // set_text doesn't trigger text_changed } @@ -99,13 +101,13 @@ void ProjectSettingsEditor::_add_setting() { undo_redo->add_do_property(ps, setting, value); undo_redo->add_undo_property(ps, setting, ps->has_setting(setting) ? ps->get(setting) : Variant()); - undo_redo->add_do_method(inspector, "update_category_list"); - undo_redo->add_undo_method(inspector, "update_category_list"); + undo_redo->add_do_method(general_settings_inspector, "update_category_list"); + undo_redo->add_undo_method(general_settings_inspector, "update_category_list"); undo_redo->add_do_method(this, "queue_save"); undo_redo->add_undo_method(this, "queue_save"); undo_redo->commit_action(); - inspector->set_current_section(setting.get_slice("/", 1)); + general_settings_inspector->set_current_section(setting.get_slice("/", 1)); add_button->release_focus(); } @@ -120,8 +122,8 @@ void ProjectSettingsEditor::_delete_setting() { undo_redo->add_undo_method(ps, "set", setting, value); undo_redo->add_undo_method(ps, "set_order", setting, order); - undo_redo->add_do_method(inspector, "update_category_list"); - undo_redo->add_undo_method(inspector, "update_category_list"); + undo_redo->add_do_method(general_settings_inspector, "update_category_list"); + undo_redo->add_undo_method(general_settings_inspector, "update_category_list"); undo_redo->add_do_method(this, "queue_save"); undo_redo->add_undo_method(this, "queue_save"); @@ -200,6 +202,44 @@ void ProjectSettingsEditor::_select_type(Variant::Type p_type) { type_box->select(type_box->get_item_index(p_type)); } +void ProjectSettingsEditor::unhandled_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + + const Ref<InputEventKey> k = p_event; + + if (k.is_valid() && k->is_pressed()) { + bool handled = false; + + if (ED_IS_SHORTCUT("ui_undo", p_event)) { + String action = undo_redo->get_current_action_name(); + if (!action.is_empty()) { + EditorNode::get_log()->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR); + } + undo_redo->undo(); + handled = true; + } + + if (ED_IS_SHORTCUT("ui_redo", p_event)) { + undo_redo->redo(); + String action = undo_redo->get_current_action_name(); + if (!action.is_empty()) { + EditorNode::get_log()->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR); + } + handled = true; + } + + if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::F)) { + search_box->grab_focus(); + search_box->select_all(); + handled = true; + } + + if (handled) { + set_input_as_handled(); + } + } +} + String ProjectSettingsEditor::_get_setting_name() const { String name = property_box->get_text().strip_edges(); if (!name.contains("/")) { @@ -463,7 +503,7 @@ void ProjectSettingsEditor::_update_action_map_editor() { actions.push_back(action_info); } - action_map->update_action_list(actions); + action_map_editor->update_action_list(actions); } void ProjectSettingsEditor::_update_theme() { @@ -472,6 +512,16 @@ void ProjectSettingsEditor::_update_theme() { restart_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); restart_icon->set_texture(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); restart_label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); + + type_box->clear(); + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + // There's no point in adding Nil types, and Object types + // can't be serialized correctly in the project settings. + if (i != Variant::NIL && i != Variant::OBJECT) { + String type = Variant::get_type_name(Variant::Type(i)); + type_box->add_icon_item(get_theme_icon(type, SNAME("EditorIcons")), type, i); + } + } } void ProjectSettingsEditor::_notification(int p_what) { @@ -482,13 +532,13 @@ void ProjectSettingsEditor::_notification(int p_what) { } } break; case NOTIFICATION_ENTER_TREE: { - inspector->edit(ps); + general_settings_inspector->edit(ps); _update_action_map_editor(); _update_theme(); } break; - case NOTIFICATION_THEME_CHANGED: + case NOTIFICATION_THEME_CHANGED: { _update_theme(); - break; + } break; } } @@ -549,14 +599,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { type_box->set_custom_minimum_size(Size2(120, 0) * EDSCALE); header->add_child(type_box); - for (int i = 0; i < Variant::VARIANT_MAX; i++) { - // There's no point in adding Nil types, and Object types - // can't be serialized correctly in the project settings. - if (i != Variant::NIL && i != Variant::OBJECT) { - type_box->add_item(Variant::get_type_name(Variant::Type(i)), i); - } - } - add_button = memnew(Button); add_button->set_text(TTR("Add")); add_button->set_disabled(true); @@ -569,14 +611,14 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { del_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_delete_setting)); header->add_child(del_button); - inspector = memnew(SectionedInspector); - inspector->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); - inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); - inspector->register_search_box(search_box); - inspector->get_inspector()->connect("property_selected", callable_mp(this, &ProjectSettingsEditor::_setting_selected)); - inspector->get_inspector()->connect("property_edited", callable_mp(this, &ProjectSettingsEditor::_setting_edited)); - inspector->get_inspector()->connect("restart_requested", callable_mp(this, &ProjectSettingsEditor::_editor_restart_request)); - general_editor->add_child(inspector); + general_settings_inspector = memnew(SectionedInspector); + general_settings_inspector->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); + general_settings_inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); + general_settings_inspector->register_search_box(search_box); + general_settings_inspector->get_inspector()->connect("property_selected", callable_mp(this, &ProjectSettingsEditor::_setting_selected)); + general_settings_inspector->get_inspector()->connect("property_edited", callable_mp(this, &ProjectSettingsEditor::_setting_edited)); + general_settings_inspector->get_inspector()->connect("restart_requested", callable_mp(this, &ProjectSettingsEditor::_editor_restart_request)); + general_editor->add_child(general_settings_inspector); restart_container = memnew(PanelContainer); general_editor->add_child(restart_container); @@ -604,14 +646,14 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { restart_close_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_editor_restart_close)); restart_hb->add_child(restart_close_button); - action_map = memnew(ActionMapEditor); - action_map->set_name(TTR("Input Map")); - action_map->connect("action_added", callable_mp(this, &ProjectSettingsEditor::_action_added)); - action_map->connect("action_edited", callable_mp(this, &ProjectSettingsEditor::_action_edited)); - action_map->connect("action_removed", callable_mp(this, &ProjectSettingsEditor::_action_removed)); - action_map->connect("action_renamed", callable_mp(this, &ProjectSettingsEditor::_action_renamed)); - action_map->connect("action_reordered", callable_mp(this, &ProjectSettingsEditor::_action_reordered)); - tab_container->add_child(action_map); + action_map_editor = memnew(ActionMapEditor); + action_map_editor->set_name(TTR("Input Map")); + action_map_editor->connect("action_added", callable_mp(this, &ProjectSettingsEditor::_action_added)); + action_map_editor->connect("action_edited", callable_mp(this, &ProjectSettingsEditor::_action_edited)); + action_map_editor->connect("action_removed", callable_mp(this, &ProjectSettingsEditor::_action_removed)); + action_map_editor->connect("action_renamed", callable_mp(this, &ProjectSettingsEditor::_action_renamed)); + action_map_editor->connect("action_reordered", callable_mp(this, &ProjectSettingsEditor::_action_reordered)); + tab_container->add_child(action_map_editor); localization_editor = memnew(LocalizationEditor); localization_editor->set_name(TTR("Localization")); @@ -647,7 +689,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { advanced->set_pressed(true); } - inspector->set_restrict_to_basic_settings(!use_advanced); + general_settings_inspector->set_restrict_to_basic_settings(!use_advanced); import_defaults_editor = memnew(ImportDefaultsEditor); import_defaults_editor->set_name(TTR("Import Defaults")); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index a8eed0093f..d48c2b76ca 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -50,8 +50,8 @@ class ProjectSettingsEditor : public AcceptDialog { Timer *timer; TabContainer *tab_container; - SectionedInspector *inspector; - ActionMapEditor *action_map; + SectionedInspector *general_settings_inspector; + ActionMapEditor *action_map_editor; LocalizationEditor *localization_editor; EditorAutoloadSettings *autoload_settings; ShaderGlobalsEditor *shaders_global_variables_editor; @@ -81,6 +81,8 @@ class ProjectSettingsEditor : public AcceptDialog { void _feature_selected(int p_index); void _select_type(Variant::Type p_type); + virtual void unhandled_input(const Ref<InputEvent> &p_event) override; + String _get_setting_name() const; void _setting_edited(const String &p_name); void _setting_selected(const String &p_path); diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 92dcd53830..c6a4c0d86a 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -337,7 +337,7 @@ void RenameDialog::_bind_methods() { } void RenameDialog::_update_substitute() { - LineEdit *focus_owner_line_edit = Object::cast_to<LineEdit>(scene_tree_editor->get_focus_owner()); + LineEdit *focus_owner_line_edit = Object::cast_to<LineEdit>(scene_tree_editor->get_viewport()->gui_get_focus_owner()); bool is_main_field = _is_main_field(focus_owner_line_edit); but_insert_name->set_disabled(!is_main_field); @@ -632,7 +632,7 @@ bool RenameDialog::_is_main_field(LineEdit *line_edit) { } void RenameDialog::_insert_text(String text) { - LineEdit *focus_owner = Object::cast_to<LineEdit>(scene_tree_editor->get_focus_owner()); + LineEdit *focus_owner = Object::cast_to<LineEdit>(scene_tree_editor->get_viewport()->gui_get_focus_owner()); if (_is_main_field(focus_owner)) { focus_owner->selection_delete(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 30ea1bcbb9..9b18d3a491 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -78,7 +78,7 @@ void SceneTreeDock::input(const Ref<InputEvent> &p_event) { void SceneTreeDock::unhandled_key_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); - if (get_focus_owner() && get_focus_owner()->is_text_field()) { + if (get_viewport()->gui_get_focus_owner() && get_viewport()->gui_get_focus_owner()->is_text_field()) { return; } diff --git a/main/main.cpp b/main/main.cpp index 246802ad38..f8088cba1c 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1310,12 +1310,14 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/viewport_width", PropertyInfo(Variant::INT, "display/window/size/viewport_width", PROPERTY_HINT_RANGE, - "0,7680,or_greater")); // 8K resolution + "0,7680,1,or_greater")); // 8K resolution + GLOBAL_DEF_BASIC("display/window/size/viewport_height", 600); ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/viewport_height", PropertyInfo(Variant::INT, "display/window/size/viewport_height", PROPERTY_HINT_RANGE, - "0,4320,or_greater")); // 8K resolution + "0,4320,1,or_greater")); // 8K resolution + GLOBAL_DEF_BASIC("display/window/size/resizable", true); GLOBAL_DEF_BASIC("display/window/size/borderless", false); GLOBAL_DEF_BASIC("display/window/size/fullscreen", false); @@ -1325,13 +1327,13 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, - "0,7680,or_greater")); // 8K resolution + "0,7680,1,or_greater")); // 8K resolution GLOBAL_DEF("display/window/size/window_height_override", 0); ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/window_height_override", PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, - "0,4320,or_greater")); // 8K resolution + "0,4320,1,or_greater")); // 8K resolution if (use_custom_res) { if (!force_res) { diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index fd69725a21..5ba45c0c13 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -308,6 +308,7 @@ CODE_SIGN_ENTITLEMENTS = "$binary/$binary.entitlements"; CODE_SIGN_IDENTITY = "$code_sign_identity_debug"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug"; + CODE_SIGN_STYLE = "$code_sign_style_debug"; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; DEVELOPMENT_TEAM = $team_id; INFOPLIST_FILE = "$binary/$binary-Info.plist"; @@ -338,6 +339,7 @@ CODE_SIGN_ENTITLEMENTS = "$binary/$binary.entitlements"; CODE_SIGN_IDENTITY = "$code_sign_identity_release"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release"; + CODE_SIGN_STYLE = "$code_sign_style_release"; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; DEVELOPMENT_TEAM = $team_id; INFOPLIST_FILE = "$binary/$binary-Info.plist"; diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h index 6377f8915d..dffcadbcdc 100644 --- a/modules/bullet/shape_bullet.h +++ b/modules/bullet/shape_bullet.h @@ -105,7 +105,7 @@ private: }; class SphereShapeBullet : public ShapeBullet { - real_t radius; + real_t radius = 0.0; public: SphereShapeBullet(); @@ -137,8 +137,8 @@ private: }; class CapsuleShapeBullet : public ShapeBullet { - real_t height; - real_t radius; + real_t height = 0.0; + real_t radius = 0.0; public: CapsuleShapeBullet(); @@ -155,8 +155,8 @@ private: }; class CylinderShapeBullet : public ShapeBullet { - real_t height; - real_t radius; + real_t height = 0.0; + real_t radius = 0.0; public: CylinderShapeBullet(); diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 4b36bca02a..fbddedbe55 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1451,8 +1451,8 @@ Ref<Material> CSGCylinder3D::get_material() const { CSGCylinder3D::CSGCylinder3D() { // defaults - radius = 1.0; - height = 1.0; + radius = 0.5; + height = 2.0; sides = 8; cone = false; smooth_faces = true; @@ -1671,8 +1671,8 @@ Ref<Material> CSGTorus3D::get_material() const { CSGTorus3D::CSGTorus3D() { // defaults - inner_radius = 2.0; - outer_radius = 3.0; + inner_radius = 0.5; + outer_radius = 1.0; sides = 8; ring_sides = 6; smooth_faces = true; diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h index eed995a40e..6da9893368 100644 --- a/modules/csg/csg_shape.h +++ b/modules/csg/csg_shape.h @@ -239,7 +239,7 @@ class CSGBox3D : public CSGPrimitive3D { virtual CSGBrush *_build_brush() override; Ref<Material> material; - Vector3 size = Vector3(2, 2, 2); + Vector3 size = Vector3(1, 1, 1); protected: static void _bind_methods(); diff --git a/modules/csg/doc_classes/CSGBox3D.xml b/modules/csg/doc_classes/CSGBox3D.xml index d64e58ae4d..4b479ed42e 100644 --- a/modules/csg/doc_classes/CSGBox3D.xml +++ b/modules/csg/doc_classes/CSGBox3D.xml @@ -12,7 +12,7 @@ <member name="material" type="Material" setter="set_material" getter="get_material"> The material used to render the box. </member> - <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(1, 1, 1)"> The box's width, height and depth. </member> </members> diff --git a/modules/csg/doc_classes/CSGCylinder3D.xml b/modules/csg/doc_classes/CSGCylinder3D.xml index 40e989bfb3..1fe2025bab 100644 --- a/modules/csg/doc_classes/CSGCylinder3D.xml +++ b/modules/csg/doc_classes/CSGCylinder3D.xml @@ -12,13 +12,13 @@ <member name="cone" type="bool" setter="set_cone" getter="is_cone" default="false"> If [code]true[/code] a cone is created, the [member radius] will only apply to one side. </member> - <member name="height" type="float" setter="set_height" getter="get_height" default="1.0"> + <member name="height" type="float" setter="set_height" getter="get_height" default="2.0"> The height of the cylinder. </member> <member name="material" type="Material" setter="set_material" getter="get_material"> The material used to render the cylinder. </member> - <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> + <member name="radius" type="float" setter="set_radius" getter="get_radius" default="0.5"> The radius of the cylinder. </member> <member name="sides" type="int" setter="set_sides" getter="get_sides" default="8"> diff --git a/modules/csg/doc_classes/CSGTorus3D.xml b/modules/csg/doc_classes/CSGTorus3D.xml index 91ee63a4c9..2c0eef8f09 100644 --- a/modules/csg/doc_classes/CSGTorus3D.xml +++ b/modules/csg/doc_classes/CSGTorus3D.xml @@ -9,13 +9,13 @@ <tutorials> </tutorials> <members> - <member name="inner_radius" type="float" setter="set_inner_radius" getter="get_inner_radius" default="2.0"> + <member name="inner_radius" type="float" setter="set_inner_radius" getter="get_inner_radius" default="0.5"> The inner radius of the torus. </member> <member name="material" type="Material" setter="set_material" getter="get_material"> The material used to render the torus. </member> - <member name="outer_radius" type="float" setter="set_outer_radius" getter="get_outer_radius" default="3.0"> + <member name="outer_radius" type="float" setter="set_outer_radius" getter="get_outer_radius" default="1.0"> The outer radius of the torus. </member> <member name="ring_sides" type="int" setter="set_ring_sides" getter="get_ring_sides" default="6"> diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 2be588cac4..2de923c125 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -103,8 +103,6 @@ private: bool valid = false; bool reload_invalidated = false; - bool builtin; - GDMonoClass *base = nullptr; GDMonoClass *native = nullptr; GDMonoClass *script_class = nullptr; diff --git a/modules/ogg/ogg_packet_sequence.h b/modules/ogg/ogg_packet_sequence.h index 7e56b14a24..73e3cb4fff 100644 --- a/modules/ogg/ogg_packet_sequence.h +++ b/modules/ogg/ogg_packet_sequence.h @@ -104,7 +104,7 @@ class OGGPacketSequencePlayback : public RefCounted { mutable ogg_packet *packet; - uint64_t data_version; + uint64_t data_version = 0; mutable int64_t packetno = 0; diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index d6a96282f3..6a06619840 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -62,7 +62,6 @@ if env["builtin_harfbuzz"]: #'src/hb-gobject-structs.cc', "src/hb-icu.cc", "src/hb-map.cc", - "src/hb-ms-feature-ranges.cc", "src/hb-number.cc", "src/hb-ot-cff1-table.cc", "src/hb-ot-cff2-table.cc", diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h index f1b01aa6dc..b01732b2fd 100644 --- a/modules/visual_script/editor/visual_script_editor.h +++ b/modules/visual_script/editor/visual_script_editor.h @@ -173,10 +173,10 @@ class VisualScriptEditor : public ScriptEditorBase { String member_name; PortAction port_action; - int port_action_node; - int port_action_output; + int port_action_node = 0; + int port_action_output = 0; Vector2 port_action_pos; - int port_action_new_node; + int port_action_new_node = 0; bool saved_pos_dirty = false; @@ -196,7 +196,7 @@ class VisualScriptEditor : public ScriptEditorBase { int _create_new_node_from_name(const String &p_text, const Vector2 &p_point); void _selected_new_virtual_method(const String &p_text, const String &p_category, const bool p_connecting); - int error_line; + int error_line = -1; void _node_selected(Node *p_node); void _center_on_node(int p_id); @@ -267,12 +267,12 @@ class VisualScriptEditor : public ScriptEditorBase { bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); - int editing_id; - int editing_input; + int editing_id = 0; + int editing_input = 0; - bool can_swap; - int data_disconnect_node; - int data_disconnect_port; + bool can_swap = false; + int data_disconnect_node = 0; + int data_disconnect_port = 0; void _default_value_changed(); void _default_value_edited(Node *p_button, int p_id, int p_input_port); diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp index 1059d126bc..4072dcebe5 100644 --- a/modules/visual_script/editor/visual_script_property_selector.cpp +++ b/modules/visual_script/editor/visual_script_property_selector.cpp @@ -379,8 +379,6 @@ void VisualScriptPropertySelector::_bind_methods() { } VisualScriptPropertySelector::VisualScriptPropertySelector() { - virtuals_only = false; - vbox = memnew(VBoxContainer); add_child(vbox); diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h index 3970c4473e..6b5112f1af 100644 --- a/modules/visual_script/editor/visual_script_property_selector.h +++ b/modules/visual_script/editor/visual_script_property_selector.h @@ -96,16 +96,16 @@ class VisualScriptPropertySelector : public ConfirmationDialog { EditorHelpBit *help_bit; - bool properties; - bool visual_script_generic; - bool connecting; + bool properties = false; + bool visual_script_generic = false; + bool connecting = false; String selected; Variant::Type type; String base_type; String base_script; ObjectID script; Object *instance; - bool virtuals_only; + bool virtuals_only = false; VBoxContainer *vbox; protected: diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp index ea17f1ac61..fe00b1a3cd 100644 --- a/platform/iphone/export/export_plugin.cpp +++ b/platform/iphone/export/export_plugin.cpp @@ -83,7 +83,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "iPhone Developer")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_debug", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 1)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Distribution"), "")); @@ -178,6 +178,10 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ "scaleAspectFill", "scaleToFill" }; + String dbg_sign_id = p_preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : p_preset->get("application/code_sign_identity_debug"); + String rel_sign_id = p_preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : p_preset->get("application/code_sign_identity_release"); + bool dbg_manual = !p_preset->get("application/provisioning_profile_uuid_debug").operator String().is_empty() || (dbg_sign_id != "iPhone Developer"); + bool rel_manual = !p_preset->get("application/provisioning_profile_uuid_release").operator String().is_empty() || (rel_sign_id != "iPhone Distribution"); String str; String strnew; str.parse_utf8((const char *)pfile.ptr(), pfile.size()); @@ -218,13 +222,25 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n"; } else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) { strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n"; + } else if (lines[i].find("$code_sign_style_debug") != -1) { + if (dbg_manual) { + strnew += lines[i].replace("$code_sign_style_debug", "Manual") + "\n"; + } else { + strnew += lines[i].replace("$code_sign_style_debug", "Automatic") + "\n"; + } + } else if (lines[i].find("$code_sign_style_release") != -1) { + if (rel_manual) { + strnew += lines[i].replace("$code_sign_style_release", "Manual") + "\n"; + } else { + strnew += lines[i].replace("$code_sign_style_release", "Automatic") + "\n"; + } } else if (lines[i].find("$provisioning_profile_uuid") != -1) { String uuid = p_debug ? p_preset->get("application/provisioning_profile_uuid_debug") : p_preset->get("application/provisioning_profile_uuid_release"); strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n"; } else if (lines[i].find("$code_sign_identity_debug") != -1) { - strnew += lines[i].replace("$code_sign_identity_debug", p_preset->get("application/code_sign_identity_debug")) + "\n"; + strnew += lines[i].replace("$code_sign_identity_debug", dbg_sign_id) + "\n"; } else if (lines[i].find("$code_sign_identity_release") != -1) { - strnew += lines[i].replace("$code_sign_identity_release", p_preset->get("application/code_sign_identity_release")) + "\n"; + strnew += lines[i].replace("$code_sign_identity_release", rel_sign_id) + "\n"; } else if (lines[i].find("$additional_plist_content") != -1) { strnew += lines[i].replace("$additional_plist_content", p_config.plist_content) + "\n"; } else if (lines[i].find("$godot_archs") != -1) { @@ -770,10 +786,18 @@ Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) { if (p_file.ends_with(".dylib")) { CodesignData *data = (CodesignData *)p_userdata; print_line(String("Signing ") + p_file); + + String sign_id; + if (data->debug) { + sign_id = data->preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : data->preset->get("application/code_sign_identity_debug"); + } else { + sign_id = data->preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : data->preset->get("application/code_sign_identity_release"); + } + List<String> codesign_args; codesign_args.push_back("-f"); codesign_args.push_back("-s"); - codesign_args.push_back(data->preset->get(data->debug ? "application/code_sign_identity_debug" : "application/code_sign_identity_release")); + codesign_args.push_back(sign_id); codesign_args.push_back(p_file); return OS::get_singleton()->execute("codesign", codesign_args); } @@ -1680,6 +1704,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p archive_args.push_back("-destination"); archive_args.push_back("generic/platform=iOS"); archive_args.push_back("archive"); + archive_args.push_back("-allowProvisioningUpdates"); archive_args.push_back("-archivePath"); archive_args.push_back(archive_path); String archive_str; diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp index 45aa68ce7c..c946302862 100644 --- a/platform/javascript/http_client_javascript.cpp +++ b/platform/javascript/http_client_javascript.cpp @@ -87,6 +87,11 @@ Error HTTPClientJavaScript::request(Method p_method, const String &p_url, const ERR_FAIL_COND_V(port < 0, ERR_UNCONFIGURED); ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); + Error err = verify_headers(p_headers); + if (err) { + return err; + } + String url = (use_tls ? "https://" : "http://") + host + ":" + itos(port) + p_url; Vector<CharString> keeper; Vector<const char *> c_strings; diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp index 4d1f72f5c9..f0b58efb63 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/osx/export/export_plugin.cpp @@ -777,6 +777,24 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources"); } + Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); + if (translations.size() > 0) { + { + String fname = tmp_app_path_name + "/Contents/Resources/en.lproj"; + tmp_app_dir->make_dir_recursive(fname); + FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + } + + for (const String &E : translations) { + Ref<Translation> tr = ResourceLoader::load(E); + if (tr.is_valid()) { + String fname = tmp_app_path_name + "/Contents/Resources/" + tr->get_locale() + ".lproj"; + tmp_app_dir->make_dir_recursive(fname); + FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + } + } + } + // Now process our template. bool found_binary = false; Vector<String> dylibs_found; diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 68762db3a9..d30d0afc5c 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -76,8 +76,8 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), "")); @@ -89,6 +89,7 @@ void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); if (rcedit_path.is_empty()) { + WARN_PRINT("The rcedit tool is not configured in the Editor Settings (Export > Windows > Rcedit). No custom icon or app information data will be embedded in the exported executable."); return; } @@ -327,3 +328,46 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p return OK; } + +bool EditorExportPlatformWindows::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { + String err = ""; + bool valid = EditorExportPlatformPC::can_export(p_preset, err, r_missing_templates); + + String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); + if (rcedit_path.is_empty()) { + err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > Rcedit) to change the icon or app information data.") + "\n"; + } + + String icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/icon")); + if (!icon_path.is_empty() && !FileAccess::exists(icon_path)) { + err += TTR("Invalid icon path:") + " " + icon_path + "\n"; + } + + // Only non-negative integers can exist in the version string. + + String file_version = p_preset->get("application/file_version"); + if (!file_version.is_empty()) { + PackedStringArray version_array = file_version.split(".", false); + if (version_array.size() != 4 || !version_array[0].is_valid_int() || + !version_array[1].is_valid_int() || !version_array[2].is_valid_int() || + !version_array[3].is_valid_int() || file_version.find("-") > -1) { + err += TTR("Invalid file version:") + " " + file_version + "\n"; + } + } + + String product_version = p_preset->get("application/product_version"); + if (!product_version.is_empty()) { + PackedStringArray version_array = product_version.split(".", false); + if (version_array.size() != 4 || !version_array[0].is_valid_int() || + !version_array[1].is_valid_int() || !version_array[2].is_valid_int() || + !version_array[3].is_valid_int() || product_version.find("-") > -1) { + err += TTR("Invalid product version:") + " " + product_version + "\n"; + } + } + + if (!err.is_empty()) { + r_error = err; + } + + return valid; +} diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 351333aa42..89e5b1b635 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -47,6 +47,7 @@ public: virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override; virtual void get_export_options(List<ExportOption> *r_options) override; virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; }; #endif diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index ec451b07cf..da2ef6c5ec 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -403,7 +403,7 @@ bool BaseButton::_is_focus_owner_in_shorcut_context() const { } Node *ctx_node = get_shortcut_context(); - Control *vp_focus = get_focus_owner(); + Control *vp_focus = get_viewport() ? get_viewport()->gui_get_focus_owner() : nullptr; // If the context is valid and the viewport focus is valid, check if the context is the focus or is a parent of it. return ctx_node && vp_focus && (ctx_node == vp_focus || ctx_node->is_ancestor_of(vp_focus)); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 7ebc5c27f8..fdae8e2f1f 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2196,8 +2196,7 @@ void Control::release_focus() { return; } - get_viewport()->_gui_remove_focus(); - update(); + get_viewport()->gui_release_focus(); } bool Control::is_top_level_control() const { @@ -2600,11 +2599,6 @@ Control::MouseFilter Control::get_mouse_filter() const { return data.mouse_filter; } -Control *Control::get_focus_owner() const { - ERR_FAIL_COND_V(!is_inside_tree(), nullptr); - return get_viewport()->_gui_get_focus_owner(); -} - void Control::warp_mouse(const Point2 &p_to_pos) { ERR_FAIL_COND(!is_inside_tree()); get_viewport()->warp_mouse(get_global_transform().xform(p_to_pos)); @@ -2894,7 +2888,6 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("release_focus"), &Control::release_focus); ClassDB::bind_method(D_METHOD("find_prev_valid_focus"), &Control::find_prev_valid_focus); ClassDB::bind_method(D_METHOD("find_next_valid_focus"), &Control::find_next_valid_focus); - ClassDB::bind_method(D_METHOD("get_focus_owner"), &Control::get_focus_owner); ClassDB::bind_method(D_METHOD("set_h_size_flags", "flags"), &Control::set_h_size_flags); ClassDB::bind_method(D_METHOD("get_h_size_flags"), &Control::get_h_size_flags); diff --git a/scene/gui/control.h b/scene/gui/control.h index bf79f790e7..962135280f 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -462,8 +462,6 @@ public: void set_focus_previous(const NodePath &p_prev); NodePath get_focus_previous() const; - Control *get_focus_owner() const; - void set_mouse_filter(MouseFilter p_filter); MouseFilter get_mouse_filter() const; diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index f7805136f9..a985a9d031 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -98,7 +98,13 @@ void MenuButton::pressed() { popup->set_position(gp); popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), size)); - popup->take_mouse_focus(); + // If not triggered by the mouse, start the popup with its first item selected. + if (popup->get_item_count() > 0 && + ((get_action_mode() == ActionMode::ACTION_MODE_BUTTON_PRESS && Input::get_singleton()->is_action_just_pressed("ui_accept")) || + (get_action_mode() == ActionMode::ACTION_MODE_BUTTON_RELEASE && Input::get_singleton()->is_action_just_released("ui_accept")))) { + popup->set_current_index(0); + } + popup->popup(); } diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index c80de04c01..9984ab240a 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -181,7 +181,14 @@ void OptionButton::pressed() { Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); popup->set_size(Size2(size.width, 0)); - popup->set_current_index(current); + + // If not triggered by the mouse, start the popup with the checked item selected. + if (popup->get_item_count() > 0 && + ((get_action_mode() == ActionMode::ACTION_MODE_BUTTON_PRESS && Input::get_singleton()->is_action_just_pressed("ui_accept")) || + (get_action_mode() == ActionMode::ACTION_MODE_BUTTON_RELEASE && Input::get_singleton()->is_action_just_released("ui_accept")))) { + popup->set_current_index(current > -1 ? current : 0); + } + popup->popup(); } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index fc853a3df4..812339dc19 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -192,7 +192,7 @@ void PopupMenu::_activate_submenu(int p_over) { Popup *submenu_popup = Object::cast_to<Popup>(n); ERR_FAIL_COND_MSG(!submenu_popup, "Item subnode is not a Popup: " + items[p_over].submenu + "."); if (submenu_popup->is_visible()) { - return; //already visible! + return; // Already visible. } Ref<StyleBox> style = get_theme_stylebox(SNAME("panel")); @@ -223,24 +223,33 @@ void PopupMenu::_activate_submenu(int p_over) { submenu_popup->set_close_on_parent_focus(false); submenu_popup->set_position(submenu_pos); submenu_popup->set_as_minsize(); // Shrink the popup size to its contents. - submenu_popup->popup(); - // Set autohide areas PopupMenu *submenu_pum = Object::cast_to<PopupMenu>(submenu_popup); - if (submenu_pum) { - submenu_pum->take_mouse_focus(); - // Make the position of the parent popup relative to submenu popup - this_rect.position = this_rect.position - submenu_pum->get_position(); - - // Autohide area above the submenu item - submenu_pum->clear_autohide_areas(); - submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2)); - - // If there is an area below the submenu item, add an autohide area there. - if (items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset <= control->get_size().height) { - int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + vsep / 2 + style->get_offset().height; - submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from)); - } + if (!submenu_pum) { + submenu_popup->popup(); + return; + } + + // If not triggered by the mouse, start the popup with its first item selected. + if (submenu_pum->get_item_count() > 0 && Input::get_singleton()->is_action_just_pressed("ui_accept")) { + submenu_pum->set_current_index(0); + } + + submenu_pum->popup(); + + // Set autohide areas. + + // Make the position of the parent popup relative to submenu popup. + this_rect.position = this_rect.position - submenu_pum->get_position(); + + // Autohide area above the submenu item. + submenu_pum->clear_autohide_areas(); + submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2)); + + // If there is an area below the submenu item, add an autohide area there. + if (items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset <= control->get_size().height) { + int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + vsep / 2 + style->get_offset().height; + submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from)); } } @@ -1747,6 +1756,7 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("get_item_tooltip", "index"), &PopupMenu::get_item_tooltip); ClassDB::bind_method(D_METHOD("get_item_shortcut", "index"), &PopupMenu::get_item_shortcut); + ClassDB::bind_method(D_METHOD("set_current_index", "index"), &PopupMenu::set_current_index); ClassDB::bind_method(D_METHOD("get_current_index"), &PopupMenu::get_current_index); ClassDB::bind_method(D_METHOD("set_item_count", "count"), &PopupMenu::set_item_count); ClassDB::bind_method(D_METHOD("get_item_count"), &PopupMenu::get_item_count); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 8f4c063c58..4865b9770e 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -421,9 +421,24 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> Line &l = p_frame->lines.write[p_line]; + uint16_t autowrap_flags = TextServer::BREAK_MANDATORY; + switch (autowrap_mode) { + case AUTOWRAP_WORD_SMART: + autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY; + break; + case AUTOWRAP_WORD: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; + break; + case AUTOWRAP_ARBITRARY: + autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY; + break; + case AUTOWRAP_OFF: + break; + } + // Clear cache. l.text_buf->clear(); - l.text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_TRIM_EDGE_SPACES); + l.text_buf->set_flags(autowrap_flags | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_TRIM_EDGE_SPACES); l.char_offset = *r_char_offset; l.char_count = 0; @@ -4077,6 +4092,19 @@ String RichTextLabel::get_language() const { return language; } +void RichTextLabel::set_autowrap_mode(RichTextLabel::AutowrapMode p_mode) { + if (autowrap_mode != p_mode) { + autowrap_mode = p_mode; + main->first_invalid_line = 0; //invalidate ALL + _validate_line_caches(main); + update(); + } +} + +RichTextLabel::AutowrapMode RichTextLabel::get_autowrap_mode() const { + return autowrap_mode; +} + void RichTextLabel::set_percent_visible(float p_percent) { if (percent_visible != p_percent) { if (p_percent < 0 || p_percent >= 1) { @@ -4188,6 +4216,9 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_language", "language"), &RichTextLabel::set_language); ClassDB::bind_method(D_METHOD("get_language"), &RichTextLabel::get_language); + ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &RichTextLabel::set_autowrap_mode); + ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &RichTextLabel::get_autowrap_mode); + ClassDB::bind_method(D_METHOD("set_meta_underline", "enable"), &RichTextLabel::set_meta_underline); ClassDB::bind_method(D_METHOD("is_meta_underlined"), &RichTextLabel::is_meta_underlined); @@ -4280,6 +4311,8 @@ void RichTextLabel::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); + ADD_GROUP("Structured Text", "structured_text_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options"); @@ -4288,6 +4321,11 @@ void RichTextLabel::_bind_methods() { ADD_SIGNAL(MethodInfo("meta_hover_started", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); ADD_SIGNAL(MethodInfo("meta_hover_ended", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); + BIND_ENUM_CONSTANT(AUTOWRAP_OFF); + BIND_ENUM_CONSTANT(AUTOWRAP_ARBITRARY); + BIND_ENUM_CONSTANT(AUTOWRAP_WORD); + BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART); + BIND_ENUM_CONSTANT(LIST_NUMBERS); BIND_ENUM_CONSTANT(LIST_LETTERS); BIND_ENUM_CONSTANT(LIST_ROMAN); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 2b24da4c37..e79244f2e4 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -39,6 +39,13 @@ class RichTextLabel : public Control { GDCLASS(RichTextLabel, Control); public: + enum AutowrapMode { + AUTOWRAP_OFF, + AUTOWRAP_ARBITRARY, + AUTOWRAP_WORD, + AUTOWRAP_WORD_SMART + }; + enum ListType { LIST_NUMBERS, LIST_LETTERS, @@ -346,6 +353,8 @@ private: VScrollBar *vscroll = nullptr; + AutowrapMode autowrap_mode = AUTOWRAP_WORD_SMART; + bool scroll_visible = false; bool scroll_follow = false; bool scroll_following = false; @@ -574,6 +583,9 @@ public: void set_language(const String &p_language); String get_language() const; + void set_autowrap_mode(AutowrapMode p_mode); + AutowrapMode get_autowrap_mode() const; + void set_structured_text_bidi_override(Control::StructuredTextParser p_parser); Control::StructuredTextParser get_structured_text_bidi_override() const; @@ -603,6 +615,7 @@ public: ~RichTextLabel(); }; +VARIANT_ENUM_CAST(RichTextLabel::AutowrapMode); VARIANT_ENUM_CAST(RichTextLabel::ListType); VARIANT_ENUM_CAST(RichTextLabel::ItemType); VARIANT_ENUM_CAST(RichTextLabel::VisibleCharactersBehavior); diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index dd66f566af..4e91548d14 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -86,9 +86,9 @@ String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const S String lowwer_case_header_name = p_header_name.to_lower(); for (int i = 0; i < p_headers.size(); i++) { - if (p_headers[i].find(":", 0) >= 0) { + if (p_headers[i].find(":") > 0) { Vector<String> parts = p_headers[i].split(":", false, 1); - if (parts[0].strip_edges().to_lower() == lowwer_case_header_name) { + if (parts.size() > 1 && parts[0].strip_edges().to_lower() == lowwer_case_header_name) { value = parts[1].strip_edges(); break; } @@ -99,7 +99,7 @@ String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const S } Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_headers, bool p_ssl_validate_domain, HTTPClient::Method p_method, const String &p_request_data) { - // Copy the string into a raw buffer + // Copy the string into a raw buffer. Vector<uint8_t> raw_data; CharString charstr = p_request_data.utf8(); @@ -134,7 +134,7 @@ Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_cust headers = p_custom_headers; if (accept_gzip) { - // If the user has specified a different Accept-Encoding, don't overwrite it + // If the user has specified an Accept-Encoding header, don't overwrite it. if (!has_header(headers, "Accept-Encoding")) { headers.push_back("Accept-Encoding: gzip, deflate"); } @@ -227,7 +227,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) { } if (response_code == 301 || response_code == 302) { - // Handle redirect + // Handle redirect. if (max_redirects >= 0 && redirections >= max_redirects) { call_deferred(SNAME("_request_done"), RESULT_REDIRECT_LIMIT_REACHED, response_code, response_headers, PackedByteArray()); @@ -244,12 +244,12 @@ bool HTTPRequest::_handle_response(bool *ret_value) { } if (!new_request.is_empty()) { - // 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, new request. _parse_url(new_request); } else { request_string = new_request; @@ -276,11 +276,11 @@ bool HTTPRequest::_update_connection() { switch (client->get_status()) { case HTTPClient::STATUS_DISCONNECTED: { call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); - return true; // End it, since it's doing something + return true; // End it, since it's disconnected. } break; case HTTPClient::STATUS_RESOLVING: { client->poll(); - // Must wait + // Must wait. return false; } break; case HTTPClient::STATUS_CANT_RESOLVE: { @@ -290,9 +290,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(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); return true; @@ -301,7 +301,7 @@ bool HTTPRequest::_update_connection() { case HTTPClient::STATUS_CONNECTED: { if (request_sent) { if (!got_response) { - // No body + // No body. bool ret_value; @@ -313,16 +313,16 @@ bool HTTPRequest::_update_connection() { return true; } if (body_len < 0) { - // Chunked transfer is done + // Chunked transfer is done. call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body); return true; } call_deferred(SNAME("_request_done"), RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray()); return true; - // Request might have been done + // Request might have been done. } else { - // Did not request yet, do request + // Did not request yet, do request. int size = request_data.size(); Error err = client->request(method, request_string, headers, size > 0 ? request_data.ptr() : nullptr, size); @@ -334,13 +334,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, still requesting + // Must wait, still requesting. client->poll(); return false; - } break; // Request in progress + } break; // Request in progress. case HTTPClient::STATUS_BODY: { if (!got_response) { bool ret_value; @@ -411,7 +411,7 @@ bool HTTPRequest::_update_connection() { 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(SNAME("_request_done"), RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray()); return true; @@ -428,7 +428,7 @@ bool HTTPRequest::_update_connection() { void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data) { cancel_request(); - // Determine if the request body is compressed + // Determine if the request body is compressed. bool is_compressed; String content_encoding = get_header_value(p_headers, "Content-Encoding").to_lower(); Compression::Mode mode; @@ -452,11 +452,11 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra } else if (result == -5) { WARN_PRINT("Decompressed size of HTTP response body exceeded body_size_limit"); p_status = RESULT_BODY_SIZE_LIMIT_EXCEEDED; - // Just return the raw data if we failed to decompress it + // Just return the raw data if we failed to decompress it. } else { WARN_PRINT("Failed to decompress HTTP response body"); p_status = RESULT_BODY_DECOMPRESS_FAILED; - // Just return the raw data if we failed to decompress it + // Just return the raw data if we failed to decompress it. } } @@ -471,7 +471,6 @@ void HTTPRequest::_notification(int p_what) { bool done = _update_connection(); if (done) { set_process_internal(false); - // cancel_request(); called from _request done now } } @@ -619,7 +618,6 @@ void HTTPRequest::_bind_methods() { ADD_SIGNAL(MethodInfo("request_completed", PropertyInfo(Variant::INT, "result"), PropertyInfo(Variant::INT, "response_code"), PropertyInfo(Variant::PACKED_STRING_ARRAY, "headers"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "body"))); BIND_ENUM_CONSTANT(RESULT_SUCCESS); - //BIND_ENUM_CONSTANT( RESULT_NO_BODY ); BIND_ENUM_CONSTANT(RESULT_CHUNKED_BODY_SIZE_MISMATCH); BIND_ENUM_CONSTANT(RESULT_CANT_CONNECT); BIND_ENUM_CONSTANT(RESULT_CANT_RESOLVE); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index bde68f0b3d..09880ad6cf 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2092,7 +2092,7 @@ void Viewport::_gui_hide_control(Control *p_control) { } if (gui.key_focus == p_control) { - _gui_remove_focus(); + gui_release_focus(); } if (gui.mouse_over == p_control) { gui.mouse_over = nullptr; @@ -2142,15 +2142,7 @@ Window *Viewport::get_base_window() const { } void Viewport::_gui_remove_focus_for_window(Node *p_window) { if (get_base_window() == p_window) { - _gui_remove_focus(); - } -} - -void Viewport::_gui_remove_focus() { - if (gui.key_focus) { - Node *f = gui.key_focus; - gui.key_focus = nullptr; - f->notification(Control::NOTIFICATION_FOCUS_EXIT, true); + gui_release_focus(); } } @@ -2279,10 +2271,6 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus } } -Control *Viewport::_gui_get_focus_owner() { - return gui.key_focus; -} - void Viewport::_gui_grab_click_focus(Control *p_control) { gui.mouse_click_grabber = p_control; call_deferred(SNAME("_post_gui_grab_click_focus")); @@ -2798,6 +2786,19 @@ int Viewport::gui_get_canvas_sort_index() { return gui.canvas_sort_index++; } +void Viewport::gui_release_focus() { + if (gui.key_focus) { + Control *f = gui.key_focus; + gui.key_focus = nullptr; + f->notification(Control::NOTIFICATION_FOCUS_EXIT, true); + f->update(); + } +} + +Control *Viewport::gui_get_focus_owner() { + return gui.key_focus; +} + void Viewport::set_msaa(MSAA p_msaa) { ERR_FAIL_INDEX(p_msaa, MSAA_MAX); if (msaa == p_msaa) { @@ -3591,6 +3592,9 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("gui_is_dragging"), &Viewport::gui_is_dragging); ClassDB::bind_method(D_METHOD("gui_is_drag_successful"), &Viewport::gui_is_drag_successful); + ClassDB::bind_method(D_METHOD("gui_release_focus"), &Viewport::gui_release_focus); + ClassDB::bind_method(D_METHOD("gui_get_focus_owner"), &Viewport::gui_get_focus_owner); + ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input); ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 2541474cf3..3a71745f44 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -411,7 +411,6 @@ private: Control *_gui_get_drag_preview(); void _gui_remove_focus_for_window(Node *p_window); - void _gui_remove_focus(); void _gui_unfocus_control(Control *p_control); bool _gui_control_has_focus(const Control *p_control); void _gui_control_grab_focus(Control *p_control); @@ -419,8 +418,6 @@ private: void _post_gui_grab_click_focus(); void _gui_accept_event(); - Control *_gui_get_focus_owner(); - bool _gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check); friend class AudioListener2D; @@ -559,6 +556,9 @@ public: void gui_reset_canvas_sort_index(); int gui_get_canvas_sort_index(); + void gui_release_focus(); + Control *gui_get_focus_owner(); + TypedArray<String> get_configuration_warnings() const override; void set_debug_draw(DebugDraw p_debug_draw); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index f7036578e2..838cef824b 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -555,11 +555,13 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeResizableBase); GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeGroupBase); GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeConstant); + GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeVectorBase); GDREGISTER_CLASS(VisualShaderNodeComment); GDREGISTER_CLASS(VisualShaderNodeFloatConstant); GDREGISTER_CLASS(VisualShaderNodeIntConstant); GDREGISTER_CLASS(VisualShaderNodeBooleanConstant); GDREGISTER_CLASS(VisualShaderNodeColorConstant); + GDREGISTER_CLASS(VisualShaderNodeVec2Constant); GDREGISTER_CLASS(VisualShaderNodeVec3Constant); GDREGISTER_CLASS(VisualShaderNodeTransformConstant); GDREGISTER_CLASS(VisualShaderNodeFloatOp); @@ -603,6 +605,7 @@ void register_scene_types() { GDREGISTER_CLASS(VisualShaderNodeIntUniform); GDREGISTER_CLASS(VisualShaderNodeBooleanUniform); GDREGISTER_CLASS(VisualShaderNodeColorUniform); + GDREGISTER_CLASS(VisualShaderNodeVec2Uniform); GDREGISTER_CLASS(VisualShaderNodeVec3Uniform); GDREGISTER_CLASS(VisualShaderNodeTransformUniform); GDREGISTER_CLASS(VisualShaderNodeTextureUniform); diff --git a/scene/resources/box_shape_3d.cpp b/scene/resources/box_shape_3d.cpp index b97d378e02..a1ec9a2230 100644 --- a/scene/resources/box_shape_3d.cpp +++ b/scene/resources/box_shape_3d.cpp @@ -95,5 +95,5 @@ void BoxShape3D::_bind_methods() { BoxShape3D::BoxShape3D() : Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_BOX)) { - set_size(Vector3(2, 2, 2)); + set_size(Vector3(1, 1, 1)); } diff --git a/scene/resources/capsule_shape_3d.h b/scene/resources/capsule_shape_3d.h index 967a413da4..4c039ab326 100644 --- a/scene/resources/capsule_shape_3d.h +++ b/scene/resources/capsule_shape_3d.h @@ -35,8 +35,8 @@ class CapsuleShape3D : public Shape3D { GDCLASS(CapsuleShape3D, Shape3D); - float radius = 1.0; - float height = 3.0; + float radius = 0.5; + float height = 2.0; protected: static void _bind_methods(); diff --git a/scene/resources/cylinder_shape_3d.h b/scene/resources/cylinder_shape_3d.h index 0211f2b08f..65427423c8 100644 --- a/scene/resources/cylinder_shape_3d.h +++ b/scene/resources/cylinder_shape_3d.h @@ -35,7 +35,7 @@ class CylinderShape3D : public Shape3D { GDCLASS(CylinderShape3D, Shape3D); - float radius = 1.0; + float radius = 0.5; float height = 2.0; protected: diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index aa9682bd80..3fc5fd4a16 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -106,8 +106,8 @@ class CapsuleMesh : public PrimitiveMesh { GDCLASS(CapsuleMesh, PrimitiveMesh); private: - float radius = 1.0; - float height = 3.0; + float radius = 0.5; + float height = 2.0; int radial_segments = 64; int rings = 8; @@ -138,7 +138,7 @@ class BoxMesh : public PrimitiveMesh { GDCLASS(BoxMesh, PrimitiveMesh); private: - Vector3 size = Vector3(2.0, 2.0, 2.0); + Vector3 size = Vector3(1, 1, 1); int subdivide_w = 0; int subdivide_h = 0; int subdivide_d = 0; @@ -171,8 +171,8 @@ class CylinderMesh : public PrimitiveMesh { GDCLASS(CylinderMesh, PrimitiveMesh); private: - float top_radius = 1.0; - float bottom_radius = 1.0; + float top_radius = 0.5; + float bottom_radius = 0.5; float height = 2.0; int radial_segments = 64; int rings = 4; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 303d3d65c1..0c7f069004 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -53,8 +53,98 @@ int VisualShaderNode::get_output_port_for_preview() const { return port_preview; } -void VisualShaderNode::set_input_port_default_value(int p_port, const Variant &p_value) { - default_input_values[p_port] = p_value; +void VisualShaderNode::set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value) { + Variant value = p_value; + + if (p_prev_value.get_type() != Variant::NIL) { + switch (p_value.get_type()) { + case Variant::FLOAT: { + switch (p_prev_value.get_type()) { + case Variant::INT: { + value = (float)p_prev_value; + } break; + case Variant::FLOAT: { + value = p_prev_value; + } break; + case Variant::VECTOR2: { + Vector2 pv = p_prev_value; + value = pv.x; + } break; + case Variant::VECTOR3: { + Vector3 pv = p_prev_value; + value = pv.x; + } break; + default: + break; + } + } break; + case Variant::INT: { + switch (p_prev_value.get_type()) { + case Variant::INT: { + value = p_prev_value; + } break; + case Variant::FLOAT: { + value = (int)p_prev_value; + } break; + case Variant::VECTOR2: { + Vector2 pv = p_prev_value; + value = (int)pv.x; + } break; + case Variant::VECTOR3: { + Vector3 pv = p_prev_value; + value = (int)pv.x; + } break; + default: + break; + } + } break; + case Variant::VECTOR2: { + switch (p_prev_value.get_type()) { + case Variant::INT: { + float pv = (float)(int)p_prev_value; + value = Vector2(pv, pv); + } break; + case Variant::FLOAT: { + float pv = p_prev_value; + value = Vector2(pv, pv); + } break; + case Variant::VECTOR2: { + value = p_prev_value; + } break; + case Variant::VECTOR3: { + Vector3 pv = p_prev_value; + value = Vector2(pv.x, pv.y); + } break; + default: + break; + } + } break; + case Variant::VECTOR3: { + switch (p_prev_value.get_type()) { + case Variant::INT: { + float pv = (float)(int)p_prev_value; + value = Vector3(pv, pv, pv); + } break; + case Variant::FLOAT: { + float pv = p_prev_value; + value = Vector3(pv, pv, pv); + } break; + case Variant::VECTOR2: { + Vector2 pv = p_prev_value; + value = Vector3(pv.x, pv.y, 0.0); + } break; + case Variant::VECTOR3: { + value = p_prev_value; + } break; + default: + break; + } + } break; + default: + break; + } + } + default_input_values[p_port] = value; emit_changed(); } @@ -156,8 +246,15 @@ int VisualShaderNode::get_expanded_output_port_count() const { int count2 = count; for (int i = 0; i < count; i++) { if (is_output_port_expandable(i) && _is_output_port_expanded(i)) { - if (get_output_port_type(i) == PORT_TYPE_VECTOR) { - count2 += 3; + switch (get_output_port_type(i)) { + case PORT_TYPE_VECTOR_2D: { + count2 += 2; + } break; + case PORT_TYPE_VECTOR: { + count2 += 3; + } break; + default: + break; } } } @@ -245,7 +342,7 @@ void VisualShaderNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_output_ports_expanded", "values"), &VisualShaderNode::_set_output_ports_expanded); ClassDB::bind_method(D_METHOD("_get_output_ports_expanded"), &VisualShaderNode::_get_output_ports_expanded); - ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value"), &VisualShaderNode::set_input_port_default_value); + ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value", "prev_value"), &VisualShaderNode::set_input_port_default_value, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("get_input_port_default_value", "port"), &VisualShaderNode::get_input_port_default_value); ClassDB::bind_method(D_METHOD("remove_input_port_default_value", "port"), &VisualShaderNode::remove_input_port_default_value); @@ -261,6 +358,7 @@ void VisualShaderNode::_bind_methods() { BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR); BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR_INT); + BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR_2D); BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR); BIND_ENUM_CONSTANT(PORT_TYPE_BOOLEAN); BIND_ENUM_CONSTANT(PORT_TYPE_TRANSFORM); @@ -385,9 +483,9 @@ String VisualShaderNodeCustom::generate_global_per_node(Shader::Mode p_mode, Vis return ""; } -void VisualShaderNodeCustom::set_input_port_default_value(int p_port, const Variant &p_value) { +void VisualShaderNodeCustom::set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value) { if (!is_initialized) { - VisualShaderNode::set_input_port_default_value(p_port, p_value); + VisualShaderNode::set_input_port_default_value(p_port, p_value, p_prev_value); } } @@ -484,24 +582,48 @@ void VisualShader::update_engine_version(const Dictionary &p_new_version) { if (expression.is_valid()) { for (int j = 0; j < expression->get_input_port_count(); j++) { int type = expression->get_input_port_type(j); - if (type > 0) { // + PORT_TYPE_SCALAR_INT - type += 1; + if (type > 0) { // + PORT_TYPE_SCALAR_INT + PORT_TYPE_VECTOR_2D + type += 2; } expression->set_input_port_type(j, type); } for (int j = 0; j < expression->get_output_port_count(); j++) { int type = expression->get_output_port_type(j); - if (type > 0) { // + PORT_TYPE_SCALAR_INT - type += 1; + if (type > 0) { // + PORT_TYPE_SCALAR_INT + PORT_TYPE_VECTOR_2D + type += 2; } expression->set_output_port_type(j, type); } } + Ref<VisualShaderNodeStep> step = Object::cast_to<VisualShaderNodeStep>(E.value.node.ptr()); + if (step.is_valid()) { + int op_type = int(step->get_op_type()); + if (int(op_type) > 0) { // + OP_TYPE_VECTOR_2D + OP_TYPE_VECTOR_2D_SCALAR + op_type += 2; + } + step->set_op_type(VisualShaderNodeStep::OpType(op_type)); + } + Ref<VisualShaderNodeSmoothStep> sstep = Object::cast_to<VisualShaderNodeSmoothStep>(E.value.node.ptr()); + if (sstep.is_valid()) { + int op_type = int(sstep->get_op_type()); + if (int(op_type) > 0) { // + OP_TYPE_VECTOR_2D + OP_TYPE_VECTOR_2D_SCALAR + op_type += 2; + } + sstep->set_op_type(VisualShaderNodeSmoothStep::OpType(op_type)); + } + Ref<VisualShaderNodeMix> mix = Object::cast_to<VisualShaderNodeMix>(E.value.node.ptr()); + if (mix.is_valid()) { + int op_type = int(mix->get_op_type()); + if (int(op_type) > 0) { // + OP_TYPE_VECTOR_2D + OP_TYPE_VECTOR_2D_SCALAR + op_type += 2; + } + mix->set_op_type(VisualShaderNodeMix::OpType(op_type)); + } Ref<VisualShaderNodeCompare> compare = Object::cast_to<VisualShaderNodeCompare>(E.value.node.ptr()); if (compare.is_valid()) { int ctype = int(compare->get_comparison_type()); - if (int(ctype) > 0) { // + PORT_TYPE_SCALAR_INT - ctype += 1; + if (int(ctype) > 0) { // + CTYPE_SCALAR_INT + CTYPE_VECTOR_2D + ctype += 2; } compare->set_comparison_type(VisualShaderNodeCompare::ComparisonType(ctype)); } @@ -719,7 +841,7 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po } bool VisualShader::is_port_types_compatible(int p_a, int p_b) const { - return MAX(0, p_a - 3) == (MAX(0, p_b - 3)); + return MAX(0, p_a - 4) == (MAX(0, p_b - 4)); } void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { @@ -953,15 +1075,27 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port Error err = _write_node(p_type, global_code, global_code_per_node, global_code_per_func, code, default_tex_params, input_connections, output_connections, p_node, processed, true, classes); ERR_FAIL_COND_V(err != OK, String()); - if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_SCALAR) { - code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " );\n"; - } else if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_SCALAR_INT) { - code += " COLOR.rgb = vec3(float(n_out" + itos(p_node) + "p" + itos(p_port) + "));\n"; - } else if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_BOOLEAN) { - code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " ? 1.0 : 0.0);\n"; - } else { - code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n"; + switch (node->get_output_port_type(p_port)) { + case VisualShaderNode::PORT_TYPE_SCALAR: { + code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + ");\n"; + } break; + case VisualShaderNode::PORT_TYPE_SCALAR_INT: { + code += " COLOR.rgb = vec3(float(n_out" + itos(p_node) + "p" + itos(p_port) + "));\n"; + } break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: { + code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " ? 1.0 : 0.0);\n"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + ", 0.0);\n"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n"; + } break; + default: { + code += " COLOR.rgb = vec3(0.0);\n"; + } break; } + code += "}\n"; //set code secretly @@ -1406,30 +1540,102 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui } } else if (in_type == out_type) { inputs[i] = src_var; - } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_VECTOR) { - inputs[i] = "dot(" + src_var + ", vec3(0.333333, 0.333333, 0.333333))"; - } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR_INT && out_type == VisualShaderNode::PORT_TYPE_VECTOR) { - inputs[i] = "dot(float(" + src_var + "), vec3(0.333333, 0.333333, 0.333333))"; - } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_SCALAR) { - inputs[i] = "vec3(" + src_var + ")"; - } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_SCALAR_INT) { - inputs[i] = "vec3(float(" + src_var + "))"; - } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_VECTOR) { - inputs[i] = "all(bvec3(" + src_var + "))"; - } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_SCALAR) { - inputs[i] = src_var + " > 0.0 ? true : false"; - } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_SCALAR_INT) { - inputs[i] = src_var + " > 0 ? true : false"; - } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) { - inputs[i] = "(" + src_var + " ? 1.0 : 0.0)"; - } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR_INT && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) { - inputs[i] = "(" + src_var + " ? 1 : 0)"; - } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) { - inputs[i] = "vec3(" + src_var + " ? 1.0 : 0.0)"; - } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_SCALAR_INT) { - inputs[i] = "float(" + src_var + ")"; - } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR_INT && out_type == VisualShaderNode::PORT_TYPE_SCALAR) { - inputs[i] = "int(" + src_var + ")"; + } else { + switch (in_type) { + case VisualShaderNode::PORT_TYPE_SCALAR: { + switch (out_type) { + case VisualShaderNode::PORT_TYPE_SCALAR_INT: { + inputs[i] = "float(" + src_var + ")"; + } break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: { + inputs[i] = "(" + src_var + " ? 1.0 : 0.0)"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + inputs[i] = "dot(" + src_var + ", vec2(0.333333, 0.333333))"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + inputs[i] = "dot(" + src_var + ", vec3(0.333333, 0.333333, 0.333333))"; + } break; + default: + break; + } + } break; + case VisualShaderNode::PORT_TYPE_SCALAR_INT: { + switch (out_type) { + case VisualShaderNode::PORT_TYPE_SCALAR: { + inputs[i] = "int(" + src_var + ")"; + } break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: { + inputs[i] = "(" + src_var + " ? 1 : 0)"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + inputs[i] = "dot(float(" + src_var + "), vec2(0.333333, 0.333333))"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + inputs[i] = "dot(float(" + src_var + "), vec3(0.333333, 0.333333, 0.333333))"; + } break; + default: + break; + } + } break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: { + switch (out_type) { + case VisualShaderNode::PORT_TYPE_SCALAR: { + inputs[i] = src_var + " > 0.0 ? true : false"; + } break; + case VisualShaderNode::PORT_TYPE_SCALAR_INT: { + inputs[i] = src_var + " > 0 ? true : false"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + inputs[i] = "all(bvec2(" + src_var + "))"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + inputs[i] = "all(bvec3(" + src_var + "))"; + } break; + default: + break; + } + } break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + switch (out_type) { + case VisualShaderNode::PORT_TYPE_SCALAR: { + inputs[i] = "vec2(" + src_var + ")"; + } break; + case VisualShaderNode::PORT_TYPE_SCALAR_INT: { + inputs[i] = "vec2(float(" + src_var + "))"; + } break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: { + inputs[i] = "vec2(" + src_var + " ? 1.0 : 0.0)"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + inputs[i] = "vec2(" + src_var + ".xy)"; + } break; + default: + break; + } + } break; + + case VisualShaderNode::PORT_TYPE_VECTOR: { + switch (out_type) { + case VisualShaderNode::PORT_TYPE_SCALAR: { + inputs[i] = "vec3(" + src_var + ")"; + } break; + case VisualShaderNode::PORT_TYPE_SCALAR_INT: { + inputs[i] = "vec3(float(" + src_var + "))"; + } break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: { + inputs[i] = "vec3(" + src_var + " ? 1.0 : 0.0)"; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + inputs[i] = "vec3(" + src_var + ", 0.0)"; + } break; + default: + break; + } + } break; + default: + break; + } } } else { if (!vsnode->is_generate_input_var(i)) { @@ -1449,6 +1655,10 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui bool val = defval; inputs[i] = "n_in" + itos(node) + "p" + itos(i); node_code += " bool " + inputs[i] + " = " + (val ? "true" : "false") + ";\n"; + } else if (defval.get_type() == Variant::VECTOR2) { + Vector2 val = defval; + inputs[i] = "n_in" + itos(node) + "p" + itos(i); + node_code += " vec2 " + inputs[i] + " = " + vformat("vec2(%.5f, %.5f);\n", val.x, val.y); } else if (defval.get_type() == Variant::VECTOR3) { Vector3 val = defval; inputs[i] = "n_in" + itos(node) + "p" + itos(i); @@ -1485,8 +1695,15 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui if (vsnode->is_output_port_expandable(i) && vsnode->_is_output_port_expanded(i)) { expanded = true; - if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) { - output_count += 3; + switch (vsnode->get_output_port_type(i)) { + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + output_count += 2; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + output_count += 3; + } break; + default: + break; } } expanded_output_ports.insert(i, expanded); @@ -1506,6 +1723,9 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui case VisualShaderNode::PORT_TYPE_SCALAR_INT: outputs[i] = "int " + var_name; break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: + outputs[i] = "vec2 " + var_name; + break; case VisualShaderNode::PORT_TYPE_VECTOR: outputs[i] = "vec3 " + var_name; break; @@ -1515,12 +1735,19 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui case VisualShaderNode::PORT_TYPE_TRANSFORM: outputs[i] = "mat4 " + var_name; break; - default: { - } + default: + break; } if (expanded_output_ports[i]) { - if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) { - j += 3; + switch (vsnode->get_output_port_type(i)) { + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + j += 2; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + j += 3; + } break; + default: + break; } } } @@ -1535,6 +1762,9 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui case VisualShaderNode::PORT_TYPE_SCALAR_INT: code += " int " + outputs[i] + ";\n"; break; + case VisualShaderNode::PORT_TYPE_VECTOR_2D: + code += " vec2 " + outputs[i] + ";\n"; + break; case VisualShaderNode::PORT_TYPE_VECTOR: code += " vec3 " + outputs[i] + ";\n"; break; @@ -1544,12 +1774,19 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui case VisualShaderNode::PORT_TYPE_TRANSFORM: code += " mat4 " + outputs[i] + ";\n"; break; - default: { - } + default: + break; } if (expanded_output_ports[i]) { - if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) { - j += 3; + switch (vsnode->get_output_port_type(i)) { + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + j += 2; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + j += 3; + } break; + default: + break; } } } @@ -1565,38 +1802,65 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui for (int i = 0; i < output_count; i++) { bool new_line_inserted = false; if (expanded_output_ports[i]) { - if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) { - if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component - if (!new_line_inserted) { - code += "\n"; - new_line_inserted = true; + switch (vsnode->get_output_port_type(i)) { + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component + if (!new_line_inserted) { + code += "\n"; + new_line_inserted = true; + } + String r = "n_out" + itos(node) + "p" + itos(i + 1); + code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n"; + outputs[i + 1] = r; } - String r = "n_out" + itos(node) + "p" + itos(i + 1); - code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n"; - outputs[i + 1] = r; - } - if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component - if (!new_line_inserted) { - code += "\n"; - new_line_inserted = true; + if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component + if (!new_line_inserted) { + code += "\n"; + new_line_inserted = true; + } + String g = "n_out" + itos(node) + "p" + itos(i + 2); + code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n"; + outputs[i + 2] = g; + } + + i += 2; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR: { + if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component + if (!new_line_inserted) { + code += "\n"; + new_line_inserted = true; + } + String r = "n_out" + itos(node) + "p" + itos(i + 1); + code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n"; + outputs[i + 1] = r; } - String g = "n_out" + itos(node) + "p" + itos(i + 2); - code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n"; - outputs[i + 2] = g; - } - if (vsnode->is_output_port_connected(i + 3) || (for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component - if (!new_line_inserted) { - code += "\n"; - new_line_inserted = true; + if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component + if (!new_line_inserted) { + code += "\n"; + new_line_inserted = true; + } + String g = "n_out" + itos(node) + "p" + itos(i + 2); + code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n"; + outputs[i + 2] = g; } - String b = "n_out" + itos(node) + "p" + itos(i + 3); - code += " float " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n"; - outputs[i + 3] = b; - } - i += 3; + if (vsnode->is_output_port_connected(i + 3) || (for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component + if (!new_line_inserted) { + code += "\n"; + new_line_inserted = true; + } + String b = "n_out" + itos(node) + "p" + itos(i + 3); + code += " float " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n"; + outputs[i + 3] = b; + } + + i += 3; + } break; + default: + break; } } } @@ -2066,8 +2330,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "TANGENT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "BINORMAL" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, @@ -2082,7 +2346,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection", "PROJECTION_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_projection", "INV_PROJECTION_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(VIEWPORT_SIZE, 0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" }, // Node3D, Fragment @@ -2092,19 +2356,19 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "TANGENT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "BINORMAL" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "view", "VIEW" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "world", "WORLD_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_camera", "INV_CAMERA_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "camera", "CAMERA_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection", "PROJECTION_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_projection", "INV_PROJECTION_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(VIEWPORT_SIZE, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "front_facing", "FRONT_FACING" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" }, @@ -2114,8 +2378,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { // Node3D, Light { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.xyz" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "view", "VIEW" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light", "LIGHT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_color", "LIGHT_COLOR" }, @@ -2132,18 +2396,18 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection", "PROJECTION_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_projection", "INV_PROJECTION_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(VIEWPORT_SIZE, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" }, // Canvas Item // Canvas Item, Vertex - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX, 0.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "texture_pixel_size", "vec3(TEXTURE_PIXEL_SIZE, 1.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "world", "WORLD_MATRIX" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "canvas", "CANVAS_MATRIX" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "screen", "SCREEN_MATRIX" }, @@ -2154,13 +2418,13 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { // Canvas Item, Fragment { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.xyz" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "texture_pixel_size", "vec3(TEXTURE_PIXEL_SIZE, 1.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_pixel_size", "vec3(SCREEN_PIXEL_SIZE, 1.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_pixel_size", "SCREEN_PIXEL_SIZE" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" }, @@ -2169,11 +2433,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "specular_shininess", "SPECULAR_SHININESS.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "specular_shininess_alpha", "SPECULAR_SHININESS.a" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" }, // Canvas Item, Light { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.xyz" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, @@ -2185,9 +2449,9 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_vertex", "LIGHT_VERTEX" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "shadow", "SHADOW_MODULATE.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "shadow_alpha", "SHADOW_MODULATE.a" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "texture_pixel_size", "vec3(TEXTURE_PIXEL_SIZE, 1.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "specular_shininess", "SPECULAR_SHININESS.rgb" }, @@ -2302,8 +2566,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR, "quarter_res_color", "QUARTER_RES_COLOR.rgb" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "quarter_res_alpha", "QUARTER_RES_COLOR.a" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SAMPLER, "radiance", "RADIANCE" }, - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR, "sky_coords", "vec3(SKY_COORDS, 0.0)" }, + { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, + { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "sky_coords", "SKY_COORDS" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Fog, Fog @@ -2324,11 +2588,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "vec3(0.0, 1.0, 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "vec3(1.0, 0.0, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(1.0, 1.0, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Spatial, Fragment @@ -2337,27 +2601,27 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "vec3(0.0, 1.0, 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "vec3(1.0, 0.0, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(1.0, 1.0, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Spatial, Light { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.rgb" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV, 0.0)" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(1.0, 1.0, 0.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Canvas Item, Vertex - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX, 0.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, @@ -2365,20 +2629,20 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { // Canvas Item, Fragment { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Canvas Item, Light { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Particles @@ -2391,7 +2655,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { // Sky - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, + { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Fog @@ -2455,6 +2719,9 @@ String VisualShaderNodeInput::generate_code(Shader::Mode p_mode, VisualShader::T case PORT_TYPE_SCALAR_INT: { code = " " + p_output_vars[0] + " = 0;\n"; } break; + case PORT_TYPE_VECTOR_2D: { + code = " " + p_output_vars[0] + " = vec2(0.0);\n"; + } break; case PORT_TYPE_VECTOR: { code = " " + p_output_vars[0] + " = vec3(0.0);\n"; } break; @@ -2670,7 +2937,9 @@ int VisualShaderNodeUniformRef::get_output_port_count() const { return 1; case UniformType::UNIFORM_TYPE_BOOLEAN: return 1; - case UniformType::UNIFORM_TYPE_VECTOR: + case UniformType::UNIFORM_TYPE_VECTOR2: + return 1; + case UniformType::UNIFORM_TYPE_VECTOR3: return 1; case UniformType::UNIFORM_TYPE_TRANSFORM: return 1; @@ -2692,7 +2961,9 @@ VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_output_port return PortType::PORT_TYPE_SCALAR_INT; case UniformType::UNIFORM_TYPE_BOOLEAN: return PortType::PORT_TYPE_BOOLEAN; - case UniformType::UNIFORM_TYPE_VECTOR: + case UniformType::UNIFORM_TYPE_VECTOR2: + return PortType::PORT_TYPE_VECTOR_2D; + case UniformType::UNIFORM_TYPE_VECTOR3: return PortType::PORT_TYPE_VECTOR; case UniformType::UNIFORM_TYPE_TRANSFORM: return PortType::PORT_TYPE_TRANSFORM; @@ -2719,7 +2990,9 @@ String VisualShaderNodeUniformRef::get_output_port_name(int p_port) const { return ""; case UniformType::UNIFORM_TYPE_BOOLEAN: return ""; - case UniformType::UNIFORM_TYPE_VECTOR: + case UniformType::UNIFORM_TYPE_VECTOR2: + return ""; + case UniformType::UNIFORM_TYPE_VECTOR3: return ""; case UniformType::UNIFORM_TYPE_TRANSFORM: return ""; @@ -2789,7 +3062,9 @@ VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_port_type_b return PORT_TYPE_SCALAR_INT; case UniformType::UNIFORM_TYPE_SAMPLER: return PORT_TYPE_SAMPLER; - case UniformType::UNIFORM_TYPE_VECTOR: + case UniformType::UNIFORM_TYPE_VECTOR2: + return PORT_TYPE_VECTOR_2D; + case UniformType::UNIFORM_TYPE_VECTOR3: return PORT_TYPE_VECTOR; case UniformType::UNIFORM_TYPE_TRANSFORM: return PORT_TYPE_TRANSFORM; @@ -2808,26 +3083,19 @@ String VisualShaderNodeUniformRef::generate_code(Shader::Mode p_mode, VisualShad if (uniform_name == "[None]") { return " " + p_output_vars[0] + " = 0.0;\n"; } - return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; - case UniformType::UNIFORM_TYPE_INT: - return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; - case UniformType::UNIFORM_TYPE_BOOLEAN: - return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; - case UniformType::UNIFORM_TYPE_VECTOR: - return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; - case UniformType::UNIFORM_TYPE_TRANSFORM: - return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + break; case UniformType::UNIFORM_TYPE_COLOR: { String code = " " + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n"; code += " " + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n"; return code; } break; case UniformType::UNIFORM_TYPE_SAMPLER: - break; + return String(); default: break; } - return ""; + + return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; } void VisualShaderNodeUniformRef::_set_uniform_type(int p_uniform_type) { @@ -2871,8 +3139,8 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "TANGENT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "BINORMAL" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "UV:xy" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "UV2:xy" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" }, @@ -2897,7 +3165,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "clearcoat", "CLEARCOAT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "clearcoat_gloss", "CLEARCOAT_GLOSS" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "anisotropy", "ANISOTROPY" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "anisotropy_flow", "ANISOTROPY_FLOW:xy" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "anisotropy_flow", "ANISOTROPY_FLOW" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "subsurf_scatter", "SSS_STRENGTH" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "backlight", "BACKLIGHT" }, @@ -2915,8 +3183,8 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { //////////////////////////////////////////////////////////////////////// // Canvas Item, Vertex. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "VERTEX:xy" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "UV:xy" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, @@ -2929,7 +3197,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "normal_map", "NORMAL_MAP" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "normal_map_depth", "NORMAL_MAP_DEPTH" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light_vertex", "LIGHT_VERTEX" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "shadow_vertex", "SHADOW_VERTEX:xy" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "shadow_vertex", "SHADOW_VERTEX" }, //////////////////////////////////////////////////////////////////////// // Canvas Item, Light. //////////////////////////////////////////////////////////////////////// @@ -3880,6 +4148,9 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad case PORT_TYPE_SCALAR_INT: tk = "0"; break; + case PORT_TYPE_VECTOR_2D: + tk = "vec2(0.0, 0.0)"; + break; case PORT_TYPE_VECTOR: tk = "vec3(0.0, 0.0, 0.0)"; break; diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index acb33efd30..9f877e08a5 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -214,6 +214,7 @@ public: enum PortType { PORT_TYPE_SCALAR, PORT_TYPE_SCALAR_INT, + PORT_TYPE_VECTOR_2D, PORT_TYPE_VECTOR, PORT_TYPE_BOOLEAN, PORT_TYPE_TRANSFORM, @@ -229,7 +230,7 @@ public: virtual PortType get_input_port_type(int p_port) const = 0; virtual String get_input_port_name(int p_port) const = 0; - virtual void set_input_port_default_value(int p_port, const Variant &p_value); + virtual void set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value = Variant()); Variant get_input_port_default_value(int p_port) const; // if NIL (default if node does not set anything) is returned, it means no default value is wanted if disconnected, thus no input var must be supplied (empty string will be supplied) Array get_default_input_values() const; virtual void set_default_input_values(const Array &p_values); @@ -311,7 +312,7 @@ protected: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual void set_input_port_default_value(int p_port, const Variant &p_value) override; + virtual void set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value = Variant()) override; virtual void set_default_input_values(const Array &p_values) override; virtual void remove_input_port_default_value(int p_port) override; virtual void clear_default_input_values() override; @@ -492,7 +493,8 @@ public: UNIFORM_TYPE_FLOAT, UNIFORM_TYPE_INT, UNIFORM_TYPE_BOOLEAN, - UNIFORM_TYPE_VECTOR, + UNIFORM_TYPE_VECTOR2, + UNIFORM_TYPE_VECTOR3, UNIFORM_TYPE_TRANSFORM, UNIFORM_TYPE_COLOR, UNIFORM_TYPE_SAMPLER, diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 9987408046..9a714fd3dd 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -30,6 +30,65 @@ #include "visual_shader_nodes.h" +////////////// Vector Base + +VisualShaderNodeVectorBase::PortType VisualShaderNodeVectorBase::get_input_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: + return PORT_TYPE_VECTOR; + default: + break; + } + return PORT_TYPE_SCALAR; +} + +VisualShaderNodeVectorBase::PortType VisualShaderNodeVectorBase::get_output_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: + return PORT_TYPE_VECTOR; + default: + break; + } + return PORT_TYPE_SCALAR; +} + +void VisualShaderNodeVectorBase::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + op_type = p_op_type; + emit_changed(); +} + +VisualShaderNodeVectorBase::OpType VisualShaderNodeVectorBase::get_op_type() const { + return op_type; +} + +void VisualShaderNodeVectorBase::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeVectorBase::set_op_type); + ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeVectorBase::get_op_type); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Vector2,Vector3"), "set_op_type", "get_op_type"); + + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D); + BIND_ENUM_CONSTANT(OP_TYPE_MAX); +} + +Vector<StringName> VisualShaderNodeVectorBase::get_editable_properties() const { + Vector<StringName> props; + props.push_back("op_type"); + return props; +} + +VisualShaderNodeVectorBase::VisualShaderNodeVectorBase() { +} + ////////////// Constants Base VisualShaderNodeConstant::VisualShaderNodeConstant() { @@ -294,10 +353,72 @@ void VisualShaderNodeColorConstant::_bind_methods() { VisualShaderNodeColorConstant::VisualShaderNodeColorConstant() { } -////////////// Vector +////////////// Vector2 + +String VisualShaderNodeVec2Constant::get_caption() const { + return "Vector2Constant"; +} + +int VisualShaderNodeVec2Constant::get_input_port_count() const { + return 0; +} + +VisualShaderNodeVec2Constant::PortType VisualShaderNodeVec2Constant::get_input_port_type(int p_port) const { + return PORT_TYPE_VECTOR_2D; +} + +String VisualShaderNodeVec2Constant::get_input_port_name(int p_port) const { + return String(); +} + +int VisualShaderNodeVec2Constant::get_output_port_count() const { + return 1; +} + +VisualShaderNodeVec2Constant::PortType VisualShaderNodeVec2Constant::get_output_port_type(int p_port) const { + return PORT_TYPE_VECTOR_2D; +} + +String VisualShaderNodeVec2Constant::get_output_port_name(int p_port) const { + return ""; //no output port means the editor will be used as port +} + +String VisualShaderNodeVec2Constant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + return " " + p_output_vars[0] + " = " + vformat("vec2(%.6f, %.6f)", constant.x, constant.y) + ";\n"; +} + +void VisualShaderNodeVec2Constant::set_constant(const Vector2 &p_constant) { + if (constant.is_equal_approx(p_constant)) { + return; + } + constant = p_constant; + emit_changed(); +} + +Vector2 VisualShaderNodeVec2Constant::get_constant() const { + return constant; +} + +Vector<StringName> VisualShaderNodeVec2Constant::get_editable_properties() const { + Vector<StringName> props; + props.push_back("constant"); + return props; +} + +void VisualShaderNodeVec2Constant::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_constant", "constant"), &VisualShaderNodeVec2Constant::set_constant); + ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeVec2Constant::get_constant); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant"), "set_constant", "get_constant"); +} + +VisualShaderNodeVec2Constant::VisualShaderNodeVec2Constant() { +} + +////////////// Vector3 String VisualShaderNodeVec3Constant::get_caption() const { - return "VectorConstant"; + return "Vector3Constant"; } int VisualShaderNodeVec3Constant::get_input_port_count() const { @@ -439,7 +560,7 @@ int VisualShaderNodeTexture::get_input_port_count() const { VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_input_port_type(int p_port) const { switch (p_port) { case 0: - return PORT_TYPE_VECTOR; + return PORT_TYPE_VECTOR_2D; case 1: return PORT_TYPE_SCALAR; case 2: @@ -529,7 +650,7 @@ String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShade String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String default_uv; if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { - default_uv = "UV.xy"; + default_uv = "UV"; } else { default_uv = "vec2(0.0)"; } @@ -547,9 +668,9 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; + code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; } else { - code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n"; @@ -575,9 +696,9 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; + code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; } else { - code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } code += " " + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n"; @@ -599,9 +720,9 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, 0.0);\n"; + code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", 0.0);\n"; } else { - code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } code += " " + p_output_vars[0] + " = _tex_read.rgb;\n"; @@ -622,9 +743,9 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ".xy);\n"; + code += " vec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ");\n"; } else { - code += " vec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } code += " " + p_output_vars[0] + " = _tex_read.rgb;\n"; @@ -1730,10 +1851,6 @@ int VisualShaderNodeVectorOp::get_input_port_count() const { return 2; } -VisualShaderNodeVectorOp::PortType VisualShaderNodeVectorOp::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeVectorOp::get_input_port_name(int p_port) const { return p_port == 0 ? "a" : "b"; } @@ -1742,12 +1859,8 @@ int VisualShaderNodeVectorOp::get_output_port_count() const { return 1; } -VisualShaderNodeVectorOp::PortType VisualShaderNodeVectorOp::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeVectorOp::get_output_port_name(int p_port) const { - return "op"; //no output port means the editor will be used as port + return "op"; } String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { @@ -1778,13 +1891,21 @@ String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; case OP_CROSS: - code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + if (op_type == OP_TYPE_VECTOR_2D) { // not supported + code += "vec2(0.0);\n"; + } else { + code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + } break; case OP_ATAN2: code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; case OP_REFLECT: - code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + if (op_type == OP_TYPE_VECTOR_2D) { // not supported + code += "vec2(0.0);\n"; + } else { + code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + } break; case OP_STEP: code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; @@ -1796,6 +1917,27 @@ String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader return code; } +void VisualShaderNodeVectorOp::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); + } break; + default: + break; + } + op_type = p_op_type; + emit_changed(); +} + void VisualShaderNodeVectorOp::set_operator(Operator p_op) { ERR_FAIL_INDEX(int(p_op), int(OP_ENUM_SIZE)); if (op == p_op) { @@ -1810,11 +1952,27 @@ VisualShaderNodeVectorOp::Operator VisualShaderNodeVectorOp::get_operator() cons } Vector<StringName> VisualShaderNodeVectorOp::get_editable_properties() const { - Vector<StringName> props; + Vector<StringName> props = VisualShaderNodeVectorBase::get_editable_properties(); props.push_back("operator"); return props; } +String VisualShaderNodeVectorOp::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { + bool invalid_type = false; + + if (op_type == OP_TYPE_VECTOR_2D) { + if (op == OP_CROSS || op == OP_REFLECT) { + invalid_type = true; + } + } + + if (invalid_type) { + return TTR("Invalid operator for that type."); + } + + return String(); +} + void VisualShaderNodeVectorOp::_bind_methods() { ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeVectorOp::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeVectorOp::get_operator); @@ -1837,8 +1995,18 @@ void VisualShaderNodeVectorOp::_bind_methods() { } VisualShaderNodeVectorOp::VisualShaderNodeVectorOp() { - set_input_port_default_value(0, Vector3()); - set_input_port_default_value(1, Vector3()); + switch (op_type) { + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2()); + set_input_port_default_value(1, Vector2()); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3()); + set_input_port_default_value(1, Vector3()); + } break; + default: + break; + } } ////////////// Color Op @@ -2412,10 +2580,6 @@ int VisualShaderNodeVectorFunc::get_input_port_count() const { return 1; } -VisualShaderNodeVectorFunc::PortType VisualShaderNodeVectorFunc::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeVectorFunc::get_input_port_name(int p_port) const { return ""; } @@ -2424,22 +2588,18 @@ int VisualShaderNodeVectorFunc::get_output_port_count() const { return 1; } -VisualShaderNodeVectorFunc::PortType VisualShaderNodeVectorFunc::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeVectorFunc::get_output_port_name(int p_port) const { - return ""; //no output port means the editor will be used as port + return "result"; } String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - static const char *vec_func_id[FUNC_MAX] = { + static const char *funcs[FUNC_MAX] = { "normalize($)", - "max(min($, vec3(1.0)), vec3(0.0))", + "", // FUNC_SATURATE "-($)", "1.0 / ($)", - "", - "", + "", // FUNC_RGB2HSV + "", // FUNC_HSV2RGB "abs($)", "acos($)", "acosh($)", @@ -2468,12 +2628,37 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad "tan($)", "tanh($)", "trunc($)", - "vec3(1.0, 1.0, 1.0) - $" + "" // FUNC_ONEMINUS }; + if (func == FUNC_SATURATE) { + String code; + + if (op_type == OP_TYPE_VECTOR_2D) { + code = "max(min($, vec2(1.0)), vec2(0.0))"; + } else { + code = "max(min($, vec3(1.0)), vec3(0.0))"; + } + return " " + p_output_vars[0] + " = " + code.replace("$", p_input_vars[0]) + ";\n"; + } + + if (func == FUNC_ONEMINUS) { + String code; + + if (op_type == OP_TYPE_VECTOR_2D) { + code = "vec2(1.0, 1.0) - $"; + } else { + code = "vec3(1.0, 1.0, 1.0) - $"; + } + return " " + p_output_vars[0] + " = " + code.replace("$", p_input_vars[0]) + ";\n"; + } + String code; if (func == FUNC_RGB2HSV) { + if (op_type == OP_TYPE_VECTOR_2D) { // not supported + return " " + p_output_vars[0] + " = vec2(0.0);\n"; + } code += " {\n"; code += " vec3 c = " + p_input_vars[0] + ";\n"; code += " vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"; @@ -2484,6 +2669,9 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad code += " " + p_output_vars[0] + " = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"; code += " }\n"; } else if (func == FUNC_HSV2RGB) { + if (op_type == OP_TYPE_VECTOR_2D) { // not supported + return " " + p_output_vars[0] + " = vec2(0.0);\n"; + } code += " {\n"; code += " vec3 c = " + p_input_vars[0] + ";\n"; code += " vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"; @@ -2492,12 +2680,31 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad code += " }\n"; } else { - code += " " + p_output_vars[0] + " = " + String(vec_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; + code += " " + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; } return code; } +void VisualShaderNodeVectorFunc::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + } break; + default: + break; + } + op_type = p_op_type; + emit_changed(); +} + void VisualShaderNodeVectorFunc::set_function(Function p_func) { ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); if (func == p_func) { @@ -2519,11 +2726,27 @@ VisualShaderNodeVectorFunc::Function VisualShaderNodeVectorFunc::get_function() } Vector<StringName> VisualShaderNodeVectorFunc::get_editable_properties() const { - Vector<StringName> props; + Vector<StringName> props = VisualShaderNodeVectorBase::get_editable_properties(); props.push_back("function"); return props; } +String VisualShaderNodeVectorFunc::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { + bool invalid_type = false; + + if (op_type == OP_TYPE_VECTOR_2D) { + if (func == FUNC_RGB2HSV || func == FUNC_HSV2RGB) { + invalid_type = true; + } + } + + if (invalid_type) { + return TTR("Invalid function for that type."); + } + + return String(); +} + void VisualShaderNodeVectorFunc::_bind_methods() { ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeVectorFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeVectorFunc::get_function); @@ -2569,7 +2792,16 @@ void VisualShaderNodeVectorFunc::_bind_methods() { } VisualShaderNodeVectorFunc::VisualShaderNodeVectorFunc() { - set_input_port_default_value(0, Vector3()); + switch (op_type) { + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2()); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3()); + } break; + default: + break; + } } ////////////// ColorFunc @@ -2754,11 +2986,11 @@ int VisualShaderNodeUVFunc::get_input_port_count() const { VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_input_port_type(int p_port) const { switch (p_port) { case 0: - [[fallthrough]]; // uv + return PORT_TYPE_VECTOR_2D; // uv case 1: - return PORT_TYPE_VECTOR; // scale + return PORT_TYPE_VECTOR_2D; // scale case 2: - return PORT_TYPE_VECTOR; // offset & pivot + return PORT_TYPE_VECTOR_2D; // offset & pivot default: break; } @@ -2801,7 +3033,7 @@ int VisualShaderNodeUVFunc::get_output_port_count() const { } VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; + return PORT_TYPE_VECTOR_2D; } String VisualShaderNodeUVFunc::get_output_port_name(int p_port) const { @@ -2818,9 +3050,9 @@ String VisualShaderNodeUVFunc::generate_code(Shader::Mode p_mode, VisualShader:: String uv; if (p_input_vars[0].is_empty()) { if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { - uv = "vec3(UV.xy, 0.0)"; + uv = "UV"; } else { - uv = "vec3(0.0)"; + uv = "vec2(0.0)"; } } else { uv = vformat("%s", p_input_vars[0]); @@ -2847,9 +3079,9 @@ void VisualShaderNodeUVFunc::set_function(VisualShaderNodeUVFunc::Function p_fun return; } if (p_func == FUNC_PANNING) { - set_input_port_default_value(2, Vector3()); // offset + set_input_port_default_value(2, Vector2()); // offset } else { // FUNC_SCALING - set_input_port_default_value(2, Vector3(0.5, 0.5, 0.0)); // pivot + set_input_port_default_value(2, Vector2(0.5, 0.5)); // pivot } func = p_func; emit_changed(); @@ -2877,8 +3109,8 @@ void VisualShaderNodeUVFunc::_bind_methods() { } VisualShaderNodeUVFunc::VisualShaderNodeUVFunc() { - set_input_port_default_value(1, Vector3(1.0, 1.0, 0.0)); // scale - set_input_port_default_value(2, Vector3()); // offset + set_input_port_default_value(1, Vector2(1.0, 1.0)); // scale + set_input_port_default_value(2, Vector2()); // offset } ////////////// Dot Product @@ -2930,10 +3162,6 @@ int VisualShaderNodeVectorLen::get_input_port_count() const { return 1; } -VisualShaderNodeVectorLen::PortType VisualShaderNodeVectorLen::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeVectorLen::get_input_port_name(int p_port) const { return ""; } @@ -2950,12 +3178,31 @@ String VisualShaderNodeVectorLen::get_output_port_name(int p_port) const { return "length"; } +void VisualShaderNodeVectorLen::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + } break; + default: + break; + } + op_type = p_op_type; + emit_changed(); +} + String VisualShaderNodeVectorLen::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { return " " + p_output_vars[0] + " = length(" + p_input_vars[0] + ");\n"; } VisualShaderNodeVectorLen::VisualShaderNodeVectorLen() { - set_input_port_default_value(0, Vector3()); + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); } ////////////// Determinant @@ -3007,8 +3254,13 @@ int VisualShaderNodeDerivativeFunc::get_input_port_count() const { } VisualShaderNodeDerivativeFunc::PortType VisualShaderNodeDerivativeFunc::get_input_port_type(int p_port) const { - if (op_type == OP_TYPE_VECTOR) { - return PORT_TYPE_VECTOR; + switch (op_type) { + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: + return PORT_TYPE_VECTOR; + default: + break; } return PORT_TYPE_SCALAR; } @@ -3022,8 +3274,13 @@ int VisualShaderNodeDerivativeFunc::get_output_port_count() const { } VisualShaderNodeDerivativeFunc::PortType VisualShaderNodeDerivativeFunc::get_output_port_type(int p_port) const { - if (op_type == OP_TYPE_VECTOR) { - return PORT_TYPE_VECTOR; + switch (op_type) { + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: + return PORT_TYPE_VECTOR; + default: + break; } return PORT_TYPE_SCALAR; } @@ -3050,12 +3307,15 @@ void VisualShaderNodeDerivativeFunc::set_op_type(OpType p_op_type) { return; } switch (p_op_type) { - case OP_TYPE_SCALAR: - set_input_port_default_value(0, 0.0); - break; - case OP_TYPE_VECTOR: - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); - break; + case OP_TYPE_SCALAR: { + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); + } break; + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + } break; default: break; } @@ -3094,11 +3354,12 @@ void VisualShaderNodeDerivativeFunc::_bind_methods() { ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeDerivativeFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeDerivativeFunc::get_function); - ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector"), "set_op_type", "get_op_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3"), "set_op_type", "get_op_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Sum,X,Y"), "set_function", "get_function"); BIND_ENUM_CONSTANT(OP_TYPE_SCALAR); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D); BIND_ENUM_CONSTANT(OP_TYPE_MAX); BIND_ENUM_CONSTANT(FUNC_SUM); @@ -3125,7 +3386,9 @@ VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_input_port_type(int p switch (op_type) { case OP_TYPE_INT: return PORT_TYPE_SCALAR_INT; - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; default: break; @@ -3152,7 +3415,9 @@ VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_output_port_type(int switch (op_type) { case OP_TYPE_INT: return PORT_TYPE_SCALAR_INT; - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; default: break; @@ -3175,19 +3440,24 @@ void VisualShaderNodeClamp::set_op_type(OpType p_op_type) { } switch (p_op_type) { case OP_TYPE_FLOAT: - set_input_port_default_value(0, 0.0); - set_input_port_default_value(1, 0.0); - set_input_port_default_value(2, 0.0); + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); + set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); + set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); break; case OP_TYPE_INT: - set_input_port_default_value(0, 0); - set_input_port_default_value(1, 0); - set_input_port_default_value(2, 0); + set_input_port_default_value(0, 0, get_input_port_default_value(0)); + set_input_port_default_value(1, 0, get_input_port_default_value(1)); + set_input_port_default_value(2, 0, get_input_port_default_value(2)); + break; + case OP_TYPE_VECTOR_2D: + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); + set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); break; - case OP_TYPE_VECTOR: - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); + case OP_TYPE_VECTOR_3D: + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); + set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); break; default: break; @@ -3210,11 +3480,12 @@ void VisualShaderNodeClamp::_bind_methods() { ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeClamp::set_op_type); ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeClamp::get_op_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector"), "set_op_type", "get_op_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3"), "set_op_type", "get_op_type"); BIND_ENUM_CONSTANT(OP_TYPE_FLOAT); BIND_ENUM_CONSTANT(OP_TYPE_INT); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D); BIND_ENUM_CONSTANT(OP_TYPE_MAX); } @@ -3234,10 +3505,6 @@ int VisualShaderNodeFaceForward::get_input_port_count() const { return 3; } -VisualShaderNodeFaceForward::PortType VisualShaderNodeFaceForward::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeFaceForward::get_input_port_name(int p_port) const { switch (p_port) { case 0: @@ -3255,14 +3522,33 @@ int VisualShaderNodeFaceForward::get_output_port_count() const { return 1; } -VisualShaderNodeFaceForward::PortType VisualShaderNodeFaceForward::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeFaceForward::get_output_port_name(int p_port) const { return ""; } +void VisualShaderNodeFaceForward::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); + set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); + set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); + } break; + default: + break; + } + op_type = p_op_type; + emit_changed(); +} + String VisualShaderNodeFaceForward::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { return " " + p_output_vars[0] + " = faceforward(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } @@ -3331,9 +3617,16 @@ int VisualShaderNodeStep::get_input_port_count() const { VisualShaderNodeStep::PortType VisualShaderNodeStep::get_input_port_type(int p_port) const { switch (op_type) { - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_2D_SCALAR: + if (p_port == 1) { + return PORT_TYPE_VECTOR_2D; + } + break; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; - case OP_TYPE_VECTOR_SCALAR: + case OP_TYPE_VECTOR_3D_SCALAR: if (p_port == 1) { return PORT_TYPE_VECTOR; } @@ -3345,12 +3638,13 @@ VisualShaderNodeStep::PortType VisualShaderNodeStep::get_input_port_type(int p_p } String VisualShaderNodeStep::get_input_port_name(int p_port) const { - if (p_port == 0) { - return "edge"; - } else if (p_port == 1) { - return "x"; + switch (p_port) { + case 0: + return "edge"; + case 1: + return "x"; } - return ""; + return String(); } int VisualShaderNodeStep::get_output_port_count() const { @@ -3359,9 +3653,13 @@ int VisualShaderNodeStep::get_output_port_count() const { VisualShaderNodeStep::PortType VisualShaderNodeStep::get_output_port_type(int p_port) const { switch (op_type) { - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_2D_SCALAR: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; - case OP_TYPE_VECTOR_SCALAR: + case OP_TYPE_VECTOR_3D_SCALAR: return PORT_TYPE_VECTOR; default: break; @@ -3379,30 +3677,26 @@ void VisualShaderNodeStep::set_op_type(OpType p_op_type) { return; } switch (p_op_type) { - case OP_TYPE_SCALAR: - if (op_type == OP_TYPE_VECTOR) { - set_input_port_default_value(0, 0.0); // edge - } - if (op_type == OP_TYPE_VECTOR || op_type == OP_TYPE_VECTOR_SCALAR) { - set_input_port_default_value(1, 0.0); // x - } - break; - case OP_TYPE_VECTOR: - if (op_type == OP_TYPE_SCALAR || op_type == OP_TYPE_VECTOR_SCALAR) { - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // edge - } - if (op_type == OP_TYPE_SCALAR) { - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // x - } - break; - case OP_TYPE_VECTOR_SCALAR: - if (op_type == OP_TYPE_VECTOR) { - set_input_port_default_value(0, 0.0); // edge - } - if (op_type == OP_TYPE_SCALAR) { - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // x - } - break; + case OP_TYPE_SCALAR: { + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); + set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); + } break; + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); + } break; + case OP_TYPE_VECTOR_2D_SCALAR: { + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); + } break; + case OP_TYPE_VECTOR_3D_SCALAR: { + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); + } break; default: break; } @@ -3428,11 +3722,13 @@ void VisualShaderNodeStep::_bind_methods() { ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeStep::set_op_type); ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeStep::get_op_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector,VectorScalar"), "set_op_type", "get_op_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar"), "set_op_type", "get_op_type"); BIND_ENUM_CONSTANT(OP_TYPE_SCALAR); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D_SCALAR); BIND_ENUM_CONSTANT(OP_TYPE_MAX); } @@ -3453,9 +3749,16 @@ int VisualShaderNodeSmoothStep::get_input_port_count() const { VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_input_port_type(int p_port) const { switch (op_type) { - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_2D_SCALAR: + if (p_port == 2) { + return PORT_TYPE_VECTOR_2D; // x + } + break; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; - case OP_TYPE_VECTOR_SCALAR: + case OP_TYPE_VECTOR_3D_SCALAR: if (p_port == 2) { return PORT_TYPE_VECTOR; // x } @@ -3467,14 +3770,15 @@ VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_input_port_ } String VisualShaderNodeSmoothStep::get_input_port_name(int p_port) const { - if (p_port == 0) { - return "edge0"; - } else if (p_port == 1) { - return "edge1"; - } else if (p_port == 2) { - return "x"; + switch (p_port) { + case 0: + return "edge0"; + case 1: + return "edge1"; + case 2: + return "x"; } - return ""; + return String(); } int VisualShaderNodeSmoothStep::get_output_port_count() const { @@ -3483,9 +3787,13 @@ int VisualShaderNodeSmoothStep::get_output_port_count() const { VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_output_port_type(int p_port) const { switch (op_type) { - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_2D_SCALAR: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; - case OP_TYPE_VECTOR_SCALAR: + case OP_TYPE_VECTOR_3D_SCALAR: return PORT_TYPE_VECTOR; default: break; @@ -3504,31 +3812,29 @@ void VisualShaderNodeSmoothStep::set_op_type(OpType p_op_type) { } switch (p_op_type) { case OP_TYPE_SCALAR: - if (op_type == OP_TYPE_VECTOR) { - set_input_port_default_value(0, 0.0); // edge0 - set_input_port_default_value(1, 0.0); // edge1 - } - if (op_type == OP_TYPE_VECTOR || op_type == OP_TYPE_VECTOR_SCALAR) { - set_input_port_default_value(2, 0.0); // x - } - break; - case OP_TYPE_VECTOR: - if (op_type == OP_TYPE_SCALAR || op_type == OP_TYPE_VECTOR_SCALAR) { - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // edge0 - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // edge1 - } - if (op_type == OP_TYPE_SCALAR) { - set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); // x - } - break; - case OP_TYPE_VECTOR_SCALAR: - if (op_type == OP_TYPE_VECTOR) { - set_input_port_default_value(0, 0.0); // edge0 - set_input_port_default_value(1, 0.0); // edge1 - } - if (op_type == OP_TYPE_SCALAR) { - set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); // x - } + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); // edge0 + set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // edge1 + set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // x + break; + case OP_TYPE_VECTOR_2D: + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); // edge0 + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); // edge1 + set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); // x + break; + case OP_TYPE_VECTOR_2D_SCALAR: + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); // edge0 + set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // edge1 + set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); // x + break; + case OP_TYPE_VECTOR_3D: + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); // edge0 + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // edge1 + set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); // x + break; + case OP_TYPE_VECTOR_3D_SCALAR: + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); // edge0 + set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // edge1 + set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); // x break; default: break; @@ -3555,18 +3861,20 @@ void VisualShaderNodeSmoothStep::_bind_methods() { ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeSmoothStep::set_op_type); ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeSmoothStep::get_op_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector,VectorScalar"), "set_op_type", "get_op_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar"), "set_op_type", "get_op_type"); BIND_ENUM_CONSTANT(OP_TYPE_SCALAR); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D_SCALAR); BIND_ENUM_CONSTANT(OP_TYPE_MAX); } VisualShaderNodeSmoothStep::VisualShaderNodeSmoothStep() { - set_input_port_default_value(0, 0.0); - set_input_port_default_value(1, 0.0); - set_input_port_default_value(2, 0.0); + set_input_port_default_value(0, 0.0); // edge0 + set_input_port_default_value(1, 1.0); // edge1 + set_input_port_default_value(2, 0.5); // x } ////////////// Distance @@ -3579,17 +3887,14 @@ int VisualShaderNodeVectorDistance::get_input_port_count() const { return 2; } -VisualShaderNodeVectorDistance::PortType VisualShaderNodeVectorDistance::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeVectorDistance::get_input_port_name(int p_port) const { - if (p_port == 0) { - return "p0"; - } else if (p_port == 1) { - return "p1"; + switch (p_port) { + case 0: + return "a"; + case 1: + return "b"; } - return ""; + return String(); } int VisualShaderNodeVectorDistance::get_output_port_count() const { @@ -3604,13 +3909,34 @@ String VisualShaderNodeVectorDistance::get_output_port_name(int p_port) const { return ""; } +void VisualShaderNodeVectorDistance::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); // a + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); // b + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); // a + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // b + } break; + default: + break; + } + op_type = p_op_type; + emit_changed(); +} + String VisualShaderNodeVectorDistance::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { return " " + p_output_vars[0] + " = distance(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } VisualShaderNodeVectorDistance::VisualShaderNodeVectorDistance() { - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // a + set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // b } ////////////// Refract Vector @@ -3632,14 +3958,15 @@ VisualShaderNodeVectorRefract::PortType VisualShaderNodeVectorRefract::get_input } String VisualShaderNodeVectorRefract::get_input_port_name(int p_port) const { - if (p_port == 0) { - return "I"; - } else if (p_port == 1) { - return "N"; - } else if (p_port == 2) { - return "eta"; + switch (p_port) { + case 0: + return "I"; + case 1: + return "N"; + case 2: + return "eta"; } - return ""; + return String(); } int VisualShaderNodeVectorRefract::get_output_port_count() const { @@ -3676,9 +4003,16 @@ int VisualShaderNodeMix::get_input_port_count() const { VisualShaderNodeMix::PortType VisualShaderNodeMix::get_input_port_type(int p_port) const { switch (op_type) { - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_2D_SCALAR: + if (p_port == 2) { + break; + } + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; - case OP_TYPE_VECTOR_SCALAR: + case OP_TYPE_VECTOR_3D_SCALAR: if (p_port == 2) { break; } @@ -3705,9 +4039,13 @@ int VisualShaderNodeMix::get_output_port_count() const { VisualShaderNodeMix::PortType VisualShaderNodeMix::get_output_port_type(int p_port) const { switch (op_type) { - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_2D_SCALAR: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; - case OP_TYPE_VECTOR_SCALAR: + case OP_TYPE_VECTOR_3D_SCALAR: return PORT_TYPE_VECTOR; default: break; @@ -3725,27 +4063,31 @@ void VisualShaderNodeMix::set_op_type(OpType p_op_type) { return; } switch (p_op_type) { - case OP_TYPE_SCALAR: - set_input_port_default_value(0, 0.0); // a - set_input_port_default_value(1, 1.0); // b - if (op_type == OP_TYPE_VECTOR) { - set_input_port_default_value(2, 0.5); // weight - } - break; - case OP_TYPE_VECTOR: - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // a - set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); // b - if (op_type == OP_TYPE_SCALAR || op_type == OP_TYPE_VECTOR_SCALAR) { - set_input_port_default_value(2, Vector3(0.5, 0.5, 0.5)); // weight - } - break; - case OP_TYPE_VECTOR_SCALAR: - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // a - set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); // b - if (op_type == OP_TYPE_VECTOR) { - set_input_port_default_value(2, 0.5); // weight - } - break; + case OP_TYPE_SCALAR: { + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); // a + set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // b + set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // weight + } break; + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); // a + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); // b + set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); // weight + } break; + case OP_TYPE_VECTOR_2D_SCALAR: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); // a + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); // b + set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // weight + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); // a + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // b + set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); // weight + } break; + case OP_TYPE_VECTOR_3D_SCALAR: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); // a + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // b + set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // weight + } break; default: break; } @@ -3771,11 +4113,13 @@ void VisualShaderNodeMix::_bind_methods() { ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeMix::set_op_type); ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeMix::get_op_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector,VectorScalar"), "set_op_type", "get_op_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar"), "set_op_type", "get_op_type"); BIND_ENUM_CONSTANT(OP_TYPE_SCALAR); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D_SCALAR); BIND_ENUM_CONSTANT(OP_TYPE_MAX); } @@ -3792,7 +4136,15 @@ String VisualShaderNodeVectorCompose::get_caption() const { } int VisualShaderNodeVectorCompose::get_input_port_count() const { - return 3; + switch (op_type) { + case OP_TYPE_VECTOR_2D: + return 2; + case OP_TYPE_VECTOR_3D: + return 3; + default: + break; + } + return 0; } VisualShaderNodeVectorCompose::PortType VisualShaderNodeVectorCompose::get_input_port_type(int p_port) const { @@ -3800,29 +4152,80 @@ VisualShaderNodeVectorCompose::PortType VisualShaderNodeVectorCompose::get_input } String VisualShaderNodeVectorCompose::get_input_port_name(int p_port) const { - if (p_port == 0) { - return "x"; - } else if (p_port == 1) { - return "y"; - } else { - return "z"; + switch (op_type) { + case OP_TYPE_VECTOR_2D: { + switch (p_port) { + case 0: + return "x"; + case 1: + return "y"; + } + } break; + case OP_TYPE_VECTOR_3D: { + switch (p_port) { + case 0: + return "x"; + case 1: + return "y"; + case 2: + return "z"; + } + } break; + default: + break; } + return String(); } int VisualShaderNodeVectorCompose::get_output_port_count() const { return 1; } -VisualShaderNodeVectorCompose::PortType VisualShaderNodeVectorCompose::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeVectorCompose::get_output_port_name(int p_port) const { return "vec"; } +void VisualShaderNodeVectorCompose::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_VECTOR_2D: { + float p1 = get_input_port_default_value(0); + float p2 = get_input_port_default_value(1); + + set_input_port_default_value(0, p1); + set_input_port_default_value(1, p2); + } break; + case OP_TYPE_VECTOR_3D: { + float p1 = get_input_port_default_value(0); + float p2 = get_input_port_default_value(1); + + set_input_port_default_value(0, p1); + set_input_port_default_value(1, p2); + set_input_port_default_value(2, 0.0); + } break; + default: + break; + } + op_type = p_op_type; + emit_changed(); +} + String VisualShaderNodeVectorCompose::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { - return " " + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + String code; + switch (op_type) { + case OP_TYPE_VECTOR_2D: { + code += " " + p_output_vars[0] + " = vec2(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + } break; + case OP_TYPE_VECTOR_3D: { + code += " " + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + } break; + default: + break; + } + return code; } VisualShaderNodeVectorCompose::VisualShaderNodeVectorCompose() { @@ -3889,16 +4292,20 @@ int VisualShaderNodeVectorDecompose::get_input_port_count() const { return 1; } -VisualShaderNodeVectorDecompose::PortType VisualShaderNodeVectorDecompose::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - String VisualShaderNodeVectorDecompose::get_input_port_name(int p_port) const { return "vec"; } int VisualShaderNodeVectorDecompose::get_output_port_count() const { - return 3; + switch (op_type) { + case OP_TYPE_VECTOR_2D: + return 2; + case OP_TYPE_VECTOR_3D: + return 3; + default: + break; + } + return 0; } VisualShaderNodeVectorDecompose::PortType VisualShaderNodeVectorDecompose::get_output_port_type(int p_port) const { @@ -3906,25 +4313,70 @@ VisualShaderNodeVectorDecompose::PortType VisualShaderNodeVectorDecompose::get_o } String VisualShaderNodeVectorDecompose::get_output_port_name(int p_port) const { - if (p_port == 0) { - return "x"; - } else if (p_port == 1) { - return "y"; - } else { - return "z"; + switch (op_type) { + case OP_TYPE_VECTOR_2D: { + switch (p_port) { + case 0: + return "x"; + case 1: + return "y"; + } + } break; + case OP_TYPE_VECTOR_3D: { + switch (p_port) { + case 0: + return "x"; + case 1: + return "y"; + case 2: + return "z"; + } + } break; + default: + break; + } + return String(); +} + +void VisualShaderNodeVectorDecompose::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + } break; + default: + break; } + op_type = p_op_type; + emit_changed(); } String VisualShaderNodeVectorDecompose::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; - code += " " + p_output_vars[0] + " = " + p_input_vars[0] + ".x;\n"; - code += " " + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n"; - code += " " + p_output_vars[2] + " = " + p_input_vars[0] + ".z;\n"; + switch (op_type) { + case OP_TYPE_VECTOR_2D: { + code += " " + p_output_vars[0] + " = " + p_input_vars[0] + ".x;\n"; + code += " " + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n"; + } break; + case OP_TYPE_VECTOR_3D: { + code += " " + p_output_vars[0] + " = " + p_input_vars[0] + ".x;\n"; + code += " " + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n"; + code += " " + p_output_vars[2] + " = " + p_input_vars[0] + ".z;\n"; + } break; + default: + break; + } return code; } VisualShaderNodeVectorDecompose::VisualShaderNodeVectorDecompose() { - set_input_port_default_value(0, Vector3()); + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); } ////////////// Transform Decompose @@ -4574,10 +5026,110 @@ Vector<StringName> VisualShaderNodeColorUniform::get_editable_properties() const VisualShaderNodeColorUniform::VisualShaderNodeColorUniform() { } -////////////// Vector Uniform +////////////// Vector2 Uniform + +String VisualShaderNodeVec2Uniform::get_caption() const { + return "Vector2Uniform"; +} + +int VisualShaderNodeVec2Uniform::get_input_port_count() const { + return 0; +} + +VisualShaderNodeVec2Uniform::PortType VisualShaderNodeVec2Uniform::get_input_port_type(int p_port) const { + return PORT_TYPE_VECTOR_2D; +} + +String VisualShaderNodeVec2Uniform::get_input_port_name(int p_port) const { + return String(); +} + +int VisualShaderNodeVec2Uniform::get_output_port_count() const { + return 1; +} + +VisualShaderNodeVec2Uniform::PortType VisualShaderNodeVec2Uniform::get_output_port_type(int p_port) const { + return PORT_TYPE_VECTOR_2D; +} + +String VisualShaderNodeVec2Uniform::get_output_port_name(int p_port) const { + return String(); +} + +void VisualShaderNodeVec2Uniform::set_default_value_enabled(bool p_enabled) { + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeVec2Uniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeVec2Uniform::set_default_value(const Vector2 &p_value) { + default_value = p_value; + emit_changed(); +} + +Vector2 VisualShaderNodeVec2Uniform::get_default_value() const { + return default_value; +} + +String VisualShaderNodeVec2Uniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform vec2 " + get_uniform_name(); + if (default_value_enabled) { + code += vformat(" = vec2(%.6f, %.6f)", default_value.x, default_value.y); + } + code += ";\n"; + return code; +} + +String VisualShaderNodeVec2Uniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; +} + +void VisualShaderNodeVec2Uniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec2Uniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec2Uniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec2Uniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec2Uniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "default_value"), "set_default_value", "get_default_value"); +} + +bool VisualShaderNodeVec2Uniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeVec2Uniform::is_use_prop_slots() const { + return true; +} + +bool VisualShaderNodeVec2Uniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +bool VisualShaderNodeVec2Uniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + +Vector<StringName> VisualShaderNodeVec2Uniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; +} + +VisualShaderNodeVec2Uniform::VisualShaderNodeVec2Uniform() { +} + +////////////// Vector3 Uniform String VisualShaderNodeVec3Uniform::get_caption() const { - return "VectorUniform"; + return "Vector3Uniform"; } int VisualShaderNodeVec3Uniform::get_input_port_count() const { @@ -4792,7 +5344,7 @@ int VisualShaderNodeTextureUniform::get_input_port_count() const { } VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_input_port_type(int p_port) const { - return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR; + return p_port == 0 ? PORT_TYPE_VECTOR_2D : PORT_TYPE_SCALAR; } String VisualShaderNodeTextureUniform::get_input_port_name(int p_port) const { @@ -4940,7 +5492,7 @@ bool VisualShaderNodeTextureUniform::is_code_generated() const { String VisualShaderNodeTextureUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String default_uv; if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { - default_uv = "UV.xy"; + default_uv = "UV"; } else { default_uv = "vec2(0.0)"; } @@ -4955,9 +5507,9 @@ String VisualShaderNodeTextureUniform::generate_code(Shader::Mode p_mode, Visual } } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; + code += " vec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; } else { - code += " vec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } code += " " + p_output_vars[0] + " = n_tex_read.rgb;\n"; @@ -5523,7 +6075,9 @@ VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_input_port_type(int switch (op_type) { case OP_TYPE_INT: return PORT_TYPE_SCALAR_INT; - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; case OP_TYPE_BOOLEAN: return PORT_TYPE_BOOLEAN; @@ -5557,7 +6111,9 @@ VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_output_port_type(in switch (op_type) { case OP_TYPE_INT: return PORT_TYPE_SCALAR_INT; - case OP_TYPE_VECTOR: + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR; case OP_TYPE_BOOLEAN: return PORT_TYPE_BOOLEAN; @@ -5580,16 +6136,20 @@ void VisualShaderNodeSwitch::set_op_type(OpType p_op_type) { } switch (p_op_type) { case OP_TYPE_FLOAT: - set_input_port_default_value(1, 1.0); - set_input_port_default_value(2, 0.0); + set_input_port_default_value(1, 1.0, get_input_port_default_value(1)); + set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); break; case OP_TYPE_INT: - set_input_port_default_value(1, 1); - set_input_port_default_value(2, 0); + set_input_port_default_value(1, 1, get_input_port_default_value(1)); + set_input_port_default_value(2, 0, get_input_port_default_value(2)); break; - case OP_TYPE_VECTOR: - set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); - set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); + case OP_TYPE_VECTOR_2D: + set_input_port_default_value(1, Vector2(1.0, 1.0), get_input_port_default_value(1)); + set_input_port_default_value(2, Vector2(0.0, 0.0), get_input_port_default_value(2)); + break; + case OP_TYPE_VECTOR_3D: + set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0), get_input_port_default_value(1)); + set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0), get_input_port_default_value(2)); break; case OP_TYPE_BOOLEAN: set_input_port_default_value(1, true); @@ -5620,11 +6180,12 @@ void VisualShaderNodeSwitch::_bind_methods() { // static ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeSwitch::set_op_type); ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeSwitch::get_op_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector,Boolean,Transform"), "set_op_type", "get_op_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Boolean,Transform"), "set_op_type", "get_op_type"); BIND_ENUM_CONSTANT(OP_TYPE_FLOAT); BIND_ENUM_CONSTANT(OP_TYPE_INT); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D); BIND_ENUM_CONSTANT(OP_TYPE_BOOLEAN); BIND_ENUM_CONSTANT(OP_TYPE_TRANSFORM); BIND_ENUM_CONSTANT(OP_TYPE_MAX); @@ -5854,7 +6415,9 @@ VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(i return PORT_TYPE_SCALAR; case CTYPE_SCALAR_INT: return PORT_TYPE_SCALAR_INT; - case CTYPE_VECTOR: + case CTYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case CTYPE_VECTOR_3D: return PORT_TYPE_VECTOR; case CTYPE_BOOLEAN: return PORT_TYPE_BOOLEAN; @@ -5926,7 +6489,7 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: String code; switch (comparison_type) { - case CTYPE_SCALAR: + case CTYPE_SCALAR: { if (func == FUNC_EQUAL) { code += " " + p_output_vars[0] + " = (abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");"; } else if (func == FUNC_NOT_EQUAL) { @@ -5934,33 +6497,34 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: } else { code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n"; } - break; - - case CTYPE_SCALAR_INT: + } break; + case CTYPE_SCALAR_INT: { code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n"; - break; - - case CTYPE_VECTOR: + } break; + case CTYPE_VECTOR_2D: { + code += " {\n"; + code += " bvec2 _bv = " + String(functions[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n"; + code += " " + p_output_vars[0] + " = " + String(conditions[condition]).replace("$", "_bv") + ";\n"; + code += " }\n"; + } break; + case CTYPE_VECTOR_3D: { code += " {\n"; code += " bvec3 _bv = " + String(functions[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n"; code += " " + p_output_vars[0] + " = " + String(conditions[condition]).replace("$", "_bv") + ";\n"; code += " }\n"; - break; - - case CTYPE_BOOLEAN: + } break; + case CTYPE_BOOLEAN: { if (func > FUNC_NOT_EQUAL) { return " " + p_output_vars[0] + " = false;\n"; } code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n"; - break; - - case CTYPE_TRANSFORM: + } break; + case CTYPE_TRANSFORM: { if (func > FUNC_NOT_EQUAL) { return " " + p_output_vars[0] + " = false;\n"; } code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n"; - break; - + } break; default: break; } @@ -5974,18 +6538,23 @@ void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_comparison_ty } switch (p_comparison_type) { case CTYPE_SCALAR: - set_input_port_default_value(0, 0.0); - set_input_port_default_value(1, 0.0); + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); + set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); simple_decl = true; break; case CTYPE_SCALAR_INT: - set_input_port_default_value(0, 0); - set_input_port_default_value(1, 0); + set_input_port_default_value(0, 0, get_input_port_default_value(0)); + set_input_port_default_value(1, 0, get_input_port_default_value(1)); simple_decl = true; break; - case CTYPE_VECTOR: - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); + case CTYPE_VECTOR_2D: + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); + simple_decl = false; + break; + case CTYPE_VECTOR_3D: + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); simple_decl = false; break; case CTYPE_BOOLEAN: @@ -6039,7 +6608,7 @@ Vector<StringName> VisualShaderNodeCompare::get_editable_properties() const { Vector<StringName> props; props.push_back("type"); props.push_back("function"); - if (comparison_type == CTYPE_VECTOR) { + if (comparison_type == CTYPE_VECTOR_2D || comparison_type == CTYPE_VECTOR_3D) { props.push_back("condition"); } return props; @@ -6055,13 +6624,14 @@ void VisualShaderNodeCompare::_bind_methods() { ClassDB::bind_method(D_METHOD("set_condition", "condition"), &VisualShaderNodeCompare::set_condition); ClassDB::bind_method(D_METHOD("get_condition"), &VisualShaderNodeCompare::get_condition); - ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Float,Int,Vector,Boolean,Transform"), "set_comparison_type", "get_comparison_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Boolean,Transform"), "set_comparison_type", "get_comparison_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "a == b,a != b,a > b,a >= b,a < b,a <= b"), "set_function", "get_function"); ADD_PROPERTY(PropertyInfo(Variant::INT, "condition", PROPERTY_HINT_ENUM, "All,Any"), "set_condition", "get_condition"); BIND_ENUM_CONSTANT(CTYPE_SCALAR); BIND_ENUM_CONSTANT(CTYPE_SCALAR_INT); - BIND_ENUM_CONSTANT(CTYPE_VECTOR); + BIND_ENUM_CONSTANT(CTYPE_VECTOR_2D); + BIND_ENUM_CONSTANT(CTYPE_VECTOR_3D); BIND_ENUM_CONSTANT(CTYPE_BOOLEAN); BIND_ENUM_CONSTANT(CTYPE_TRANSFORM); BIND_ENUM_CONSTANT(CTYPE_MAX); @@ -6096,8 +6666,13 @@ int VisualShaderNodeMultiplyAdd::get_input_port_count() const { } VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_input_port_type(int p_port) const { - if (op_type == OP_TYPE_VECTOR) { - return PORT_TYPE_VECTOR; + switch (op_type) { + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: + return PORT_TYPE_VECTOR; + default: + break; } return PORT_TYPE_SCALAR; } @@ -6118,11 +6693,15 @@ int VisualShaderNodeMultiplyAdd::get_output_port_count() const { } VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_output_port_type(int p_port) const { - if (op_type == OP_TYPE_SCALAR) { - return PORT_TYPE_SCALAR; - } else { - return PORT_TYPE_VECTOR; + switch (op_type) { + case OP_TYPE_VECTOR_2D: + return PORT_TYPE_VECTOR_2D; + case OP_TYPE_VECTOR_3D: + return PORT_TYPE_VECTOR; + default: + break; } + return PORT_TYPE_SCALAR; } String VisualShaderNodeMultiplyAdd::get_output_port_name(int p_port) const { @@ -6139,16 +6718,21 @@ void VisualShaderNodeMultiplyAdd::set_op_type(OpType p_op_type) { return; } switch (p_op_type) { - case OP_TYPE_SCALAR: - set_input_port_default_value(0, 0.0); - set_input_port_default_value(1, 0.0); - set_input_port_default_value(2, 0.0); - break; - case OP_TYPE_VECTOR: - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); - break; + case OP_TYPE_SCALAR: { + set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); + set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); + set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); + } break; + case OP_TYPE_VECTOR_2D: { + set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); + set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); + } break; + case OP_TYPE_VECTOR_3D: { + set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); + set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); + } break; default: break; } @@ -6170,10 +6754,11 @@ void VisualShaderNodeMultiplyAdd::_bind_methods() { ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeMultiplyAdd::set_op_type); ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeMultiplyAdd::get_op_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector"), "set_op_type", "get_op_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3"), "set_op_type", "get_op_type"); BIND_ENUM_CONSTANT(OP_TYPE_SCALAR); - BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D); BIND_ENUM_CONSTANT(OP_TYPE_MAX); } diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 16f916f240..5c7a674d34 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -34,6 +34,49 @@ #include "scene/resources/visual_shader.h" /////////////////////////////////////// +/// Vector Base Node +/////////////////////////////////////// + +class VisualShaderNodeVectorBase : public VisualShaderNode { + GDCLASS(VisualShaderNodeVectorBase, VisualShaderNode); + +public: + enum OpType { + OP_TYPE_VECTOR_2D, + OP_TYPE_VECTOR_3D, + OP_TYPE_MAX, + }; + +protected: + OpType op_type = OP_TYPE_VECTOR_3D; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override = 0; + + virtual int get_input_port_count() const override = 0; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override = 0; + + virtual int get_output_port_count() const override = 0; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override = 0; + + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override = 0; + + virtual void set_op_type(OpType p_op_type); + OpType get_op_type() const; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeVectorBase(); +}; + +VARIANT_ENUM_CAST(VisualShaderNodeVectorBase::OpType) + +/////////////////////////////////////// /// CONSTANTS /////////////////////////////////////// @@ -177,6 +220,36 @@ public: /////////////////////////////////////// +class VisualShaderNodeVec2Constant : public VisualShaderNodeConstant { + GDCLASS(VisualShaderNodeVec2Constant, VisualShaderNodeConstant); + Vector2 constant; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + + void set_constant(const Vector2 &p_constant); + Vector2 get_constant() const; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeVec2Constant(); +}; + +/////////////////////////////////////// + class VisualShaderNodeVec3Constant : public VisualShaderNodeConstant { GDCLASS(VisualShaderNodeVec3Constant, VisualShaderNodeConstant); Vector3 constant; @@ -615,8 +688,8 @@ public: VARIANT_ENUM_CAST(VisualShaderNodeIntOp::Operator) -class VisualShaderNodeVectorOp : public VisualShaderNode { - GDCLASS(VisualShaderNodeVectorOp, VisualShaderNode); +class VisualShaderNodeVectorOp : public VisualShaderNodeVectorBase { + GDCLASS(VisualShaderNodeVectorOp, VisualShaderNodeVectorBase); public: enum Operator { @@ -644,19 +717,20 @@ public: virtual String get_caption() const override; virtual int get_input_port_count() const override; - virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; virtual int get_output_port_count() const override; - virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual void set_op_type(OpType p_op_type) override; + void set_operator(Operator p_op); Operator get_operator() const; virtual Vector<StringName> get_editable_properties() const override; + String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; VisualShaderNodeVectorOp(); }; @@ -923,8 +997,10 @@ VARIANT_ENUM_CAST(VisualShaderNodeIntFunc::Function) /// VECTOR FUNC /////////////////////////////////////// -class VisualShaderNodeVectorFunc : public VisualShaderNode { - GDCLASS(VisualShaderNodeVectorFunc, VisualShaderNode); +class VisualShaderNodeVectorFunc : public VisualShaderNodeVectorBase { + GDCLASS(VisualShaderNodeVectorFunc, VisualShaderNodeVectorBase); + + void _update_default_input_values(); public: enum Function { @@ -975,19 +1051,20 @@ public: virtual String get_caption() const override; virtual int get_input_port_count() const override; - virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; virtual int get_output_port_count() const override; - virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual void set_op_type(OpType p_op_type) override; + void set_function(Function p_func); Function get_function() const; virtual Vector<StringName> get_editable_properties() const override; + String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; VisualShaderNodeVectorFunc(); }; @@ -1150,20 +1227,20 @@ public: /// LENGTH /////////////////////////////////////// -class VisualShaderNodeVectorLen : public VisualShaderNode { - GDCLASS(VisualShaderNodeVectorLen, VisualShaderNode); +class VisualShaderNodeVectorLen : public VisualShaderNodeVectorBase { + GDCLASS(VisualShaderNodeVectorLen, VisualShaderNodeVectorBase); public: virtual String get_caption() const override; virtual int get_input_port_count() const override; - virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + virtual void set_op_type(OpType p_op_type) override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVectorLen(); @@ -1203,7 +1280,8 @@ public: enum OpType { OP_TYPE_FLOAT, OP_TYPE_INT, - OP_TYPE_VECTOR, + OP_TYPE_VECTOR_2D, + OP_TYPE_VECTOR_3D, OP_TYPE_MAX, }; @@ -1244,7 +1322,8 @@ class VisualShaderNodeDerivativeFunc : public VisualShaderNode { public: enum OpType { OP_TYPE_SCALAR, - OP_TYPE_VECTOR, + OP_TYPE_VECTOR_2D, + OP_TYPE_VECTOR_3D, OP_TYPE_MAX, }; @@ -1293,20 +1372,19 @@ VARIANT_ENUM_CAST(VisualShaderNodeDerivativeFunc::Function) /// FACEFORWARD /////////////////////////////////////// -class VisualShaderNodeFaceForward : public VisualShaderNode { - GDCLASS(VisualShaderNodeFaceForward, VisualShaderNode); +class VisualShaderNodeFaceForward : public VisualShaderNodeVectorBase { + GDCLASS(VisualShaderNodeFaceForward, VisualShaderNodeVectorBase); public: virtual String get_caption() const override; virtual int get_input_port_count() const override; - virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; virtual int get_output_port_count() const override; - virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + virtual void set_op_type(OpType p_op_type) override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeFaceForward(); @@ -1345,8 +1423,10 @@ class VisualShaderNodeStep : public VisualShaderNode { public: enum OpType { OP_TYPE_SCALAR, - OP_TYPE_VECTOR, - OP_TYPE_VECTOR_SCALAR, + OP_TYPE_VECTOR_2D, + OP_TYPE_VECTOR_2D_SCALAR, + OP_TYPE_VECTOR_3D, + OP_TYPE_VECTOR_3D_SCALAR, OP_TYPE_MAX, }; @@ -1387,8 +1467,10 @@ class VisualShaderNodeSmoothStep : public VisualShaderNode { public: enum OpType { OP_TYPE_SCALAR, - OP_TYPE_VECTOR, - OP_TYPE_VECTOR_SCALAR, + OP_TYPE_VECTOR_2D, + OP_TYPE_VECTOR_2D_SCALAR, + OP_TYPE_VECTOR_3D, + OP_TYPE_VECTOR_3D_SCALAR, OP_TYPE_MAX, }; @@ -1423,20 +1505,20 @@ VARIANT_ENUM_CAST(VisualShaderNodeSmoothStep::OpType) /// DISTANCE /////////////////////////////////////// -class VisualShaderNodeVectorDistance : public VisualShaderNode { - GDCLASS(VisualShaderNodeVectorDistance, VisualShaderNode); +class VisualShaderNodeVectorDistance : public VisualShaderNodeVectorBase { + GDCLASS(VisualShaderNodeVectorDistance, VisualShaderNodeVectorBase); public: virtual String get_caption() const override; virtual int get_input_port_count() const override; - virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + virtual void set_op_type(OpType p_op_type) override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVectorDistance(); @@ -1475,8 +1557,10 @@ class VisualShaderNodeMix : public VisualShaderNode { public: enum OpType { OP_TYPE_SCALAR, - OP_TYPE_VECTOR, - OP_TYPE_VECTOR_SCALAR, + OP_TYPE_VECTOR_2D, + OP_TYPE_VECTOR_2D_SCALAR, + OP_TYPE_VECTOR_3D, + OP_TYPE_VECTOR_3D_SCALAR, OP_TYPE_MAX, }; @@ -1511,8 +1595,8 @@ VARIANT_ENUM_CAST(VisualShaderNodeMix::OpType) /// COMPOSE /////////////////////////////////////// -class VisualShaderNodeVectorCompose : public VisualShaderNode { - GDCLASS(VisualShaderNodeVectorCompose, VisualShaderNode); +class VisualShaderNodeVectorCompose : public VisualShaderNodeVectorBase { + GDCLASS(VisualShaderNodeVectorCompose, VisualShaderNodeVectorBase); public: virtual String get_caption() const override; @@ -1522,9 +1606,9 @@ public: virtual String get_input_port_name(int p_port) const override; virtual int get_output_port_count() const override; - virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + virtual void set_op_type(OpType p_op_type) override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVectorCompose(); @@ -1555,20 +1639,20 @@ public: /// DECOMPOSE /////////////////////////////////////// -class VisualShaderNodeVectorDecompose : public VisualShaderNode { - GDCLASS(VisualShaderNodeVectorDecompose, VisualShaderNode); +class VisualShaderNodeVectorDecompose : public VisualShaderNodeVectorBase { + GDCLASS(VisualShaderNodeVectorDecompose, VisualShaderNodeVectorBase); public: virtual String get_caption() const override; virtual int get_input_port_count() const override; - virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + virtual void set_op_type(OpType p_op_type) override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVectorDecompose(); @@ -1820,6 +1904,49 @@ public: /////////////////////////////////////// +class VisualShaderNodeVec2Uniform : public VisualShaderNodeUniform { + GDCLASS(VisualShaderNodeVec2Uniform, VisualShaderNodeUniform); + +private: + bool default_value_enabled = false; + Vector2 default_value; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + + virtual bool is_show_prop_names() const override; + virtual bool is_use_prop_slots() const override; + + void set_default_value_enabled(bool p_enabled); + bool is_default_value_enabled() const; + + void set_default_value(const Vector2 &p_value); + Vector2 get_default_value() const; + + bool is_qualifier_supported(Qualifier p_qual) const override; + bool is_convertible_to_constant() const override; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeVec2Uniform(); +}; + +/////////////////////////////////////// + class VisualShaderNodeVec3Uniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeVec3Uniform, VisualShaderNodeUniform); @@ -2119,7 +2246,8 @@ public: enum OpType { OP_TYPE_FLOAT, OP_TYPE_INT, - OP_TYPE_VECTOR, + OP_TYPE_VECTOR_2D, + OP_TYPE_VECTOR_3D, OP_TYPE_BOOLEAN, OP_TYPE_TRANSFORM, OP_TYPE_MAX, @@ -2232,7 +2360,8 @@ public: enum ComparisonType { CTYPE_SCALAR, CTYPE_SCALAR_INT, - CTYPE_VECTOR, + CTYPE_VECTOR_2D, + CTYPE_VECTOR_3D, CTYPE_BOOLEAN, CTYPE_TRANSFORM, CTYPE_MAX, @@ -2300,7 +2429,8 @@ class VisualShaderNodeMultiplyAdd : public VisualShaderNode { public: enum OpType { OP_TYPE_SCALAR, - OP_TYPE_VECTOR, + OP_TYPE_VECTOR_2D, + OP_TYPE_VECTOR_3D, OP_TYPE_MAX, }; diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 69977aaa35..5b43ca4bcd 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -813,6 +813,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) { code += scode; //use directly + if (bnode->use_comma_between_statements && i + 1 < bnode->statements.size()) { + code += ","; + } } else { code += _mktab(p_level) + scode + ";\n"; } @@ -1287,10 +1290,10 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } else if (cfnode->flow_op == SL::FLOW_OP_FOR) { String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + String middle = _dump_node_code(cfnode->blocks[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + String right = _dump_node_code(cfnode->blocks[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); code += _mktab(p_level) + "for (" + left + ";" + middle + ";" + right + ")\n"; - code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + code += _dump_node_code(cfnode->blocks[3], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } else if (cfnode->flow_op == SL::FLOW_OP_RETURN) { if (cfnode->expressions.size()) { diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index cf77d2156f..2e1ee41406 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -5252,21 +5252,32 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expression.push_back(e); continue; } else { - if (tk.type != TK_SEMICOLON) { - _set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk))); - return nullptr; - } else { -#ifdef DEBUG_ENABLED - if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { - _add_line_warning(ShaderWarning::FORMATTING_ERROR, RTR("Empty statement. Remove ';' to fix this warning.")); - } -#endif // DEBUG_ENABLED + bool valid = false; + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_FOR_EXPRESSION && tk.type == TK_PARENTHESIS_CLOSE) { + valid = true; _set_tkpos(prepos); OperatorNode *func = alloc_node<OperatorNode>(); func->op = OP_EMPTY; expr = func; } + if (!valid) { + if (tk.type != TK_SEMICOLON) { + _set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk))); + return nullptr; + } else { +#ifdef DEBUG_ENABLED + if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { + _add_line_warning(ShaderWarning::FORMATTING_ERROR, RTR("Empty statement. Remove ';' to fix this warning.")); + } +#endif // DEBUG_ENABLED + _set_tkpos(prepos); + + OperatorNode *func = alloc_node<OperatorNode>(); + func->op = OP_EMPTY; + expr = func; + } + } } ERR_FAIL_COND_V(!expr, nullptr); @@ -6769,14 +6780,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun array_size = 0; } - if (tk.type == TK_COMMA) { - if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) { - _set_error(vformat("Multiple declarations in '%s' loop are not supported.", "for")); - return ERR_PARSE_ERROR; - } - } else if (tk.type == TK_SEMICOLON) { + if (tk.type == TK_SEMICOLON) { break; - } else { + } else if (tk.type != TK_COMMA) { _set_expected_error(",", ";"); return ERR_PARSE_ERROR; } @@ -7138,43 +7144,35 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun cf->flow_op = FLOW_OP_FOR; BlockNode *init_block = alloc_node<BlockNode>(); - init_block->block_type = BlockNode::BLOCK_TYPE_FOR; + init_block->block_type = BlockNode::BLOCK_TYPE_FOR_INIT; init_block->parent_block = p_block; init_block->single_statement = true; cf->blocks.push_back(init_block); - if (_parse_block(init_block, p_function_info, true, false, false) != OK) { - return ERR_PARSE_ERROR; - } - - Node *n = _parse_and_reduce_expression(init_block, p_function_info); - if (!n) { - return ERR_PARSE_ERROR; - } - - if (n->get_datatype() != TYPE_BOOL) { - _set_error(RTR("The middle expression is expected to be boolean.")); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_expected_error(";"); - return ERR_PARSE_ERROR; + Error err = _parse_block(init_block, p_function_info, true, false, false); + if (err != OK) { + return err; } - cf->expressions.push_back(n); - - n = _parse_and_reduce_expression(init_block, p_function_info); - if (!n) { - return ERR_PARSE_ERROR; + BlockNode *condition_block = alloc_node<BlockNode>(); + condition_block->block_type = BlockNode::BLOCK_TYPE_FOR_CONDITION; + condition_block->parent_block = init_block; + condition_block->single_statement = true; + condition_block->use_comma_between_statements = true; + cf->blocks.push_back(condition_block); + err = _parse_block(condition_block, p_function_info, true, false, false); + if (err != OK) { + return err; } - cf->expressions.push_back(n); - - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_expected_error(")"); - return ERR_PARSE_ERROR; + BlockNode *expression_block = alloc_node<BlockNode>(); + expression_block->block_type = BlockNode::BLOCK_TYPE_FOR_EXPRESSION; + expression_block->parent_block = init_block; + expression_block->single_statement = true; + expression_block->use_comma_between_statements = true; + cf->blocks.push_back(expression_block); + err = _parse_block(expression_block, p_function_info, true, false, false); + if (err != OK) { + return err; } BlockNode *block = alloc_node<BlockNode>(); @@ -7182,8 +7180,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun cf->blocks.push_back(block); p_block->statements.push_back(cf); - Error err = _parse_block(block, p_function_info, true, true, true); - if (err) { + err = _parse_block(block, p_function_info, true, true, true); + if (err != OK) { return err; } @@ -7333,10 +7331,48 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (!expr) { return ERR_PARSE_ERROR; } + + bool empty = false; + + if (expr->type == Node::TYPE_OPERATOR) { + OperatorNode *op = static_cast<OperatorNode *>(expr); + if (op->op == OP_EMPTY) { + empty = true; + } + } + if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_INIT) { + if (!empty && expr->type != BlockNode::TYPE_VARIABLE_DECLARATION) { + _set_error(RTR("The left expression is expected to be a variable declaration.")); + return ERR_PARSE_ERROR; + } + } + if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_CONDITION) { + if (!empty && expr->get_datatype() != TYPE_BOOL) { + _set_error(RTR("The middle expression is expected to be boolean.")); + return ERR_PARSE_ERROR; + } + } + p_block->statements.push_back(expr); tk = _get_token(); - if (tk.type != TK_SEMICOLON) { + if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_CONDITION) { + if (tk.type == TK_COMMA) { + continue; + } + if (tk.type != TK_SEMICOLON) { + _set_expected_error(",", ";"); + return ERR_PARSE_ERROR; + } + } else if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_EXPRESSION) { + if (tk.type == TK_COMMA) { + continue; + } + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_expected_error(",", ")"); + return ERR_PARSE_ERROR; + } + } else if (tk.type != TK_SEMICOLON) { _set_expected_error(";"); return ERR_PARSE_ERROR; } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 1307eeac2b..f39b21621d 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -504,7 +504,9 @@ public: enum BlockType { BLOCK_TYPE_STANDART, - BLOCK_TYPE_FOR, + BLOCK_TYPE_FOR_INIT, + BLOCK_TYPE_FOR_CONDITION, + BLOCK_TYPE_FOR_EXPRESSION, BLOCK_TYPE_SWITCH, BLOCK_TYPE_CASE, BLOCK_TYPE_DEFAULT, @@ -526,6 +528,7 @@ public: Map<StringName, Variable> variables; List<Node *> statements; bool single_statement = false; + bool use_comma_between_statements = false; BlockNode() : Node(TYPE_BLOCK) {} diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index db1f589334..3c5faa4ef7 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -230,8 +230,8 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_shaped_text_is_ready, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_glyphs, "shaped", "r_glyphs"); - GDVIRTUAL_BIND(_shaped_text_sort_logical, "shaped", "r_glyphs"); + GDVIRTUAL_BIND(_shaped_text_get_glyphs, "shaped"); + GDVIRTUAL_BIND(_shaped_text_sort_logical, "shaped"); GDVIRTUAL_BIND(_shaped_text_get_glyph_count, "shaped"); GDVIRTUAL_BIND(_shaped_text_get_range, "shaped"); @@ -243,7 +243,7 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_shaped_text_get_trim_pos, "shaped"); GDVIRTUAL_BIND(_shaped_text_get_ellipsis_pos, "shaped"); GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyph_count, "shaped"); - GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyphs, "shaped", "r_glyphs"); + GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyphs, "shaped"); GDVIRTUAL_BIND(_shaped_text_overrun_trim_to_width, "shaped", "width", "trim_flags"); @@ -505,7 +505,7 @@ void TextServerExtension::font_set_hinting(RID p_font_rid, TextServer::Hinting p } TextServer::Hinting TextServerExtension::font_get_hinting(RID p_font_rid) const { - int ret; + TextServer::Hinting ret; if (GDVIRTUAL_CALL(_font_get_hinting, p_font_rid, ret)) { return (TextServer::Hinting)ret; } @@ -955,7 +955,7 @@ void TextServerExtension::shaped_text_set_direction(RID p_shaped, TextServer::Di } TextServer::Direction TextServerExtension::shaped_text_get_direction(RID p_shaped) const { - int ret; + TextServer::Direction ret; if (GDVIRTUAL_CALL(_shaped_text_get_direction, p_shaped, ret)) { return (TextServer::Direction)ret; } @@ -963,7 +963,7 @@ TextServer::Direction TextServerExtension::shaped_text_get_direction(RID p_shape } TextServer::Direction TextServerExtension::shaped_text_get_inferred_direction(RID p_shaped) const { - int ret; + TextServer::Direction ret; if (GDVIRTUAL_CALL(_shaped_text_get_inferred_direction, p_shaped, ret)) { return (TextServer::Direction)ret; } @@ -975,7 +975,7 @@ void TextServerExtension::shaped_text_set_orientation(RID p_shaped, TextServer:: } TextServer::Orientation TextServerExtension::shaped_text_get_orientation(RID p_shaped) const { - int ret; + TextServer::Orientation ret; if (GDVIRTUAL_CALL(_shaped_text_get_orientation, p_shaped, ret)) { return (TextServer::Orientation)ret; } @@ -1139,16 +1139,16 @@ bool TextServerExtension::shaped_text_is_ready(RID p_shaped) const { } const Glyph *TextServerExtension::shaped_text_get_glyphs(RID p_shaped) const { - const Glyph *ret; - if (GDVIRTUAL_CALL(_shaped_text_get_glyphs, p_shaped, &ret)) { + GDNativePtr<Glyph> ret; + if (GDVIRTUAL_CALL(_shaped_text_get_glyphs, p_shaped, ret)) { return ret; } return nullptr; } const Glyph *TextServerExtension::shaped_text_sort_logical(RID p_shaped) { - const Glyph *ret; - if (GDVIRTUAL_CALL(_shaped_text_sort_logical, p_shaped, &ret)) { + GDNativePtr<Glyph> ret; + if (GDVIRTUAL_CALL(_shaped_text_sort_logical, p_shaped, ret)) { return ret; } return nullptr; @@ -1211,8 +1211,8 @@ int TextServerExtension::shaped_text_get_ellipsis_pos(RID p_shaped) const { } const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(RID p_shaped) const { - const Glyph *ret; - if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, &ret)) { + GDNativePtr<Glyph> ret; + if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, ret)) { return ret; } return nullptr; diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index df1f1d7a70..9e7f666be1 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -132,7 +132,7 @@ public: virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) override; virtual Hinting font_get_hinting(RID p_font_rid) const override; GDVIRTUAL2(_font_set_hinting, RID, Hinting); - GDVIRTUAL1RC(/*Hinting*/ int, _font_get_hinting, RID); + GDVIRTUAL1RC(Hinting, _font_get_hinting, RID); virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; @@ -317,8 +317,8 @@ public: virtual Direction shaped_text_get_direction(RID p_shaped) const override; virtual Direction shaped_text_get_inferred_direction(RID p_shaped) const override; GDVIRTUAL2(_shaped_text_set_direction, RID, Direction); - GDVIRTUAL1RC(/*Direction*/ int, _shaped_text_get_direction, RID); - GDVIRTUAL1RC(/*Direction*/ int, _shaped_text_get_inferred_direction, RID); + GDVIRTUAL1RC(Direction, _shaped_text_get_direction, RID); + GDVIRTUAL1RC(Direction, _shaped_text_get_inferred_direction, RID); virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &); @@ -331,7 +331,7 @@ public: virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation); - GDVIRTUAL1RC(/*Orientation*/ int, _shaped_text_get_orientation, RID); + GDVIRTUAL1RC(Orientation, _shaped_text_get_orientation, RID); virtual void shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) override; virtual bool shaped_text_get_preserve_invalid(RID p_shaped) const override; @@ -380,8 +380,8 @@ public: virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const override; virtual const Glyph *shaped_text_sort_logical(RID p_shaped) override; virtual int shaped_text_get_glyph_count(RID p_shaped) const override; - GDVIRTUAL2C(_shaped_text_get_glyphs, RID, GDNativePtr<const Glyph *>); - GDVIRTUAL2(_shaped_text_sort_logical, RID, GDNativePtr<const Glyph *>); + GDVIRTUAL1RC(GDNativePtr<Glyph>, _shaped_text_get_glyphs, RID); + GDVIRTUAL1R(GDNativePtr<Glyph>, _shaped_text_sort_logical, RID); GDVIRTUAL1RC(int, _shaped_text_get_glyph_count, RID); virtual Vector2i shaped_text_get_range(RID p_shaped) const override; @@ -400,7 +400,7 @@ public: virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const override; GDVIRTUAL1RC(int, _shaped_text_get_trim_pos, RID); GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_pos, RID); - GDVIRTUAL2C(_shaped_text_get_ellipsis_glyphs, RID, GDNativePtr<const Glyph *>); + GDVIRTUAL1RC(GDNativePtr<Glyph>, _shaped_text_get_ellipsis_glyphs, RID); GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_glyph_count, RID); virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) override; diff --git a/servers/text_server.h b/servers/text_server.h index 6724c02caf..629a633b9f 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -557,7 +557,6 @@ VARIANT_ENUM_CAST(TextServer::SpacingType); VARIANT_ENUM_CAST(TextServer::FontStyle); GDVIRTUAL_NATIVE_PTR(Glyph); -GDVIRTUAL_NATIVE_PTR(Glyph *); GDVIRTUAL_NATIVE_PTR(CaretInfo); #endif // TEXT_SERVER_H diff --git a/thirdparty/README.md b/thirdparty/README.md index dc2f174b2b..e1f911a9f9 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -206,7 +206,7 @@ Files extracted from upstream source: ## harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz -- Version: 3.2.0 (be91d2917d9860326cb5fd1d03ffe1042a72f6d3, 2021) +- Version: 3.3.1 (45df259538c204540819d74456d30ffb40df488a, 2022) - License: MIT Files extracted from upstream source: @@ -309,7 +309,7 @@ Files extracted from upstream source: ## libwebp - Upstream: https://chromium.googlesource.com/webm/libwebp/ -- Version: 1.2.1 (9ce5843dbabcfd3f7c39ec7ceba9cbeb213cbfdf, 2021) +- Version: 1.2.2 (b0a860891dcd4c0c2d7c6149e5cccb6eb881cc21, 2022) - License: BSD-3-Clause Files extracted from upstream source: @@ -317,10 +317,6 @@ Files extracted from upstream source: - `src/*` except from: `.am`, `.rc` and `.in` files - `AUTHORS`, `COPYING`, `PATENTS` -Important: The files `utils/bit_reader_utils.{c,h}` have Godot-made -changes to ensure they build for Javascript/HTML5. Those -changes are marked with `// -- GODOT --` comments. - ## mbedtls diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh index 1dcbe92904..1db0f1df92 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh @@ -839,7 +839,7 @@ struct StateTableDriver } if (!c->in_place) - buffer->swap_buffers (); + buffer->sync (); } public: diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh index d745c11431..0bf9bd2912 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh @@ -146,7 +146,7 @@ struct DuctileGlyphAction HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis. * This would normally be 0x64756374 ('duct'), * but you may use any axis the font contains. */ - HBFixed minimumLimit; /* The lowest value for the ductility axis tha + HBFixed minimumLimit; /* The lowest value for the ductility axis that * still yields an acceptable appearance. Normally * this will be 1.0. */ HBFixed noStretchValue; /* This is the default value that corresponds to diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh index 446d87e28b..3a3ab08046 100644 --- a/thirdparty/harfbuzz/src/hb-algs.hh +++ b/thirdparty/harfbuzz/src/hb-algs.hh @@ -36,6 +36,7 @@ #include <algorithm> #include <initializer_list> +#include <functional> #include <new> /* @@ -210,12 +211,23 @@ struct } HB_FUNCOBJ (hb_bool); +template <typename T> +static inline +T hb_coerce (const T v) { return v; } +template <typename T, typename V, + hb_enable_if (!hb_is_same (hb_decay<T>, hb_decay<V>) && std::is_pointer<V>::value)> +static inline +T hb_coerce (const V v) { return *v; } + struct { private: template <typename T> constexpr auto - impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) + impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) + + template <typename T> constexpr auto + impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v))) template <typename T, hb_enable_if (std::is_integral<T>::value)> constexpr auto @@ -435,23 +447,29 @@ struct private: template <typename T1, typename T2> auto - impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN + impl (T1&& v1, T2 &&v2, hb_priority<3>) const HB_AUTO_RETURN ( std::forward<T2> (v2).cmp (std::forward<T1> (v1)) == 0 ) template <typename T1, typename T2> auto - impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN + impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN ( std::forward<T1> (v1).cmp (std::forward<T2> (v2)) == 0 ) template <typename T1, typename T2> auto - impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN + impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN ( std::forward<T1> (v1) == std::forward<T2> (v2) ) + template <typename T1, typename T2> auto + impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN + ( + std::forward<T2> (v2) == std::forward<T1> (v1) + ) + public: template <typename T1, typename T2> auto @@ -472,6 +490,10 @@ struct hb_pair_t typedef T2 second_t; typedef hb_pair_t<T1, T2> pair_t; + template <typename U1 = T1, typename U2 = T2, + hb_enable_if (std::is_default_constructible<U1>::value && + std::is_default_constructible<U2>::value)> + hb_pair_t () : first (), second () {} hb_pair_t (T1 a, T2 b) : first (a), second (b) {} template <typename Q1, typename Q2, @@ -870,7 +892,7 @@ hb_bsearch_impl (unsigned *pos, /* Out */ #pragma GCC diagnostic ignored "-Wcast-align" V* p = (V*) (((const char *) base) + (mid * stride)); #pragma GCC diagnostic pop - int c = compar ((const void *) hb_addressof (key), (const void *) p, ds...); + int c = compar ((const void *) std::addressof (key), (const void *) p, ds...); if (c < 0) max = mid - 1; else if (c > 0) diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh index 0beffb078f..1d1476d7cd 100644 --- a/thirdparty/harfbuzz/src/hb-array.hh +++ b/thirdparty/harfbuzz/src/hb-array.hh @@ -412,7 +412,7 @@ bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const return true; } -/* TODO Specialize opeator== for hb_bytes_t and hb_ubytes_t. */ +/* TODO Specialize operator== for hb_bytes_t and hb_ubytes_t. */ template <> inline uint32_t hb_array_t<const char>::hash () const { diff --git a/thirdparty/harfbuzz/src/hb-bimap.hh b/thirdparty/harfbuzz/src/hb-bimap.hh index d466af8b60..a9e1278de7 100644 --- a/thirdparty/harfbuzz/src/hb-bimap.hh +++ b/thirdparty/harfbuzz/src/hb-bimap.hh @@ -33,20 +33,6 @@ /* Bi-directional map */ struct hb_bimap_t { - /* XXX(remove) */ - void init () - { - forw_map.init (); - back_map.init (); - } - - /* XXX(remove) */ - void fini () - { - forw_map.fini (); - back_map.fini (); - } - void reset () { forw_map.reset (); diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc index be3161a54d..e50afcb203 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.cc +++ b/thirdparty/harfbuzz/src/hb-buffer.cc @@ -86,7 +86,46 @@ hb_segment_properties_hash (const hb_segment_properties_t *p) (intptr_t) (p->language); } +/** + * hb_segment_properties_overlay: + * @p: #hb_segment_properties_t to fill in. + * @src: #hb_segment_properties_t to fill in from. + * + * Fills in missing fields of @p from @src in a considered manner. + * + * First, if @p does not have direction set, direction is copied from @src. + * + * Next, if @p and @src have the same direction (which can be unset), if @p + * does not have script set, script is copied from @src. + * + * Finally, if @p and @src have the same direction and script (which either + * can be unset), if @p does not have language set, language is copied from + * @src. + * + * Since: 3.3.0 + **/ +void +hb_segment_properties_overlay (hb_segment_properties_t *p, + const hb_segment_properties_t *src) +{ + if (unlikely (!p || !src)) + return; + if (!p->direction) + p->direction = src->direction; + + if (p->direction != src->direction) + return; + + if (!p->script) + p->script = src->script; + + if (p->script != src->script) + return; + + if (!p->language) + p->language = src->language; +} /* Here is how the buffer works internally: * @@ -96,14 +135,14 @@ hb_segment_properties_hash (const hb_segment_properties_t *p) * As an optimization, both info and out_info may point to the * same piece of memory, which is owned by info. This remains the * case as long as out_len doesn't exceed i at any time. - * In that case, swap_buffers() is mostly no-op and the glyph operations + * In that case, sync() is mostly no-op and the glyph operations * operate mostly in-place. * * As soon as out_info gets longer than info, out_info is moved over * to an alternate buffer (which we reuse the pos buffer for), and its * current contents (out_len entries) are copied to the new place. * - * This should all remain transparent to the user. swap_buffers() then + * This should all remain transparent to the user. sync() then * switches info over to out_info and does housekeeping. */ @@ -217,11 +256,24 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size) /* HarfBuzz-Internal API */ void +hb_buffer_t::similar (const hb_buffer_t &src) +{ + hb_unicode_funcs_destroy (unicode); + unicode = hb_unicode_funcs_reference (src.unicode); + flags = src.flags; + cluster_level = src.cluster_level; + replacement = src.invisible; + invisible = src.invisible; + not_found = src.not_found; +} + +void hb_buffer_t::reset () { hb_unicode_funcs_destroy (unicode); unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ()); flags = HB_BUFFER_FLAG_DEFAULT; + cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT; replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; invisible = 0; not_found = 0; @@ -232,11 +284,10 @@ hb_buffer_t::reset () void hb_buffer_t::clear () { + content_type = HB_BUFFER_CONTENT_TYPE_INVALID; hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; props = default_props; - scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; - content_type = HB_BUFFER_CONTENT_TYPE_INVALID; successful = true; have_output = false; have_positions = false; @@ -244,16 +295,44 @@ hb_buffer_t::clear () idx = 0; len = 0; out_len = 0; - out_info = info; - serial = 0; + out_info = info; memset (context, 0, sizeof context); memset (context_len, 0, sizeof context_len); deallocate_var_all (); + serial = 0; + scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; +} + +void +hb_buffer_t::enter () +{ + deallocate_var_all (); + serial = 0; + scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; + if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR))) + { + max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR, + (unsigned) HB_BUFFER_MAX_LEN_MIN); + } + if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR))) + { + max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR, + (unsigned) HB_BUFFER_MAX_OPS_MIN); + } +} +void +hb_buffer_t::leave () +{ + max_len = HB_BUFFER_MAX_LEN_DEFAULT; + max_ops = HB_BUFFER_MAX_OPS_DEFAULT; + deallocate_var_all (); + serial = 0; } + void hb_buffer_t::add (hb_codepoint_t codepoint, unsigned int cluster) @@ -307,7 +386,7 @@ hb_buffer_t::clear_positions () } void -hb_buffer_t::swap_buffers () +hb_buffer_t::sync () { assert (have_output); @@ -494,33 +573,6 @@ done: } void -hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end) -{ - unsigned int cluster = UINT_MAX; - cluster = _infos_find_min_cluster (info, start, end, cluster); - _unsafe_to_break_set_mask (info, start, end, cluster); -} -void -hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end) -{ - if (!have_output) - { - unsafe_to_break_impl (start, end); - return; - } - - assert (start <= out_len); - assert (idx <= end); - - unsigned int cluster = UINT_MAX; - cluster = _infos_find_min_cluster (out_info, start, out_len, cluster); - cluster = _infos_find_min_cluster (info, idx, end, cluster); - - _unsafe_to_break_set_mask (out_info, start, out_len, cluster); - _unsafe_to_break_set_mask (info, idx, end, cluster); -} - -void hb_buffer_t::guess_segment_properties () { assert_unicode (); @@ -565,12 +617,11 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, 0, /* invisible */ 0, /* not_found */ - HB_BUFFER_SCRATCH_FLAG_DEFAULT, - HB_BUFFER_MAX_LEN_DEFAULT, - HB_BUFFER_MAX_OPS_DEFAULT, + HB_BUFFER_CONTENT_TYPE_INVALID, HB_SEGMENT_PROPERTIES_DEFAULT, + false, /* successful */ false, /* have_output */ true /* have_positions */ @@ -610,6 +661,46 @@ hb_buffer_create () } /** + * hb_buffer_create_similar: + * @src: An #hb_buffer_t + * + * Creates a new #hb_buffer_t, similar to hb_buffer_create(). The only + * difference is that the buffer is configured similarly to @src. + * + * Return value: (transfer full): + * A newly allocated #hb_buffer_t, similar to hb_buffer_create(). + * + * Since: 3.3.0 + **/ +hb_buffer_t * +hb_buffer_create_similar (const hb_buffer_t *src) +{ + hb_buffer_t *buffer = hb_buffer_create (); + + buffer->similar (*src); + + return buffer; +} + +/** + * hb_buffer_reset: + * @buffer: An #hb_buffer_t + * + * Resets the buffer to its initial status, as if it was just newly created + * with hb_buffer_create(). + * + * Since: 0.9.2 + **/ +void +hb_buffer_reset (hb_buffer_t *buffer) +{ + if (unlikely (hb_object_is_immutable (buffer))) + return; + + buffer->reset (); +} + +/** * hb_buffer_get_empty: * * Fetches an empty #hb_buffer_t. @@ -1157,24 +1248,6 @@ hb_buffer_get_not_found_glyph (hb_buffer_t *buffer) /** - * hb_buffer_reset: - * @buffer: An #hb_buffer_t - * - * Resets the buffer to its initial status, as if it was just newly created - * with hb_buffer_create(). - * - * Since: 0.9.2 - **/ -void -hb_buffer_reset (hb_buffer_t *buffer) -{ - if (unlikely (hb_object_is_immutable (buffer))) - return; - - buffer->reset (); -} - -/** * hb_buffer_clear_contents: * @buffer: An #hb_buffer_t * @@ -1749,6 +1822,8 @@ hb_buffer_append (hb_buffer_t *buffer, if (!buffer->have_positions && source->have_positions) buffer->clear_positions (); + hb_segment_properties_overlay (&buffer->props, &source->props); + memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); if (buffer->have_positions) memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h index a183cb9d4a..9fbd7b1ec3 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.h +++ b/thirdparty/harfbuzz/src/hb-buffer.h @@ -76,18 +76,68 @@ typedef struct hb_glyph_info_t { * @HB_GLYPH_FLAG_UNSAFE_TO_BREAK: Indicates that if input text is broken at the * beginning of the cluster this glyph is part of, * then both sides need to be re-shaped, as the - * result might be different. On the flip side, - * it means that when this flag is not present, - * then it's safe to break the glyph-run at the - * beginning of this cluster, and the two sides - * represent the exact same result one would get - * if breaking input text at the beginning of - * this cluster and shaping the two sides - * separately. This can be used to optimize - * paragraph layout, by avoiding re-shaping - * of each line after line-breaking, or limiting - * the reshaping to a small piece around the - * breaking point only. + * result might be different. + * On the flip side, it means that when this + * flag is not present, then it is safe to break + * the glyph-run at the beginning of this + * cluster, and the two sides will represent the + * exact same result one would get if breaking + * input text at the beginning of this cluster + * and shaping the two sides separately. + * This can be used to optimize paragraph + * layout, by avoiding re-shaping of each line + * after line-breaking. + * @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT: Indicates that if input text is changed on one + * side of the beginning of the cluster this glyph + * is part of, then the shaping results for the + * other side might change. + * Note that the absence of this flag will NOT by + * itself mean that it IS safe to concat text. + * Only two pieces of text both of which clear of + * this flag can be concatenated safely. + * This can be used to optimize paragraph + * layout, by avoiding re-shaping of each line + * after line-breaking, by limiting the + * reshaping to a small piece around the + * breaking positin only, even if the breaking + * position carries the + * #HB_GLYPH_FLAG_UNSAFE_TO_BREAK or when + * hyphenation or other text transformation + * happens at line-break position, in the following + * way: + * 1. Iterate back from the line-break position + * until the first cluster start position that is + * NOT unsafe-to-concat, 2. shape the segment from + * there till the end of line, 3. check whether the + * resulting glyph-run also is clear of the + * unsafe-to-concat at its start-of-text position; + * if it is, just splice it into place and the line + * is shaped; If not, move on to a position further + * back that is clear of unsafe-to-concat and retry + * from there, and repeat. + * At the start of next line a similar algorithm can + * be implemented. That is: 1. Iterate forward from + * the line-break position untill the first cluster + * start position that is NOT unsafe-to-concat, 2. + * shape the segment from beginning of the line to + * that position, 3. check whether the resulting + * glyph-run also is clear of the unsafe-to-concat + * at its end-of-text position; if it is, just splice + * it into place and the beginning is shaped; If not, + * move on to a position further forward that is clear + * of unsafe-to-concat and retry up to there, and repeat. + * A slight complication will arise in the + * implementation of the algorithm above, + * because while our buffer API has a way to + * return flags for position corresponding to + * start-of-text, there is currently no position + * corresponding to end-of-text. This limitation + * can be alleviated by shaping more text than needed + * and looking for unsafe-to-concat flag within text + * clusters. + * The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will + * always imply this flag. + * Since: 3.3.0 * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. * * Flags for #hb_glyph_info_t. @@ -96,8 +146,9 @@ typedef struct hb_glyph_info_t { */ typedef enum { /*< flags >*/ HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, + HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002, - HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */ + HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */ } hb_glyph_flags_t; HB_EXTERN hb_glyph_flags_t @@ -170,6 +221,9 @@ hb_segment_properties_equal (const hb_segment_properties_t *a, HB_EXTERN unsigned int hb_segment_properties_hash (const hb_segment_properties_t *p); +HB_EXTERN void +hb_segment_properties_overlay (hb_segment_properties_t *p, + const hb_segment_properties_t *src); /** @@ -185,6 +239,13 @@ HB_EXTERN hb_buffer_t * hb_buffer_create (void); HB_EXTERN hb_buffer_t * +hb_buffer_create_similar (const hb_buffer_t *src); + +HB_EXTERN void +hb_buffer_reset (hb_buffer_t *buffer); + + +HB_EXTERN hb_buffer_t * hb_buffer_get_empty (void); HB_EXTERN hb_buffer_t * @@ -391,8 +452,9 @@ HB_EXTERN hb_codepoint_t hb_buffer_get_not_found_glyph (hb_buffer_t *buffer); -HB_EXTERN void -hb_buffer_reset (hb_buffer_t *buffer); +/* + * Content API. + */ HB_EXTERN void hb_buffer_clear_contents (hb_buffer_t *buffer); diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh index 0f8140f1b3..adf4aa2b6f 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.hh +++ b/thirdparty/harfbuzz/src/hb-buffer.hh @@ -67,8 +67,8 @@ enum hb_buffer_scratch_flags_t { HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u, - HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u, - HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000020u, + HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u, + HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u, /* Reserved for complex shapers' internal use. */ HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u, @@ -87,18 +87,21 @@ struct hb_buffer_t { hb_object_header_t header; - /* Information about how the text in the buffer should be treated */ + /* + * Information about how the text in the buffer should be treated. + */ + hb_unicode_funcs_t *unicode; /* Unicode functions */ hb_buffer_flags_t flags; /* BOT / EOT / etc. */ hb_buffer_cluster_level_t cluster_level; hb_codepoint_t replacement; /* U+FFFD or something else. */ hb_codepoint_t invisible; /* 0 or something else. */ hb_codepoint_t not_found; /* 0 or something else. */ - hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ - unsigned int max_len; /* Maximum allowed len. */ - int max_ops; /* Maximum allowed operations. */ - /* Buffer contents */ + /* + * Buffer contents + */ + hb_buffer_content_type_t content_type; hb_segment_properties_t props; /* Script, language, direction */ @@ -115,8 +118,6 @@ struct hb_buffer_t hb_glyph_info_t *out_info; hb_glyph_position_t *pos; - unsigned int serial; - /* Text before / after the main buffer contents. * Always in Unicode, and ordered outward. * Index 0 is for "pre-context", 1 for "post-context". */ @@ -124,7 +125,25 @@ struct hb_buffer_t hb_codepoint_t context[2][CONTEXT_LENGTH]; unsigned int context_len[2]; - /* Debugging API */ + + /* + * Managed by enter / leave + */ + +#ifndef HB_NDEBUG + uint8_t allocated_var_bits; +#endif + uint8_t serial; + hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ + unsigned int max_len; /* Maximum allowed len. */ + int max_ops; /* Maximum allowed operations. */ + /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ + + + /* + * Messaging callback + */ + #ifndef HB_NO_BUFFER_MESSAGE hb_buffer_message_func_t message_func; void *message_data; @@ -134,11 +153,6 @@ struct hb_buffer_t static constexpr unsigned message_depth = 0u; #endif - /* Internal debugging. */ - /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ -#ifndef HB_NDEBUG - uint8_t allocated_var_bits; -#endif /* Methods */ @@ -190,12 +204,17 @@ struct hb_buffer_t hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; } hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; } + HB_INTERNAL void similar (const hb_buffer_t &src); HB_INTERNAL void reset (); HB_INTERNAL void clear (); + /* Called around shape() */ + HB_INTERNAL void enter (); + HB_INTERNAL void leave (); + unsigned int backtrack_len () const { return have_output ? out_len : idx; } unsigned int lookahead_len () const { return len - idx; } - unsigned int next_serial () { return serial++; } + uint8_t next_serial () { return ++serial ? serial : ++serial; } HB_INTERNAL void add (hb_codepoint_t codepoint, unsigned int cluster); @@ -252,7 +271,7 @@ struct hb_buffer_t HB_INTERNAL void guess_segment_properties (); - HB_INTERNAL void swap_buffers (); + HB_INTERNAL void sync (); HB_INTERNAL void clear_output (); HB_INTERNAL void clear_positions (); @@ -366,15 +385,80 @@ struct hb_buffer_t /* Merge clusters for deleting current glyph, and skip it. */ HB_INTERNAL void delete_glyph (); - void unsafe_to_break (unsigned int start, - unsigned int end) + + void set_glyph_flags (hb_mask_t mask, + unsigned start = 0, + unsigned end = (unsigned) -1, + bool interior = false, + bool from_out_buffer = false) { - if (end - start < 2) + end = hb_min (end, len); + + if (interior && !from_out_buffer && end - start < 2) return; - unsafe_to_break_impl (start, end); + + scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS; + + if (!from_out_buffer || !have_output) + { + if (!interior) + { + for (unsigned i = start; i < end; i++) + info[i].mask |= mask; + } + else + { + unsigned cluster = _infos_find_min_cluster (info, start, end); + _infos_set_glyph_flags (info, start, end, cluster, mask); + } + } + else + { + assert (start <= out_len); + assert (idx <= end); + + if (!interior) + { + for (unsigned i = start; i < out_len; i++) + out_info[i].mask |= mask; + for (unsigned i = idx; i < end; i++) + info[i].mask |= mask; + } + else + { + unsigned cluster = _infos_find_min_cluster (info, idx, end); + cluster = _infos_find_min_cluster (out_info, start, out_len, cluster); + + _infos_set_glyph_flags (out_info, start, out_len, cluster, mask); + _infos_set_glyph_flags (info, idx, end, cluster, mask); + } + } + } + + void unsafe_to_break (unsigned int start = 0, unsigned int end = -1) + { + set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, + start, end, + true); + } + void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1) + { + set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, + start, end, + true); + } + void unsafe_to_break_from_outbuffer (unsigned int start = 0, unsigned int end = -1) + { + set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, + start, end, + true, true); + } + void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1) + { + set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, + start, end, + false, true); } - HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end); - HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end); /* Internal methods */ @@ -465,36 +549,31 @@ struct hb_buffer_t set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0) { if (inf.cluster != cluster) - { - if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) - inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; - else - inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; - } + inf.mask = (inf.mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED); inf.cluster = cluster; } - + void + _infos_set_glyph_flags (hb_glyph_info_t *infos, + unsigned int start, unsigned int end, + unsigned int cluster, + hb_mask_t mask) + { + for (unsigned int i = start; i < end; i++) + if (cluster != infos[i].cluster) + { + scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS; + infos[i].mask |= mask; + } + } static unsigned _infos_find_min_cluster (const hb_glyph_info_t *infos, unsigned start, unsigned end, - unsigned cluster) + unsigned cluster = UINT_MAX) { for (unsigned int i = start; i < end; i++) cluster = hb_min (cluster, infos[i].cluster); return cluster; } - void - _unsafe_to_break_set_mask (hb_glyph_info_t *infos, - unsigned int start, unsigned int end, - unsigned int cluster) - { - for (unsigned int i = start; i < end; i++) - if (cluster != infos[i].cluster) - { - scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK; - infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; - } - } void clear_glyph_flags (hb_mask_t mask = 0) { diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh index c251e2d0ed..641de0eff2 100644 --- a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh +++ b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh @@ -217,9 +217,6 @@ inline unsigned int OpCode_Size (op_code_t op) { return Is_OpCode_ESC (op) ? 2: struct number_t { - void init () { set_real (0.0); } - void fini () {} - void set_int (int v) { value = v; } int to_int () const { return value; } @@ -245,7 +242,7 @@ struct number_t } protected: - double value; + double value = 0.; }; /* byte string */ @@ -380,10 +377,8 @@ struct cff_stack_t count = 0; elements.init (); elements.resize (kSizeLimit); - for (unsigned int i = 0; i < elements.length; i++) - elements[i].init (); } - void fini () { elements.fini_deep (); } + void fini () { elements.fini (); } ELEM& operator [] (unsigned int i) { @@ -523,9 +518,6 @@ struct arg_stack_t : cff_stack_t<ARG, 513> /* an operator prefixed by its operands in a byte string */ struct op_str_t { - void init () {} - void fini () {} - op_code_t op; byte_str_t str; }; @@ -553,7 +545,7 @@ struct parsed_values_t opStart = 0; values.init (); } - void fini () { values.fini_deep (); } + void fini () { values.fini (); } void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ()) { diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh index 52d778ffe2..ef299369b5 100644 --- a/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh +++ b/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh @@ -94,12 +94,6 @@ struct biased_subrs_t struct point_t { - void init () - { - x.init (); - y.init (); - } - void set_int (int _x, int _y) { x.set_int (_x); @@ -128,7 +122,7 @@ struct cs_interp_env_t : interp_env_t<ARG> hstem_count = 0; vstem_count = 0; hintmask_size = 0; - pt.init (); + pt.set_int (0, 0); callStack.init (); globalSubrs.init (globalSubrs_); localSubrs.init (localSubrs_); @@ -841,7 +835,6 @@ struct path_procs_t if (likely (env.argStack.get_count () == 11)) { point_t d; - d.init (); for (unsigned int i = 0; i < 10; i += 2) d.move (env.eval_arg (i), env.eval_arg (i+1)); diff --git a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh index d961566447..766183760e 100644 --- a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh +++ b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh @@ -35,18 +35,6 @@ using namespace OT; struct blend_arg_t : number_t { - void init () - { - number_t::init (); - deltas.init (); - } - - void fini () - { - number_t::fini (); - deltas.fini_deep (); - } - void set_int (int v) { reset_blends (); number_t::set_int (v); } void set_fixed (int32_t v) { reset_blends (); number_t::set_fixed (v); } void set_real (double v) { reset_blends (); number_t::set_real (v); } @@ -202,7 +190,7 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA switch (op) { case OpCode_callsubr: case OpCode_callgsubr: - /* a subroutine number shoudln't be a blended value */ + /* a subroutine number shouldn't be a blended value */ if (unlikely (env.argStack.peek ().blending ())) { env.set_error (); diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc index 26c8ad0f49..249a8a8010 100644 --- a/thirdparty/harfbuzz/src/hb-common.cc +++ b/thirdparty/harfbuzz/src/hb-common.cc @@ -29,10 +29,31 @@ #include "hb.hh" #include "hb-machinery.hh" +#if !defined(HB_NO_SETLOCALE) && (!defined(HAVE_NEWLOCALE) || !defined(HAVE_USELOCALE)) +#define HB_NO_SETLOCALE 1 +#endif + +#ifndef HB_NO_SETLOCALE + #include <locale.h> +#ifdef HAVE_XLOCALE_H +#include <xlocale.h> // Needed on BSD/OS X for uselocale +#endif + +#ifdef WIN32 +#define hb_locale_t _locale_t +#else +#define hb_locale_t locale_t +#endif +#define hb_setlocale setlocale +#define hb_uselocale uselocale + +#else + +#define hb_locale_t void * +#define hb_setlocale(Category, Locale) "C" +#define hb_uselocale(Locale) ((hb_locale_t) 0) -#ifdef HB_NO_SETLOCALE -#define setlocale(Category, Locale) "C" #endif /** @@ -122,7 +143,7 @@ hb_tag_from_string (const char *str, int len) * @tag: #hb_tag_t to convert * @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t): Converted string * - * Converts an #hb_tag_t to a string and returns it in @buf. + * Converts an #hb_tag_t to a string and returns it in @buf. * Strings will be four characters long. * * Since: 0.9.5 @@ -151,13 +172,13 @@ const char direction_strings[][4] = { * @str: (array length=len) (element-type uint8_t): String to convert * @len: Length of @str, or -1 if it is %NULL-terminated * - * Converts a string to an #hb_direction_t. + * Converts a string to an #hb_direction_t. * * Matching is loose and applies only to the first letter. For * examples, "LTR" and "left-to-right" will both return #HB_DIRECTION_LTR. * * Unmatched strings will return #HB_DIRECTION_INVALID. - * + * * Return value: The #hb_direction_t matching @str * * Since: 0.9.2 @@ -413,7 +434,7 @@ hb_language_get_default () hb_language_t language = default_language; if (unlikely (language == HB_LANGUAGE_INVALID)) { - language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1); + language = hb_language_from_string (hb_setlocale (LC_CTYPE, nullptr), -1); (void) default_language.cmpexch (HB_LANGUAGE_INVALID, language); } @@ -1039,6 +1060,47 @@ hb_variation_from_string (const char *str, int len, return false; } +#ifndef HB_NO_SETLOCALE + +static inline void free_static_C_locale (); + +static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<hb_locale_t>, + hb_C_locale_lazy_loader_t> +{ + static hb_locale_t create () + { + hb_locale_t l = newlocale (LC_ALL_MASK, "C", NULL); + if (!l) + return l; + + hb_atexit (free_static_C_locale); + + return l; + } + static void destroy (hb_locale_t l) + { + freelocale (l); + } + static hb_locale_t get_null () + { + return (hb_locale_t) 0; + } +} static_C_locale; + +static inline +void free_static_C_locale () +{ + static_C_locale.free_instance (); +} + +static hb_locale_t +get_C_locale () +{ + return static_C_locale.get_unconst (); +} + +#endif + /** * hb_variation_to_string: * @variation: an #hb_variation_t to convert @@ -1064,7 +1126,11 @@ hb_variation_to_string (hb_variation_t *variation, while (len && s[len - 1] == ' ') len--; s[len++] = '='; + + hb_locale_t oldlocale HB_UNUSED; + oldlocale = hb_uselocale (get_C_locale ()); len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value)); + (void) hb_uselocale (oldlocale); assert (len < ARRAY_LENGTH (s)); len = hb_min (len, size - 1); diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc index a512f3b8b7..5f383064c4 100644 --- a/thirdparty/harfbuzz/src/hb-coretext.cc +++ b/thirdparty/harfbuzz/src/hb-coretext.cc @@ -481,8 +481,8 @@ struct active_feature_t { a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 : 0; } - bool operator== (const active_feature_t *f) { - return cmp (this, f) == 0; + bool operator== (const active_feature_t& f) const { + return cmp (this, &f) == 0; } }; @@ -677,7 +677,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, { active_features.push (event->feature); } else { - active_feature_t *feature = active_features.find (&event->feature); + active_feature_t *feature = active_features.lsearch (event->feature); if (feature) active_features.remove (feature - active_features.arrayZ); } @@ -1213,7 +1213,8 @@ resize_and_retry: } } - buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK); + buffer->clear_glyph_flags (); + buffer->unsafe_to_break (); #undef FAIL diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc index dea87b8cd0..f177ff31c0 100644 --- a/thirdparty/harfbuzz/src/hb-directwrite.cc +++ b/thirdparty/harfbuzz/src/hb-directwrite.cc @@ -762,7 +762,8 @@ retry_getglyphs: if (isRightToLeft) hb_buffer_reverse (buffer); - buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK); + buffer->clear_glyph_flags (); + buffer->unsafe_to_break (); delete [] clusterMap; delete [] glyphIndices; diff --git a/thirdparty/harfbuzz/src/hb-draw.h b/thirdparty/harfbuzz/src/hb-draw.h index bddc876399..f82cc34842 100644 --- a/thirdparty/harfbuzz/src/hb-draw.h +++ b/thirdparty/harfbuzz/src/hb-draw.h @@ -50,7 +50,7 @@ typedef void (*hb_draw_close_path_func_t) (void *user_data); * * Glyph draw callbacks. * - * _move_to, _line_to and _cubic_to calls are nessecary to be defined but we + * _move_to, _line_to and _cubic_to calls are necessary to be defined but we * translate _quadratic_to calls to _cubic_to if the callback isn't defined. * * Since: EXPERIMENTAL diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc index 2c0087370c..5365598636 100644 --- a/thirdparty/harfbuzz/src/hb-face.cc +++ b/thirdparty/harfbuzz/src/hb-face.cc @@ -143,7 +143,7 @@ hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, typedef struct hb_face_for_data_closure_t { hb_blob_t *blob; - unsigned int index; + uint16_t index; } hb_face_for_data_closure_t; static hb_face_for_data_closure_t * @@ -156,7 +156,7 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) return nullptr; closure->blob = blob; - closure->index = index; + closure->index = (uint16_t) (index & 0xFFFFu); return closure; } @@ -195,9 +195,19 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void * @index: The index of the face within @blob * * Constructs a new face object from the specified blob and - * a face index into that blob. This is used for blobs of - * file formats such as Dfont and TTC that can contain more - * than one face. + * a face index into that blob. + * + * The face index is used for blobs of file formats such as TTC and + * and DFont that can contain more than one face. Face indices within + * such collections are zero-based. + * + * <note>Note: If the blob font format is not a collection, @index + * is ignored. Otherwise, only the lower 16-bits of @index are used. + * The unmodified @index can be accessed via hb_face_get_index().</note> + * + * <note>Note: The high 16-bits of @index, if non-zero, are used by + * hb_font_create() to load named-instances in variable fonts. See + * hb_font_create() for details.</note> * * Return value: (transfer full): The new face object * @@ -420,7 +430,8 @@ hb_face_reference_blob (hb_face_t *face) * Assigns the specified face-index to @face. Fails if the * face is immutable. * - * <note>Note: face indices within a collection are zero-based.</note> + * <note>Note: changing the index has no effect on the face itself + * This only changes the value returned by hb_face_get_index().</note> * * Since: 0.9.2 **/ diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc index fa8da96395..350fcac139 100644 --- a/thirdparty/harfbuzz/src/hb-font.cc +++ b/thirdparty/harfbuzz/src/hb-font.cc @@ -631,7 +631,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * - * Attaches a user-data key/data pair to the specified font-functions structure. + * Attaches a user-data key/data pair to the specified font-functions structure. * * Return value: %true if success, %false otherwise * @@ -821,7 +821,7 @@ hb_font_get_glyph (hb_font_t *font, * @glyph: (out): The glyph ID retrieved * * Fetches the nominal glyph ID for a Unicode code point in the - * specified font. + * specified font. * * This version of the function should not be used to fetch glyph IDs * for code points modified by variation selectors. For variation-selector @@ -940,7 +940,7 @@ hb_font_get_glyph_v_advance (hb_font_t *font, * @advance_stride: The stride between successive advances * * Fetches the advances for a sequence of glyph IDs in the specified - * font, for horizontal text segments. + * font, for horizontal text segments. * * Since: 1.8.6 **/ @@ -964,7 +964,7 @@ hb_font_get_glyph_h_advances (hb_font_t* font, * @advance_stride: (out): The stride between successive advances * * Fetches the advances for a sequence of glyph IDs in the specified - * font, for vertical text segments. + * font, for vertical text segments. * * Since: 1.8.6 **/ @@ -1278,7 +1278,7 @@ hb_font_get_glyph_origin_for_direction (hb_font_t *font, * @font: #hb_font_t to work upon * @glyph: The glyph ID to query * @direction: The direction of the text segment - * @x: (inout): Input = The original X coordinate + * @x: (inout): Input = The original X coordinate * Output = The X coordinate plus the X-coordinate of the origin * @y: (inout): Input = The original Y coordinate * Output = The Y coordinate plus the Y-coordinate of the origin @@ -1306,7 +1306,7 @@ hb_font_add_glyph_origin_for_direction (hb_font_t *font, * @font: #hb_font_t to work upon * @glyph: The glyph ID to query * @direction: The direction of the text segment - * @x: (inout): Input = The original X coordinate + * @x: (inout): Input = The original X coordinate * Output = The X coordinate minus the X-coordinate of the origin * @y: (inout): Input = The original Y coordinate * Output = The Y coordinate minus the Y-coordinate of the origin @@ -1477,6 +1477,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) = 1000, /* x_scale */ 1000, /* y_scale */ + 0., /* slant */ + 0., /* slant_xy; */ 1<<16, /* x_mult */ 1<<16, /* y_mult */ @@ -1521,6 +1523,13 @@ _hb_font_create (hb_face_t *face) * * Constructs a new font object from the specified face. * + * <note>Note: If @face's index value (as passed to hb_face_create() + * has non-zero top 16-bits, those bits minus one are passed to + * hb_font_set_var_named_instance(), effectively loading a named-instance + * of a variable font, instead of the default-instance. This allows + * specifying which named-instance to load by default when creating the + * face.</note> + * * Return value: (transfer full): The new font object * * Since: 0.9.2 @@ -1535,6 +1544,11 @@ hb_font_create (hb_face_t *face) hb_ot_font_set_funcs (font); #endif +#ifndef HB_NO_VAR + if (face && face->index >> 16) + hb_font_set_var_named_instance (font, (face->index >> 16) - 1); +#endif + return font; } @@ -1578,6 +1592,7 @@ hb_font_create_sub_font (hb_font_t *parent) font->x_scale = parent->x_scale; font->y_scale = parent->y_scale; + font->slant = parent->slant; font->mults_changed (); font->x_ppem = parent->x_ppem; font->y_ppem = parent->y_ppem; @@ -1668,12 +1683,12 @@ hb_font_destroy (hb_font_t *font) /** * hb_font_set_user_data: (skip) * @font: #hb_font_t to work upon - * @key: The user-data key + * @key: The user-data key * @data: A pointer to the user data * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * - * Attaches a user-data key/data pair to the specified font object. + * Attaches a user-data key/data pair to the specified font object. * * Return value: %true if success, %false otherwise * @@ -1875,7 +1890,7 @@ hb_font_set_funcs (hb_font_t *font, * @font_data: (destroy destroy) (scope notified): Data to attach to @font * @destroy: (nullable): The function to call when @font_data is not needed anymore * - * Replaces the user data attached to a font, updating the font's + * Replaces the user data attached to a font, updating the font's * @destroy callback. * * Since: 0.9.2 @@ -1949,7 +1964,7 @@ hb_font_get_scale (hb_font_t *font, * @x_ppem: Horizontal ppem value to assign * @y_ppem: Vertical ppem value to assign * - * Sets the horizontal and vertical pixels-per-em (ppem) of a font. + * Sets the horizontal and vertical pixels-per-em (ppem) of a font. * * Since: 0.9.2 **/ @@ -1971,7 +1986,7 @@ hb_font_set_ppem (hb_font_t *font, * @x_ppem: (out): Horizontal ppem value * @y_ppem: (out): Vertical ppem value * - * Fetches the horizontal and vertical points-per-em (ppem) of a font. + * Fetches the horizontal and vertical points-per-em (ppem) of a font. * * Since: 0.9.2 **/ @@ -2015,7 +2030,7 @@ hb_font_set_ptem (hb_font_t *font, * * Return value: Point size. A value of zero means "not set." * - * Since: 0.9.2 + * Since: 1.6.0 **/ float hb_font_get_ptem (hb_font_t *font) @@ -2023,6 +2038,49 @@ hb_font_get_ptem (hb_font_t *font) return font->ptem; } +/** + * hb_font_set_synthetic_slant: + * @font: #hb_font_t to work upon + * @slant: synthetic slant value. + * + * Sets the "synthetic slant" of a font. By default is zero. + * Synthetic slant is the graphical skew that the renderer + * applies to the font at rendering time. + * + * HarfBuzz needs to know this value to adjust shaping results, + * metrics, and style values to match the slanted rendering. + * + * <note>Note: The slant value is a ratio. For example, a + * 20% slant would be represented as a 0.2 value.</note> + * + * Since: 3.3.0 + **/ +HB_EXTERN void +hb_font_set_synthetic_slant (hb_font_t *font, float slant) +{ + if (hb_object_is_immutable (font)) + return; + + font->slant = slant; + font->mults_changed (); +} + +/** + * hb_font_get_synthetic_slant: + * @font: #hb_font_t to work upon + * + * Fetches the "synthetic slant" of a font. + * + * Return value: Synthetic slant. By default is zero. + * + * Since: 3.3.0 + **/ +HB_EXTERN float +hb_font_get_synthetic_slant (hb_font_t *font) +{ + return font->slant; +} + #ifndef HB_NO_VAR /* * Variations @@ -2036,6 +2094,10 @@ hb_font_get_ptem (hb_font_t *font) * * Applies a list of font-variation settings to a font. * + * Note that this overrides all existing variations set on @font. + * Axes not included in @variations will be effectively set to their + * default values. + * * Since: 1.4.2 */ void @@ -2091,6 +2153,10 @@ hb_font_set_variations (hb_font_t *font, * Applies a list of variation coordinates (in design-space units) * to a font. * + * Note that this overrides all existing variations set on @font. + * Axes not included in @coords will be effectively set to their + * default values. + * * Since: 1.4.2 */ void @@ -2154,6 +2220,10 @@ hb_font_set_var_named_instance (hb_font_t *font, * Applies a list of variation coordinates (in normalized units) * to a font. * + * Note that this overrides all existing variations set on @font. + * Axes not included in @coords will be effectively set to their + * default values. + * * <note>Note: Coordinates should be normalized to 2.14.</note> * * Since: 1.4.2 @@ -2196,14 +2266,19 @@ hb_font_set_var_coords_normalized (hb_font_t *font, /** * hb_font_get_var_coords_normalized: * @font: #hb_font_t to work upon - * @length: Number of coordinates retrieved + * @length: (out): Number of coordinates retrieved * * Fetches the list of normalized variation coordinates currently * set on a font. * + * Note that this returned array may only contain values for some + * (or none) of the axes; omitted axes effectively have zero values. + * * Return value is valid as long as variation coordinates of the font * are not modified. * + * Return value: coordinates array + * * Since: 1.4.2 */ const int * @@ -2216,18 +2291,24 @@ hb_font_get_var_coords_normalized (hb_font_t *font, return font->coords; } -#ifdef HB_EXPERIMENTAL_API /** * hb_font_get_var_coords_design: * @font: #hb_font_t to work upon - * @length: (out): number of coordinates + * @length: (out): Number of coordinates retrieved + * + * Fetches the list of variation coordinates (in design-space units) currently + * set on a font. + * + * Note that this returned array may only contain values for some + * (or none) of the axes; omitted axes effectively have their default + * values. * * Return value is valid as long as variation coordinates of the font * are not modified. * * Return value: coordinates array * - * Since: EXPERIMENTAL + * Since: 3.3.0 */ const float * hb_font_get_var_coords_design (hb_font_t *font, @@ -2239,7 +2320,6 @@ hb_font_get_var_coords_design (hb_font_t *font, return font->design_coords; } #endif -#endif #ifndef HB_DISABLE_DEPRECATED /* diff --git a/thirdparty/harfbuzz/src/hb-font.h b/thirdparty/harfbuzz/src/hb-font.h index 15dc126523..a3bbb2e37b 100644 --- a/thirdparty/harfbuzz/src/hb-font.h +++ b/thirdparty/harfbuzz/src/hb-font.h @@ -1024,6 +1024,12 @@ HB_EXTERN float hb_font_get_ptem (hb_font_t *font); HB_EXTERN void +hb_font_set_synthetic_slant (hb_font_t *font, float slant); + +HB_EXTERN float +hb_font_get_synthetic_slant (hb_font_t *font); + +HB_EXTERN void hb_font_set_variations (hb_font_t *font, const hb_variation_t *variations, unsigned int variations_length); @@ -1033,11 +1039,9 @@ hb_font_set_var_coords_design (hb_font_t *font, const float *coords, unsigned int coords_length); -#ifdef HB_EXPERIMENTAL_API HB_EXTERN const float * hb_font_get_var_coords_design (hb_font_t *font, unsigned int *length); -#endif HB_EXTERN void hb_font_set_var_coords_normalized (hb_font_t *font, diff --git a/thirdparty/harfbuzz/src/hb-font.hh b/thirdparty/harfbuzz/src/hb-font.hh index 1b7f445e8b..0d73589e8c 100644 --- a/thirdparty/harfbuzz/src/hb-font.hh +++ b/thirdparty/harfbuzz/src/hb-font.hh @@ -109,6 +109,8 @@ struct hb_font_t int32_t x_scale; int32_t y_scale; + float slant; + float slant_xy; int64_t x_mult; int64_t y_mult; @@ -617,6 +619,7 @@ struct hb_font_t signed upem = face->get_upem (); x_mult = ((int64_t) x_scale << 16) / upem; y_mult = ((int64_t) y_scale << 16) / upem; + slant_xy = y_scale ? slant * x_scale / y_scale : 0.f; } hb_position_t em_mult (int16_t v, int64_t mult) diff --git a/thirdparty/harfbuzz/src/hb-graphite2.cc b/thirdparty/harfbuzz/src/hb-graphite2.cc index 42420ac0b0..63dc18b466 100644 --- a/thirdparty/harfbuzz/src/hb-graphite2.cc +++ b/thirdparty/harfbuzz/src/hb-graphite2.cc @@ -439,7 +439,8 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, if (feats) gr_featureval_destroy (feats); gr_seg_destroy (seg); - buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK); + buffer->clear_glyph_flags (); + buffer->unsafe_to_break (); return true; } diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh index ad2e45e3c5..43a3098f65 100644 --- a/thirdparty/harfbuzz/src/hb-iter.hh +++ b/thirdparty/harfbuzz/src/hb-iter.hh @@ -90,8 +90,8 @@ struct hb_iter_t * it will be returning pointer to temporary rvalue. * TODO Use a wrapper return type to fix for non-reference type. */ template <typename T = item_t, - hb_enable_if (hb_is_reference (T))> - hb_remove_reference<item_t>* operator -> () const { return hb_addressof (**thiz()); } + hb_enable_if (std::is_reference<T>::value)> + hb_remove_reference<item_t>* operator -> () const { return std::addressof (**thiz()); } item_t operator * () const { return thiz()->__item__ (); } item_t operator * () { return thiz()->__item__ (); } item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); } @@ -289,7 +289,7 @@ struct hb_is_source_of { private: template <typename Iter2 = Iter, - hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<hb_add_const<Item>>))> + hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<const Item>))> static hb_true_type impl (hb_priority<2>); template <typename Iter2 = Iter> static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) >> hb_declval (Item &), hb_true_type ()); diff --git a/thirdparty/harfbuzz/src/hb-kern.hh b/thirdparty/harfbuzz/src/hb-kern.hh index 3f952fe7fc..9ea945caed 100644 --- a/thirdparty/harfbuzz/src/hb-kern.hh +++ b/thirdparty/harfbuzz/src/hb-kern.hh @@ -49,6 +49,10 @@ struct hb_kern_machine_t hb_mask_t kern_mask, bool scale = true) const { + if (!buffer->message (font, "start kern")) + return; + + buffer->unsafe_to_concat (); OT::hb_ot_apply_context_t c (1, font, buffer); c.set_lookup_mask (kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); @@ -67,7 +71,8 @@ struct hb_kern_machine_t } skippy_iter.reset (idx, 1); - if (!skippy_iter.next ()) + unsigned unsafe_to; + if (!skippy_iter.next (&unsafe_to)) { idx++; continue; @@ -125,6 +130,8 @@ struct hb_kern_machine_t skip: idx = skippy_iter.idx; } + + (void) buffer->message (font, "end kern"); } const Driver &driver; diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh index 010c2570d7..5046ac1933 100644 --- a/thirdparty/harfbuzz/src/hb-machinery.hh +++ b/thirdparty/harfbuzz/src/hb-machinery.hh @@ -244,19 +244,19 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData> { Stored *p = (Stored *) hb_calloc (1, sizeof (Stored)); if (likely (p)) - p->init (data); + p = new (p) Stored (data); return p; } static Stored *create () { Stored *p = (Stored *) hb_calloc (1, sizeof (Stored)); if (likely (p)) - p->init (); + p = new (p) Stored (); return p; } static void destroy (Stored *p) { - p->fini (); + p->~Stored (); hb_free (p); } diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh index 793dcf22ca..9341637eac 100644 --- a/thirdparty/harfbuzz/src/hb-map.hh +++ b/thirdparty/harfbuzz/src/hb-map.hh @@ -37,13 +37,10 @@ template <typename K, typename V, typename k_invalid_t = K, typename v_invalid_t = V, - k_invalid_t kINVALID = hb_is_pointer (K) ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1, - v_invalid_t vINVALID = hb_is_pointer (V) ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1> + k_invalid_t kINVALID = std::is_pointer<K>::value ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1, + v_invalid_t vINVALID = std::is_pointer<V>::value ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1> struct hb_hashmap_t { - static constexpr K INVALID_KEY = kINVALID; - static constexpr V INVALID_VALUE = vINVALID; - hb_hashmap_t () { init (); } ~hb_hashmap_t () { fini (); } @@ -64,24 +61,40 @@ struct hb_hashmap_t hb_copy (o, *this); } - static_assert (std::is_trivially_copyable<K>::value, ""); - static_assert (std::is_trivially_copyable<V>::value, ""); - static_assert (std::is_trivially_destructible<K>::value, ""); - static_assert (std::is_trivially_destructible<V>::value, ""); - struct item_t { K key; V value; uint32_t hash; - void clear () { key = kINVALID; value = vINVALID; hash = 0; } + void clear () + { + new (std::addressof (key)) K (); + key = hb_coerce<K> (kINVALID); + new (std::addressof (value)) V (); + value = hb_coerce<V> (vINVALID); + hash = 0; + } bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); } bool operator == (const item_t &o) { return *this == o.key; } - bool is_unused () const { return key == kINVALID; } - bool is_tombstone () const { return key != kINVALID && value == vINVALID; } - bool is_real () const { return key != kINVALID && value != vINVALID; } + bool is_unused () const + { + const K inv = hb_coerce<K> (kINVALID); + return key == inv; + } + bool is_tombstone () const + { + const K kinv = hb_coerce<K> (kINVALID); + const V vinv = hb_coerce<V> (vINVALID); + return key != kinv && value == vinv; + } + bool is_real () const + { + const K kinv = hb_coerce<K> (kINVALID); + const V vinv = hb_coerce<V> (vINVALID); + return key != kinv && value != vinv; + } hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); } }; @@ -118,8 +131,13 @@ struct hb_hashmap_t } void fini_shallow () { - hb_free (items); - items = nullptr; + if (likely (items)) { + unsigned size = mask + 1; + for (unsigned i = 0; i < size; i++) + items[i].~item_t (); + hb_free (items); + items = nullptr; + } population = occupancy = 0; } void fini () @@ -163,10 +181,15 @@ struct hb_hashmap_t /* Insert back old items. */ if (old_items) for (unsigned int i = 0; i < old_size; i++) + { if (old_items[i].is_real ()) + { set_with_hash (old_items[i].key, old_items[i].hash, std::move (old_items[i].value)); + } + old_items[i].~item_t (); + } hb_free (old_items); @@ -178,22 +201,22 @@ struct hb_hashmap_t V get (K key) const { - if (unlikely (!items)) return vINVALID; + if (unlikely (!items)) return hb_coerce<V> (vINVALID); unsigned int i = bucket_for (key); - return items[i].is_real () && items[i] == key ? items[i].value : vINVALID; + return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID); } - void del (K key) { set (key, vINVALID); } + void del (K key) { set (key, hb_coerce<V> (vINVALID)); } /* Has interface. */ - static constexpr V SENTINEL = vINVALID; typedef V value_t; value_t operator [] (K k) const { return get (k); } bool has (K k, V *vp = nullptr) const { V v = (*this)[k]; if (vp) *vp = v; - return v != SENTINEL; + const V vinv = hb_coerce<V> (vINVALID); + return v != vinv; } /* Projection. */ V operator () (K k) const { return get (k); } @@ -248,11 +271,13 @@ struct hb_hashmap_t bool set_with_hash (K key, uint32_t hash, VV&& value) { if (unlikely (!successful)) return false; - if (unlikely (key == kINVALID)) return true; + const K kinv = hb_coerce<K> (kINVALID); + if (unlikely (key == kinv)) return true; if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; unsigned int i = bucket_for_hash (key, hash); - if (value == vINVALID && items[i].key != key) + const V vinv = hb_coerce<V> (vINVALID); + if (value == vinv && items[i].key != key) return true; /* Trying to delete non-existent key. */ if (!items[i].is_unused ()) diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh index 0ea5774a9f..3fea5d995e 100644 --- a/thirdparty/harfbuzz/src/hb-meta.hh +++ b/thirdparty/harfbuzz/src/hb-meta.hh @@ -29,6 +29,7 @@ #include "hb.hh" +#include <memory> #include <type_traits> #include <utility> @@ -85,30 +86,13 @@ template <> struct hb_priority<0> {}; template <typename T> struct hb_type_identity_t { typedef T type; }; template <typename T> using hb_type_identity = typename hb_type_identity_t<T>::type; -struct -{ - template <typename T> constexpr T* - operator () (T& arg) const - { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-align" - /* https://en.cppreference.com/w/cpp/memory/addressof */ - return reinterpret_cast<T*> ( - &const_cast<char&> ( - reinterpret_cast<const volatile char&> (arg))); -#pragma GCC diagnostic pop - } -} -HB_FUNCOBJ (hb_addressof); - template <typename T> static inline T hb_declval (); #define hb_declval(T) (hb_declval<T> ()) template <typename T> struct hb_match_const : hb_type_identity_t<T>, hb_false_type {}; template <typename T> struct hb_match_const<const T> : hb_type_identity_t<T>, hb_true_type {}; template <typename T> using hb_remove_const = typename hb_match_const<T>::type; -template <typename T> using hb_add_const = const T; -#define hb_is_const(T) hb_match_const<T>::value + template <typename T> struct hb_match_reference : hb_type_identity_t<T>, hb_false_type {}; template <typename T> struct hb_match_reference<T &> : hb_type_identity_t<T>, hb_true_type {}; template <typename T> struct hb_match_reference<T &&> : hb_type_identity_t<T>, hb_true_type {}; @@ -119,14 +103,13 @@ template <typename T> using hb_add_lvalue_reference = decltype (_hb_try_add_lval template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_type_identity<T&&>; template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity<T>; template <typename T> using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference<T> (hb_prioritize)); -#define hb_is_reference(T) hb_match_reference<T>::value + template <typename T> struct hb_match_pointer : hb_type_identity_t<T>, hb_false_type {}; template <typename T> struct hb_match_pointer<T *> : hb_type_identity_t<T>, hb_true_type {}; template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type; template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<hb_remove_reference<T>*>; template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<T>; template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (hb_prioritize)); -#define hb_is_pointer(T) hb_match_pointer<T>::value /* TODO Add feature-parity to std::decay. */ @@ -137,8 +120,8 @@ template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>; template <typename From, typename To> using hb_is_cr_convertible = hb_bool_constant< hb_is_same (hb_decay<From>, hb_decay<To>) && - (!hb_is_const (From) || hb_is_const (To)) && - (!hb_is_reference (To) || hb_is_const (To) || hb_is_reference (To)) + (!std::is_const<From>::value || std::is_const<To>::value) && + (!std::is_reference<To>::value || std::is_const<To>::value || std::is_reference<To>::value) >; #define hb_is_cr_convertible(From,To) hb_is_cr_convertible<From, To>::value @@ -153,16 +136,6 @@ struct } HB_FUNCOBJ (hb_deref); -struct -{ - template <typename T> constexpr auto - operator () (T&& v) const HB_AUTO_RETURN (std::forward<T> (v)) - - template <typename T> constexpr auto - operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v)) -} -HB_FUNCOBJ (hb_ref); - template <typename T> struct hb_reference_wrapper { @@ -176,7 +149,7 @@ struct hb_reference_wrapper template <typename T> struct hb_reference_wrapper<T&> { - hb_reference_wrapper (T& v) : v (hb_addressof (v)) {} + hb_reference_wrapper (T& v) : v (std::addressof (v)) {} bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } operator T& () const { return *v; } diff --git a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.cc b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.cc deleted file mode 100644 index 6d09b252d8..0000000000 --- a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.cc +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright © 2011,2012,2013 Google, Inc. - * Copyright © 2021 Khaled Hosny - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Google Author(s): Behdad Esfahbod - */ - -#include "hb-ms-feature-ranges.hh" - -bool -hb_ms_setup_features (const hb_feature_t *features, - unsigned int num_features, - hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */ - hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */) -{ - feature_records.shrink(0); - range_records.shrink(0); - - /* Sort features by start/end events. */ - hb_vector_t<hb_ms_feature_event_t> feature_events; - for (unsigned int i = 0; i < num_features; i++) - { - hb_ms_active_feature_t feature; - feature.fea.tag_le = hb_uint32_swap (features[i].tag); - feature.fea.value = features[i].value; - feature.order = i; - - hb_ms_feature_event_t *event; - - event = feature_events.push (); - event->index = features[i].start; - event->start = true; - event->feature = feature; - - event = feature_events.push (); - event->index = features[i].end; - event->start = false; - event->feature = feature; - } - feature_events.qsort (); - /* Add a strategic final event. */ - { - hb_ms_active_feature_t feature; - feature.fea.tag_le = 0; - feature.fea.value = 0; - feature.order = num_features + 1; - - auto *event = feature_events.push (); - event->index = 0; /* This value does magic. */ - event->start = false; - event->feature = feature; - } - - /* Scan events and save features for each range. */ - hb_vector_t<hb_ms_active_feature_t> active_features; - unsigned int last_index = 0; - for (unsigned int i = 0; i < feature_events.length; i++) - { - auto *event = &feature_events[i]; - - if (event->index != last_index) - { - /* Save a snapshot of active features and the range. */ - auto *range = range_records.push (); - auto offset = feature_records.length; - - active_features.qsort (); - for (unsigned int j = 0; j < active_features.length; j++) - { - if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le) - { - feature_records.push (active_features[j].fea); - } - else - { - /* Overrides value for existing feature. */ - feature_records[feature_records.length - 1].value = active_features[j].fea.value; - } - } - - /* Will convert to pointer after all is ready, since feature_records.array - * may move as we grow it. */ - range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset); - range->features.num_features = feature_records.length - offset; - range->index_first = last_index; - range->index_last = event->index - 1; - - last_index = event->index; - } - - if (event->start) - { - active_features.push (event->feature); - } - else - { - auto *feature = active_features.find (&event->feature); - if (feature) - active_features.remove (feature - active_features.arrayZ); - } - } - - if (!range_records.length) /* No active feature found. */ - num_features = 0; - - /* Fixup the pointers. */ - for (unsigned int i = 0; i < range_records.length; i++) - { - auto *range = &range_records[i]; - range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features); - } - - return !!num_features; -} - -void -hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records, - hb_vector_t<hb_ms_range_record_t> &range_records, - unsigned int chars_offset, - unsigned int chars_len, - uint16_t *log_clusters, - hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */ - hb_vector_t<uint32_t> &range_counts /* OUT */) -{ - range_features.shrink (0); - range_counts.shrink (0); - - auto *last_range = &range_records[0]; - for (unsigned int i = chars_offset; i < chars_len; i++) - { - auto *range = last_range; - while (log_clusters[i] < range->index_first) - range--; - while (log_clusters[i] > range->index_last) - range++; - if (!range_features.length || - &range->features != range_features[range_features.length - 1]) - { - auto **features = range_features.push (); - auto *c = range_counts.push (); - if (unlikely (!features || !c)) - { - range_features.shrink (0); - range_counts.shrink (0); - break; - } - *features = &range->features; - *c = 1; - } - else - { - range_counts[range_counts.length - 1]++; - } - - last_range = range; - } -} diff --git a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh index 401d1e1d97..d40fdeaa82 100644 --- a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh +++ b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh @@ -52,8 +52,8 @@ struct hb_ms_active_feature_t { a->fea.value < b->fea.value ? -1 : a->fea.value > b->fea.value ? 1 : 0; } - bool operator== (const hb_ms_active_feature_t *f) - { return cmp (this, f) == 0; } + bool operator== (const hb_ms_active_feature_t& f) const + { return cmp (this, &f) == 0; } }; struct hb_ms_feature_event_t { @@ -77,20 +77,153 @@ struct hb_ms_range_record_t { unsigned int index_last; /* == end - 1 */ }; -HB_INTERNAL bool +static inline bool hb_ms_setup_features (const hb_feature_t *features, unsigned int num_features, hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */ - hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */); + hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */) +{ + feature_records.shrink(0); + range_records.shrink(0); + /* Sort features by start/end events. */ + hb_vector_t<hb_ms_feature_event_t> feature_events; + for (unsigned int i = 0; i < num_features; i++) + { + hb_ms_active_feature_t feature; + feature.fea.tag_le = hb_uint32_swap (features[i].tag); + feature.fea.value = features[i].value; + feature.order = i; + + hb_ms_feature_event_t *event; + + event = feature_events.push (); + event->index = features[i].start; + event->start = true; + event->feature = feature; + + event = feature_events.push (); + event->index = features[i].end; + event->start = false; + event->feature = feature; + } + feature_events.qsort (); + /* Add a strategic final event. */ + { + hb_ms_active_feature_t feature; + feature.fea.tag_le = 0; + feature.fea.value = 0; + feature.order = num_features + 1; + + auto *event = feature_events.push (); + event->index = 0; /* This value does magic. */ + event->start = false; + event->feature = feature; + } + + /* Scan events and save features for each range. */ + hb_vector_t<hb_ms_active_feature_t> active_features; + unsigned int last_index = 0; + for (unsigned int i = 0; i < feature_events.length; i++) + { + auto *event = &feature_events[i]; + + if (event->index != last_index) + { + /* Save a snapshot of active features and the range. */ + auto *range = range_records.push (); + auto offset = feature_records.length; + + active_features.qsort (); + for (unsigned int j = 0; j < active_features.length; j++) + { + if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le) + { + feature_records.push (active_features[j].fea); + } + else + { + /* Overrides value for existing feature. */ + feature_records[feature_records.length - 1].value = active_features[j].fea.value; + } + } + + /* Will convert to pointer after all is ready, since feature_records.array + * may move as we grow it. */ + range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset); + range->features.num_features = feature_records.length - offset; + range->index_first = last_index; + range->index_last = event->index - 1; -HB_INTERNAL void + last_index = event->index; + } + + if (event->start) + { + active_features.push (event->feature); + } + else + { + auto *feature = active_features.lsearch (event->feature); + if (feature) + active_features.remove (feature - active_features.arrayZ); + } + } + + if (!range_records.length) /* No active feature found. */ + num_features = 0; + + /* Fixup the pointers. */ + for (unsigned int i = 0; i < range_records.length; i++) + { + auto *range = &range_records[i]; + range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features); + } + + return !!num_features; +} + +static inline void hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records, hb_vector_t<hb_ms_range_record_t> &range_records, unsigned int chars_offset, unsigned int chars_len, uint16_t *log_clusters, hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */ - hb_vector_t<uint32_t> &range_counts /* OUT */); + hb_vector_t<uint32_t> &range_counts /* OUT */) +{ + range_features.shrink (0); + range_counts.shrink (0); + + auto *last_range = &range_records[0]; + for (unsigned int i = chars_offset; i < chars_len; i++) + { + auto *range = last_range; + while (log_clusters[i] < range->index_first) + range--; + while (log_clusters[i] > range->index_last) + range++; + if (!range_features.length || + &range->features != range_features[range_features.length - 1]) + { + auto **features = range_features.push (); + auto *c = range_counts.push (); + if (unlikely (!features || !c)) + { + range_features.shrink (0); + range_counts.shrink (0); + break; + } + *features = &range->features; + *c = 1; + } + else + { + range_counts[range_counts.length - 1]++; + } + + last_range = range; + } +} #endif /* HB_MS_FEATURE_RANGES_HH */ diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh index 0e15cb12c4..4b5bc32ade 100644 --- a/thirdparty/harfbuzz/src/hb-object.hh +++ b/thirdparty/harfbuzz/src/hb-object.hh @@ -53,7 +53,7 @@ struct hb_lockable_set_t item_t *replace_or_insert (T v, lock_t &l, bool replace) { l.lock (); - item_t *item = items.find (v); + item_t *item = items.lsearch (v); if (item) { if (replace) { item_t old = *item; @@ -76,7 +76,7 @@ struct hb_lockable_set_t void remove (T v, lock_t &l) { l.lock (); - item_t *item = items.find (v); + item_t *item = items.lsearch (v); if (item) { item_t old = *item; @@ -93,7 +93,7 @@ struct hb_lockable_set_t bool find (T v, item_t *i, lock_t &l) { l.lock (); - item_t *item = items.find (v); + item_t *item = items.lsearch (v); if (item) *i = *item; l.unlock (); diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh index 180c87cb89..c102c15173 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh @@ -68,8 +68,6 @@ struct code_pair_t typedef hb_vector_t<unsigned char> str_buff_t; struct str_buff_vec_t : hb_vector_t<str_buff_t> { - void fini () { SUPER::fini_deep (); } - unsigned int total_size () const { unsigned int size = 0; diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh index 5dd183e3a0..6fb59315c9 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh @@ -1144,8 +1144,8 @@ struct cff1 { sc.end_processing (); topDict.fini (); - fontDicts.fini_deep (); - privateDicts.fini_deep (); + fontDicts.fini (); + privateDicts.fini (); hb_blob_destroy (blob); blob = nullptr; } @@ -1245,32 +1245,32 @@ struct cff1 } protected: - hb_blob_t *blob; + hb_blob_t *blob = nullptr; hb_sanitize_context_t sc; public: - const Encoding *encoding; - const Charset *charset; - const CFF1NameIndex *nameIndex; - const CFF1TopDictIndex *topDictIndex; - const CFF1StringIndex *stringIndex; - const CFF1Subrs *globalSubrs; - const CFF1CharStrings *charStrings; - const CFF1FDArray *fdArray; - const CFF1FDSelect *fdSelect; - unsigned int fdCount; + const Encoding *encoding = nullptr; + const Charset *charset = nullptr; + const CFF1NameIndex *nameIndex = nullptr; + const CFF1TopDictIndex *topDictIndex = nullptr; + const CFF1StringIndex *stringIndex = nullptr; + const CFF1Subrs *globalSubrs = nullptr; + const CFF1CharStrings *charStrings = nullptr; + const CFF1FDArray *fdArray = nullptr; + const CFF1FDSelect *fdSelect = nullptr; + unsigned int fdCount = 0; cff1_top_dict_values_t topDict; hb_vector_t<cff1_font_dict_values_t> fontDicts; hb_vector_t<PRIVDICTVAL> privateDicts; - unsigned int num_glyphs; + unsigned int num_glyphs = 0; }; struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { SUPER::init (face); @@ -1295,8 +1295,7 @@ struct cff1 } glyph_names.qsort (); } - - void fini () + ~accelerator_t () { glyph_names.fini (); @@ -1398,7 +1397,10 @@ struct cff1 DEFINE_SIZE_STATIC (4); }; -struct cff1_accelerator_t : cff1::accelerator_t {}; +struct cff1_accelerator_t : cff1::accelerator_t { + cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF1_TABLE_HH */ diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh index 829217feaa..6e1b01c8fe 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh @@ -397,7 +397,7 @@ struct cff2 template <typename PRIVOPSET, typename PRIVDICTVAL> struct accelerator_templ_t { - void init (hb_face_t *face) + accelerator_templ_t (hb_face_t *face) { topDict.init (); fontDicts.init (); @@ -412,15 +412,15 @@ struct cff2 const OT::cff2 *cff2 = this->blob->template as<OT::cff2> (); if (cff2 == &Null (OT::cff2)) - { fini (); return; } + goto fail; { /* parse top dict */ byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize); - if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!topDictStr.sanitize (&sc))) goto fail; cff2_top_dict_interpreter_t top_interp; top_interp.env.init (topDictStr); topDict.init (); - if (unlikely (!top_interp.interpret (topDict))) { fini (); return; } + if (unlikely (!top_interp.interpret (topDict))) goto fail; } globalSubrs = &StructAtOffset<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize); @@ -434,49 +434,55 @@ struct cff2 (globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) || (fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) || (((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count))))) - { fini (); return; } + goto fail; num_glyphs = charStrings->count; if (num_glyphs != sc.get_num_glyphs ()) - { fini (); return; } + goto fail; fdCount = fdArray->count; if (!privateDicts.resize (fdCount)) - { fini (); return; } + goto fail; /* parse font dicts and gather private dicts */ for (unsigned int i = 0; i < fdCount; i++) { const byte_str_t fontDictStr = (*fdArray)[i]; - if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; cff2_font_dict_values_t *font; cff2_font_dict_interpreter_t font_interp; font_interp.env.init (fontDictStr); font = fontDicts.push (); - if (unlikely (font == &Crap (cff2_font_dict_values_t))) { fini (); return; } + if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail; font->init (); - if (unlikely (!font_interp.interpret (*font))) { fini (); return; } + if (unlikely (!font_interp.interpret (*font))) goto fail; const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!privDictStr.sanitize (&sc))) goto fail; dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp; priv_interp.env.init(privDictStr); privateDicts[i].init (); - if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; } + if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail; privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset); if (privateDicts[i].localSubrs != &Null (CFF2Subrs) && unlikely (!privateDicts[i].localSubrs->sanitize (&sc))) - { fini (); return; } + goto fail; } - } - void fini () + + return; + + fail: + _fini (); + } + ~accelerator_templ_t () { _fini (); } + void _fini () { sc.end_processing (); topDict.fini (); - fontDicts.fini_deep (); - privateDicts.fini_deep (); + fontDicts.fini (); + privateDicts.fini (); hb_blob_destroy (blob); blob = nullptr; } @@ -484,26 +490,28 @@ struct cff2 bool is_valid () const { return blob; } protected: - hb_blob_t *blob; + hb_blob_t *blob = nullptr; hb_sanitize_context_t sc; public: cff2_top_dict_values_t topDict; - const CFF2Subrs *globalSubrs; - const CFF2VariationStore *varStore; - const CFF2CharStrings *charStrings; - const CFF2FDArray *fdArray; - const CFF2FDSelect *fdSelect; - unsigned int fdCount; + const CFF2Subrs *globalSubrs = nullptr; + const CFF2VariationStore *varStore = nullptr; + const CFF2CharStrings *charStrings = nullptr; + const CFF2FDArray *fdArray = nullptr; + const CFF2FDSelect *fdSelect = nullptr; + unsigned int fdCount = 0; hb_vector_t<cff2_font_dict_values_t> fontDicts; hb_vector_t<PRIVDICTVAL> privateDicts; - unsigned int num_glyphs; + unsigned int num_glyphs = 0; }; struct accelerator_t : accelerator_templ_t<cff2_private_dict_opset_t, cff2_private_dict_values_t> { + accelerator_t (hb_face_t *face) : accelerator_templ_t (face) {} + HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; @@ -525,7 +533,10 @@ struct cff2 DEFINE_SIZE_STATIC (5); }; -struct cff2_accelerator_t : cff2::accelerator_t {}; +struct cff2_accelerator_t : cff2::accelerator_t { + cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF2_TABLE_HH */ diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh index d837adc788..fde57cdc5b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh @@ -369,7 +369,6 @@ struct CmapSubtableFormat4 { accelerator_t () {} accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); } - ~accelerator_t () { fini (); } void init (const CmapSubtableFormat4 *subtable) { @@ -381,7 +380,6 @@ struct CmapSubtableFormat4 glyphIdArray = idRangeOffset + segCount; glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2; } - void fini () {} bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { @@ -1607,7 +1605,7 @@ struct cmap unsigned format = (this + _.subtable).u.format; if (format == 12) has_format12 = true; - const EncodingRecord *table = hb_addressof (_); + const EncodingRecord *table = std::addressof (_); if (_.platformID == 0 && _.encodingID == 3) unicode_bmp = table; else if (_.platformID == 0 && _.encodingID == 4) unicode_ucs4 = table; else if (_.platformID == 3 && _.encodingID == 1) ms_bmp = table; @@ -1665,7 +1663,7 @@ struct cmap struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { this->table = hb_sanitize_context_t ().reference_table<cmap> (face); bool symbol; @@ -1700,8 +1698,7 @@ struct cmap } } } - - void fini () { this->table.destroy (); } + ~accelerator_t () { this->table.destroy (); } bool get_nominal_glyph (hb_codepoint_t unicode, hb_codepoint_t *glyph) const @@ -1863,7 +1860,9 @@ struct cmap DEFINE_SIZE_ARRAY (4, encodingRecord); }; -struct cmap_accelerator_t : cmap::accelerator_t {}; +struct cmap_accelerator_t : cmap::accelerator_t { + cmap_accelerator_t (hb_face_t *face) : cmap::accelerator_t (face) {} +}; } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh index 14459914ee..23fa56c4f6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh @@ -360,6 +360,16 @@ struct IndexSubtable struct IndexSubtableRecord { + /* XXX Remove this and fix by not inserting it into vector. */ + IndexSubtableRecord& operator = (const IndexSubtableRecord &o) + { + firstGlyphIndex = o.firstGlyphIndex; + lastGlyphIndex = o.lastGlyphIndex; + offsetToSubtable = (unsigned) o.offsetToSubtable; + assert (offsetToSubtable.is_null ()); + return *this; + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -809,15 +819,14 @@ struct CBDT struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { - cblc = hb_sanitize_context_t ().reference_table<CBLC> (face); - cbdt = hb_sanitize_context_t ().reference_table<CBDT> (face); + this->cblc = hb_sanitize_context_t ().reference_table<CBLC> (face); + this->cbdt = hb_sanitize_context_t ().reference_table<CBDT> (face); upem = hb_face_get_upem (face); } - - void fini () + ~accelerator_t () { this->cblc.destroy (); this->cbdt.destroy (); @@ -978,7 +987,10 @@ CBLC::subset (hb_subset_context_t *c) const return_trace (CBLC::sink_cbdt (c, &cbdt_prime)); } -struct CBDT_accelerator_t : CBDT::accelerator_t {}; +struct CBDT_accelerator_t : CBDT::accelerator_t { + CBDT_accelerator_t (hb_face_t *face) : CBDT::accelerator_t (face) {} +}; + } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh index 008422d089..dac755c02c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh @@ -71,7 +71,7 @@ struct hb_colrv1_closure_context_t : bool paint_visited (const void *paint) { hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) paint - (uintptr_t) base); - if (visited_paint.has (delta)) + if (visited_paint.in_error() || visited_paint.has (delta)) return true; visited_paint.add (delta); @@ -1270,13 +1270,9 @@ struct COLR struct accelerator_t { - accelerator_t () {} - ~accelerator_t () { fini (); } - - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { colr = hb_sanitize_context_t ().reference_table<COLR> (face); } - - void fini () { this->colr.destroy (); } + ~accelerator_t () { this->colr.destroy (); } bool is_valid () { return colr.get_blob ()->length; } @@ -1535,6 +1531,10 @@ struct COLR DEFINE_SIZE_MIN (14); }; +struct COLR_accelerator_t : COLR::accelerator_t { + COLR_accelerator_t (hb_face_t *face) : COLR::accelerator_t (face) {} +}; + } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh b/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh index ca85ba6ad6..fbaf2ec26b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh @@ -43,7 +43,7 @@ HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) con const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList (); for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++) { - const Paint &paint = hb_addressof (paint_offset_lists) + paint_offset_lists[i]; + const Paint &paint = std::addressof (paint_offset_lists) + paint_offset_lists[i]; paint.dispatch (c); } } diff --git a/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh index d2911f19e6..9741ebd450 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh @@ -202,12 +202,12 @@ struct sbix struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { table = hb_sanitize_context_t ().reference_table<sbix> (face); num_glyphs = face->get_num_glyphs (); } - void fini () { table.destroy (); } + ~accelerator_t () { table.destroy (); } bool has_data () const { return table->has_data (); } @@ -407,7 +407,10 @@ struct sbix DEFINE_SIZE_ARRAY (8, strikes); }; -struct sbix_accelerator_t : sbix::accelerator_t {}; +struct sbix_accelerator_t : sbix::accelerator_t { + sbix_accelerator_t (hb_face_t *face) : sbix::accelerator_t (face) {} +}; + } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh index e022ef43b7..fc649f1006 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh @@ -79,9 +79,9 @@ struct SVG struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { table = hb_sanitize_context_t ().reference_table<SVG> (face); } - void fini () { table.destroy (); } + ~accelerator_t () { table.destroy (); } hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const { @@ -116,7 +116,9 @@ struct SVG DEFINE_SIZE_STATIC (10); }; -struct SVG_accelerator_t : SVG::accelerator_t {}; +struct SVG_accelerator_t : SVG::accelerator_t { + SVG_accelerator_t (hb_face_t *face) : SVG::accelerator_t (face) {} +}; } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color.cc b/thirdparty/harfbuzz/src/hb-ot-color.cc index 4170b71317..16077765bd 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color.cc +++ b/thirdparty/harfbuzz/src/hb-ot-color.cc @@ -90,15 +90,15 @@ hb_ot_color_palette_get_count (hb_face_t *face) /** * hb_ot_color_palette_get_name_id: * @face: #hb_face_t to work upon - * @palette_index: The index of the color palette + * @palette_index: The index of the color palette * * Fetches the `name` table Name ID that provides display names for - * a `CPAL` color palette. + * a `CPAL` color palette. * * Palette display names can be generic (e.g., "Default") or provide * specific, themed names (e.g., "Spring", "Summer", "Fall", and "Winter"). * - * Return value: the Named ID found for the palette. + * Return value: the Named ID found for the palette. * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID. * * Since: 2.1.0 @@ -116,7 +116,7 @@ hb_ot_color_palette_get_name_id (hb_face_t *face, * @color_index: The index of the color * * Fetches the `name` table Name ID that provides display names for - * the specificed color in a face's `CPAL` color palette. + * the specified color in a face's `CPAL` color palette. * * Display names can be generic (e.g., "Background") or specific * (e.g., "Eye color"). @@ -256,6 +256,8 @@ hb_ot_color_has_svg (hb_face_t *face) * * Fetches the SVG document for a glyph. The blob may be either plain text or gzip-encoded. * + * If the glyph has no SVG document, the singleton empty blob is returned. + * * Return value: (transfer full): An #hb_blob_t containing the SVG document of the glyph, if available * * Since: 2.1.0 @@ -296,6 +298,8 @@ hb_ot_color_has_png (hb_face_t *face) * as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font * object. If UPEM is unset, the blob returned will be the largest PNG available. * + * If the glyph has no PNG image, the singleton empty blob is returned. + * * Return value: (transfer full): An #hb_blob_t containing the PNG image for the glyph, if available * * Since: 2.1.0 diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh index 6aa34295c7..9bac30fff3 100644 --- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh @@ -207,8 +207,7 @@ struct glyf _populate_subset_glyphs (const hb_subset_plan_t *plan, hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const { - OT::glyf::accelerator_t glyf; - glyf.init (plan->source); + OT::glyf::accelerator_t glyf (plan->source); + hb_range (plan->num_output_glyphs ()) | hb_map ([&] (hb_codepoint_t new_gid) @@ -233,8 +232,6 @@ struct glyf }) | hb_sink (glyphs) ; - - glyf.fini (); } static bool @@ -595,7 +592,7 @@ struct glyf if (unlikely (!header.numberOfContours)) return; unsigned flags_offset = length (instructions_length ()); - if (unlikely (length (flags_offset + 1) > bytes.length)) return; + if (unlikely (flags_offset + 1 > bytes.length)) return; HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset); first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE; @@ -920,7 +917,7 @@ struct glyf struct accelerator_t { - void init (hb_face_t *face_) + accelerator_t (hb_face_t *face_) { short_offset = false; num_glyphs = 0; @@ -953,8 +950,7 @@ struct glyf num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1; num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ()); } - - void fini () + ~accelerator_t () { loca_table.destroy (); glyf_table.destroy (); @@ -1358,7 +1354,10 @@ struct glyf * defining it _MIN instead. */ }; -struct glyf_accelerator_t : glyf::accelerator_t {}; +struct glyf_accelerator_t : glyf::accelerator_t { + glyf_accelerator_t (hb_face_t *face) : glyf::accelerator_t (face) {} +}; + } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh index 7d2d2d3eb8..36bffa70a5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh @@ -127,8 +127,7 @@ struct hmtxvmtx T *table_prime = c->serializer->start_embed <T> (); if (unlikely (!table_prime)) return_trace (false); - accelerator_t _mtx; - _mtx.init (c->plan->source); + accelerator_t _mtx (c->plan->source); unsigned num_advances = _mtx.num_advances_for_subset (c->plan); auto it = @@ -144,8 +143,6 @@ struct hmtxvmtx table_prime->serialize (c->serializer, it, num_advances); - _mtx.fini (); - if (unlikely (c->serializer->in_error ())) return_trace (false); @@ -160,8 +157,8 @@ struct hmtxvmtx { friend struct hmtxvmtx; - void init (hb_face_t *face, - unsigned int default_advance_ = 0) + accelerator_t (hb_face_t *face, + unsigned int default_advance_ = 0) { default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face); @@ -193,8 +190,7 @@ struct hmtxvmtx var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag); } - - void fini () + ~accelerator_t () { table.destroy (); var_table.destroy (); @@ -338,8 +334,12 @@ struct vmtx : hmtxvmtx<vmtx, vhea> { static constexpr bool is_horizontal = false; }; -struct hmtx_accelerator_t : hmtx::accelerator_t {}; -struct vmtx_accelerator_t : vmtx::accelerator_t {}; +struct hmtx_accelerator_t : hmtx::accelerator_t { + hmtx_accelerator_t (hb_face_t *face) : hmtx::accelerator_t (face) {} +}; +struct vmtx_accelerator_t : vmtx::accelerator_t { + vmtx_accelerator_t (hb_face_t *face) : vmtx::accelerator_t (face) {} +}; } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh index 4fb1893435..60a1906155 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh @@ -128,7 +128,7 @@ struct hb_prune_langsys_context_t bool visited (const T *p, hb_set_t &visited_set) { hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) p - (uintptr_t) table); - if (visited_set.has (delta)) + if (visited_set.in_error () || visited_set.has (delta)) return true; visited_set.add (delta); @@ -655,7 +655,6 @@ struct LangSys void collect_features (hb_prune_langsys_context_t *c) const { if (!has_required_feature () && !get_feature_count ()) return; - if (c->visitedLangsys (this)) return; if (has_required_feature () && c->duplicate_feature_map->has (reqFeatureIndex)) c->new_feature_indexes->add (get_required_feature_index ()); @@ -750,11 +749,15 @@ struct Script { //only collect features from non-redundant langsys const LangSys& d = get_default_lang_sys (); - d.collect_features (c); + if (!c->visitedLangsys (&d)) { + d.collect_features (c); + } for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) { + const LangSys& l = this+_.first.offset; + if (c->visitedLangsys (&l)) continue; if (l.compare (d, c->duplicate_feature_map)) continue; l.collect_features (c); @@ -766,6 +769,7 @@ struct Script for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) { const LangSys& l = this+_.first.offset; + if (c->visitedLangsys (&l)) continue; l.collect_features (c); c->script_langsys_map->get (script_index)->add (_.second); } @@ -845,7 +849,7 @@ struct FeatureParamsSize if (unlikely (!c->check_struct (this))) return_trace (false); /* This subtable has some "history", if you will. Some earlier versions of - * Adobe tools calculated the offset of the FeatureParams sutable from the + * Adobe tools calculated the offset of the FeatureParams subtable from the * beginning of the FeatureList table! Now, that is dealt with in the * Feature implementation. But we still need to be able to tell junk from * real data. Note: We don't check that the nameID actually exists. @@ -2926,8 +2930,6 @@ struct VariationStore hb_vector_t<hb_inc_bimap_t> inner_maps; inner_maps.resize ((unsigned) dataSets.len); - for (unsigned i = 0; i < inner_maps.length; i++) - inner_maps[i].init (); for (unsigned idx : c->plan->layout_variation_indices->iter ()) { @@ -2935,18 +2937,11 @@ struct VariationStore uint16_t minor = idx & 0xFFFF; if (major >= inner_maps.length) - { - for (unsigned i = 0; i < inner_maps.length; i++) - inner_maps[i].fini (); return_trace (false); - } inner_maps[major].add (minor); } varstore_prime->serialize (c->serializer, this, inner_maps.as_array ()); - for (unsigned i = 0; i < inner_maps.length; i++) - inner_maps[i].fini (); - return_trace ( !c->serializer->in_error() && varstore_prime->dataSets); diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh index aea644f3e1..a76d644c4b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh @@ -585,17 +585,16 @@ struct GDEF struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { - this->table = hb_sanitize_context_t ().reference_table<GDEF> (face); - if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face))) + table = hb_sanitize_context_t ().reference_table<GDEF> (face); + if (unlikely (table->is_blocklisted (table.get_blob (), face))) { - hb_blob_destroy (this->table.get_blob ()); - this->table = hb_blob_get_empty (); + hb_blob_destroy (table.get_blob ()); + table = hb_blob_get_empty (); } } - - void fini () { this->table.destroy (); } + ~accelerator_t () { table.destroy (); } hb_blob_ptr_t<GDEF> table; }; @@ -715,7 +714,9 @@ struct GDEF DEFINE_SIZE_MIN (12); }; -struct GDEF_accelerator_t : GDEF::accelerator_t {}; +struct GDEF_accelerator_t : GDEF::accelerator_t { + GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {} +}; } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh index 6db3e08940..e28c951f3f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh @@ -706,7 +706,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage or float mark_x, mark_y, base_x, base_y; - buffer->unsafe_to_break (glyph_pos, buffer->idx); + buffer->unsafe_to_break (glyph_pos, buffer->idx + 1); mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y); glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y); @@ -1235,6 +1235,7 @@ struct PairSet buffer->idx = pos; return_trace (true); } + buffer->unsafe_to_concat (buffer->idx, pos + 1); return_trace (false); } @@ -1362,7 +1363,12 @@ struct PairPosFormat1 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); - if (!skippy_iter.next ()) return_trace (false); + unsigned unsafe_to; + if (!skippy_iter.next (&unsafe_to)) + { + buffer->unsafe_to_concat (buffer->idx, unsafe_to); + return_trace (false); + } return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx)); } @@ -1555,7 +1561,12 @@ struct PairPosFormat2 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); - if (!skippy_iter.next ()) return_trace (false); + unsigned unsafe_to; + if (!skippy_iter.next (&unsafe_to)) + { + buffer->unsafe_to_concat (buffer->idx, unsafe_to); + return_trace (false); + } unsigned int len1 = valueFormat1.get_len (); unsigned int len2 = valueFormat2.get_len (); @@ -1563,13 +1574,81 @@ struct PairPosFormat2 unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); - if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false); + if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) + { + buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); + return_trace (false); + } const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; - bool applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos()); - bool applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); + + bool applied_first = false, applied_second = false; + + + /* Isolate simple kerning and apply it half to each side. + * Results in better cursor positinoing / underline drawing. */ + { + if (!len2) + { + const hb_direction_t dir = buffer->props.direction; + const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir); + const bool backward = HB_DIRECTION_IS_BACKWARD (dir); + unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance; + if (backward) + mask |= mask >> 2; /* Add eg. xPlacement in RTL. */ + /* Add Devices. */ + mask |= mask << 4; + + if (valueFormat1 & ~mask) + goto bail; + + /* Is simple kern. Apply value on an empty position slot, + * then split it between sides. */ + + hb_glyph_position_t pos{}; + if (valueFormat1.apply_value (c, this, v, pos)) + { + hb_position_t *src = &pos.x_advance; + hb_position_t *dst1 = &buffer->cur_pos().x_advance; + hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance; + unsigned i = horizontal ? 0 : 1; + + hb_position_t kern = src[i]; + hb_position_t kern1 = kern >> 1; + hb_position_t kern2 = kern - kern1; + + if (!backward) + { + dst1[i] += kern1; + dst2[i] += kern2; + dst2[i + 2] += kern2; + } + else + { + dst1[i] += kern1; + dst1[i + 2] += src[i + 2] - kern2; + dst2[i] += kern2; + } + + applied_first = applied_second = kern != 0; + goto success; + } + goto boring; + } + } + bail: + + + applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos()); + applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); + + success: if (applied_first || applied_second) buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1); + else + boring: + buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); + buffer->idx = skippy_iter.idx; if (len2) @@ -1799,10 +1878,19 @@ struct CursivePosFormat1 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); - if (!skippy_iter.prev ()) return_trace (false); + unsigned unsafe_from; + if (!skippy_iter.prev (&unsafe_from)) + { + buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); + return_trace (false); + } const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)]; - if (!prev_record.exitAnchor) return_trace (false); + if (!prev_record.exitAnchor) + { + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); + return_trace (false); + } unsigned int i = skippy_iter.idx; unsigned int j = buffer->idx; @@ -2066,7 +2154,13 @@ struct MarkBasePosFormat1 skippy_iter.reset (buffer->idx, 1); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); do { - if (!skippy_iter.prev ()) return_trace (false); + unsigned unsafe_from; + if (!skippy_iter.prev (&unsafe_from)) + { + buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); + return_trace (false); + } + /* We only want to attach to the first of a MultipleSubst sequence. * https://github.com/harfbuzz/harfbuzz/issues/740 * Reject others... @@ -2089,7 +2183,11 @@ struct MarkBasePosFormat1 //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); } unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint); - if (base_index == NOT_COVERED) return_trace (false); + if (base_index == NOT_COVERED) + { + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); + return_trace (false); + } return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); } @@ -2320,21 +2418,34 @@ struct MarkLigPosFormat1 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); - if (!skippy_iter.prev ()) return_trace (false); + unsigned unsafe_from; + if (!skippy_iter.prev (&unsafe_from)) + { + buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); + return_trace (false); + } /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */ //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); } unsigned int j = skippy_iter.idx; unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint); - if (lig_index == NOT_COVERED) return_trace (false); + if (lig_index == NOT_COVERED) + { + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); + return_trace (false); + } const LigatureArray& lig_array = this+ligatureArray; const LigatureAttach& lig_attach = lig_array[lig_index]; /* Find component to attach to */ unsigned int comp_count = lig_attach.rows; - if (unlikely (!comp_count)) return_trace (false); + if (unlikely (!comp_count)) + { + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); + return_trace (false); + } /* We must now check whether the ligature ID of the current mark glyph * is identical to the ligature ID of the found ligature. If yes, we @@ -2517,9 +2628,18 @@ struct MarkMarkPosFormat1 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; skippy_iter.reset (buffer->idx, 1); skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags); - if (!skippy_iter.prev ()) return_trace (false); + unsigned unsafe_from; + if (!skippy_iter.prev (&unsafe_from)) + { + buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); + return_trace (false); + } - if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return_trace (false); } + if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) + { + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); + return_trace (false); + } unsigned int j = skippy_iter.idx; @@ -2544,11 +2664,16 @@ struct MarkMarkPosFormat1 } /* Didn't match. */ + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); return_trace (false); good: unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint); - if (mark2_index == NOT_COVERED) return_trace (false); + if (mark2_index == NOT_COVERED) + { + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); + return_trace (false); + } return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); } @@ -2951,7 +3076,7 @@ GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer H } void -GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) +GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) { _hb_buffer_assert_gsubgpos_vars (buffer); @@ -2961,12 +3086,21 @@ GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) /* Handle attachments */ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT) - for (unsigned int i = 0; i < len; i++) + for (unsigned i = 0; i < len; i++) propagate_attachment_offsets (pos, len, i, direction); + + if (unlikely (font->slant)) + { + for (unsigned i = 0; i < len; i++) + if (unlikely (pos[i].y_offset)) + pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset); + } } -struct GPOS_accelerator_t : GPOS::accelerator_t {}; +struct GPOS_accelerator_t : GPOS::accelerator_t { + GPOS_accelerator_t (hb_face_t *face) : GPOS::accelerator_t (face) {} +}; /* Out-of-class implementation for methods recursing */ diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh index b7ce30135e..0b0bc547bd 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh @@ -826,22 +826,25 @@ struct Ligature unsigned int total_component_count = 0; - unsigned int match_length = 0; + unsigned int match_end = 0; unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; if (likely (!match_input (c, count, &component[1], match_glyph, nullptr, - &match_length, + &match_end, match_positions, &total_component_count))) + { + c->buffer->unsafe_to_concat (c->buffer->idx, match_end); return_trace (false); + } ligate_input (c, count, match_positions, - match_length, + match_end, ligGlyph, total_component_count); @@ -1296,7 +1299,7 @@ struct ReverseChainSingleSubstFormat1 match_lookahead (c, lookahead.len, (HBUINT16 *) lookahead.arrayZ, match_coverage, this, - 1, &end_index)) + c->buffer->idx + 1, &end_index)) { c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index); c->replace_glyph_inplace (substitute[index]); @@ -1305,8 +1308,11 @@ struct ReverseChainSingleSubstFormat1 * calls us through a Context lookup. */ return_trace (true); } - - return_trace (false); + else + { + c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index); + return_trace (false); + } } template<typename Iterator, @@ -1739,7 +1745,9 @@ struct GSUB : GSUBGPOS }; -struct GSUB_accelerator_t : GSUB::accelerator_t {}; +struct GSUB_accelerator_t : GSUB::accelerator_t { + GSUB_accelerator_t (hb_face_t *face) : GSUB::accelerator_t (face) {} +}; /* Out-of-class implementation for methods recursing */ diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh index 191d3bebc5..65de131f85 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -125,24 +125,31 @@ struct hb_closure_context_t : hb_set_t *covered_glyph_set = done_lookups_glyph_set->get (lookup_index); if (unlikely (covered_glyph_set->in_error ())) return true; - if (parent_active_glyphs ()->is_subset (*covered_glyph_set)) + if (parent_active_glyphs ().is_subset (*covered_glyph_set)) return true; - hb_set_union (covered_glyph_set, parent_active_glyphs ()); + covered_glyph_set->union_ (parent_active_glyphs ()); return false; } - hb_set_t* parent_active_glyphs () + const hb_set_t& previous_parent_active_glyphs () { + if (active_glyphs_stack.length <= 1) + return *glyphs; + + return active_glyphs_stack[active_glyphs_stack.length - 2]; + } + + const hb_set_t& parent_active_glyphs () { - if (active_glyphs_stack.length < 1) - return glyphs; + if (!active_glyphs_stack) + return *glyphs; return active_glyphs_stack.tail (); } - void push_cur_active_glyphs (hb_set_t* cur_active_glyph_set) + hb_set_t& push_cur_active_glyphs () { - active_glyphs_stack.push (cur_active_glyph_set); + return *active_glyphs_stack.push (); } bool pop_cur_done_glyphs () @@ -156,29 +163,24 @@ struct hb_closure_context_t : hb_face_t *face; hb_set_t *glyphs; - hb_set_t *cur_intersected_glyphs; hb_set_t output[1]; - hb_vector_t<hb_set_t *> active_glyphs_stack; + hb_vector_t<hb_set_t> active_glyphs_stack; recurse_func_t recurse_func; unsigned int nesting_level_left; hb_closure_context_t (hb_face_t *face_, hb_set_t *glyphs_, - hb_set_t *cur_intersected_glyphs_, hb_map_t *done_lookups_glyph_count_, hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set_, unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : face (face_), glyphs (glyphs_), - cur_intersected_glyphs (cur_intersected_glyphs_), recurse_func (nullptr), nesting_level_left (nesting_level_left_), done_lookups_glyph_count (done_lookups_glyph_count_), done_lookups_glyph_set (done_lookups_glyph_set_), lookup_count (0) - { - push_cur_active_glyphs (glyphs_); - } + {} ~hb_closure_context_t () { flush (); } @@ -186,11 +188,11 @@ struct hb_closure_context_t : void flush () { - hb_set_del_range (output, face->get_num_glyphs (), HB_SET_VALUE_INVALID); /* Remove invalid glyphs. */ - hb_set_union (glyphs, output); - hb_set_clear (output); + output->del_range (face->get_num_glyphs (), HB_SET_VALUE_INVALID); /* Remove invalid glyphs. */ + glyphs->union_ (*output); + output->clear (); active_glyphs_stack.pop (); - active_glyphs_stack.fini (); + active_glyphs_stack.reset (); } private: @@ -520,7 +522,7 @@ struct hb_ot_apply_context_t : may_skip (const hb_glyph_info_t &info) const { return matcher.may_skip (c, info); } - bool next () + bool next (unsigned *unsafe_to = nullptr) { assert (num_items > 0); while (idx + num_items < end) @@ -543,11 +545,17 @@ struct hb_ot_apply_context_t : } if (skip == matcher_t::SKIP_NO) + { + if (unsafe_to) + *unsafe_to = idx + 1; return false; + } } + if (unsafe_to) + *unsafe_to = end; return false; } - bool prev () + bool prev (unsigned *unsafe_from = nullptr) { assert (num_items > 0); while (idx > num_items - 1) @@ -570,8 +578,14 @@ struct hb_ot_apply_context_t : } if (skip == matcher_t::SKIP_NO) + { + if (unsafe_from) + *unsafe_from = hb_max (1u, idx) - 1u; return false; + } } + if (unsafe_from) + *unsafe_from = 0; return false; } @@ -712,53 +726,60 @@ struct hb_ot_apply_context_t : return true; } - void _set_glyph_props (hb_codepoint_t glyph_index, + void _set_glyph_class (hb_codepoint_t glyph_index, unsigned int class_guess = 0, bool ligature = false, bool component = false) const { - unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) & - HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; - add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED; + unsigned int props = _hb_glyph_info_get_glyph_props (&buffer->cur()); + props |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED; if (ligature) { - add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED; + props |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED; /* In the only place that the MULTIPLIED bit is used, Uniscribe * seems to only care about the "last" transformation between * Ligature and Multiple substitutions. Ie. if you ligate, expand, * and ligate again, it forgives the multiplication and acts as * if only ligation happened. As such, clear MULTIPLIED bit. */ - add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED; + props &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED; } if (component) - add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED; + props |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED; if (likely (has_glyph_classes)) - _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index)); + { + props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; + _hb_glyph_info_set_glyph_props (&buffer->cur(), props | gdef.get_glyph_props (glyph_index)); + } else if (class_guess) - _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess); + { + props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; + _hb_glyph_info_set_glyph_props (&buffer->cur(), props | class_guess); + } + else + _hb_glyph_info_set_glyph_props (&buffer->cur(), props); } void replace_glyph (hb_codepoint_t glyph_index) const { - _set_glyph_props (glyph_index); + _set_glyph_class (glyph_index); (void) buffer->replace_glyph (glyph_index); } void replace_glyph_inplace (hb_codepoint_t glyph_index) const { - _set_glyph_props (glyph_index); + _set_glyph_class (glyph_index); buffer->cur().codepoint = glyph_index; } void replace_glyph_with_ligature (hb_codepoint_t glyph_index, unsigned int class_guess) const { - _set_glyph_props (glyph_index, class_guess, true); + _set_glyph_class (glyph_index, class_guess, true); (void) buffer->replace_glyph (glyph_index); } void output_glyph_for_component (hb_codepoint_t glyph_index, unsigned int class_guess) const { - _set_glyph_props (glyph_index, class_guess, false, true); + _set_glyph_class (glyph_index, class_guess, false, true); (void) buffer->output_glyph (glyph_index); } }; @@ -948,7 +969,7 @@ static inline bool match_input (hb_ot_apply_context_t *c, const HBUINT16 input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data, - unsigned int *end_offset, + unsigned int *end_position, unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], unsigned int *p_total_component_count = nullptr) { @@ -1001,7 +1022,12 @@ static inline bool match_input (hb_ot_apply_context_t *c, match_positions[0] = buffer->idx; for (unsigned int i = 1; i < count; i++) { - if (!skippy_iter.next ()) return_trace (false); + unsigned unsafe_to; + if (!skippy_iter.next (&unsafe_to)) + { + *end_position = unsafe_to; + return_trace (false); + } match_positions[i] = skippy_iter.idx; @@ -1055,7 +1081,7 @@ static inline bool match_input (hb_ot_apply_context_t *c, total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]); } - *end_offset = skippy_iter.idx - buffer->idx + 1; + *end_position = skippy_iter.idx + 1; if (p_total_component_count) *p_total_component_count = total_component_count; @@ -1065,7 +1091,7 @@ static inline bool match_input (hb_ot_apply_context_t *c, static inline bool ligate_input (hb_ot_apply_context_t *c, unsigned int count, /* Including the first glyph */ const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */ - unsigned int match_length, + unsigned int match_end, hb_codepoint_t lig_glyph, unsigned int total_component_count) { @@ -1073,7 +1099,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c, hb_buffer_t *buffer = c->buffer; - buffer->merge_clusters (buffer->idx, buffer->idx + match_length); + buffer->merge_clusters (buffer->idx, match_end); /* - If a base and one or more marks ligate, consider that as a base, NOT * ligature, such that all following marks can still attach to it. @@ -1190,11 +1216,16 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c, skippy_iter.set_match_func (match_func, match_data, backtrack); for (unsigned int i = 0; i < count; i++) - if (!skippy_iter.prev ()) + { + unsigned unsafe_from; + if (!skippy_iter.prev (&unsafe_from)) + { + *match_start = unsafe_from; return_trace (false); + } + } *match_start = skippy_iter.idx; - return_trace (true); } @@ -1203,21 +1234,26 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c, const HBUINT16 lookahead[], match_func_t match_func, const void *match_data, - unsigned int offset, + unsigned int start_index, unsigned int *end_index) { TRACE_APPLY (nullptr); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; - skippy_iter.reset (c->buffer->idx + offset - 1, count); + skippy_iter.reset (start_index - 1, count); skippy_iter.set_match_func (match_func, match_data, lookahead); for (unsigned int i = 0; i < count; i++) - if (!skippy_iter.next ()) + { + unsigned unsafe_to; + if (!skippy_iter.next (&unsafe_to)) + { + *end_index = unsafe_to; return_trace (false); + } + } *end_index = skippy_iter.idx + 1; - return_trace (true); } @@ -1284,22 +1320,23 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, unsigned seqIndex = lookupRecord[i].sequenceIndex; if (seqIndex >= inputCount) continue; - hb_set_t *pos_glyphs = nullptr; + bool has_pos_glyphs = false; + hb_set_t pos_glyphs; if (hb_set_is_empty (covered_seq_indicies) || !hb_set_has (covered_seq_indicies, seqIndex)) { - pos_glyphs = hb_set_create (); + has_pos_glyphs = true; if (seqIndex == 0) { switch (context_format) { case ContextFormat::SimpleContext: - pos_glyphs->add (value); + pos_glyphs.add (value); break; case ContextFormat::ClassBasedContext: - intersected_glyphs_func (c->cur_intersected_glyphs, data, value, pos_glyphs); + intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs); break; case ContextFormat::CoverageBasedContext: - hb_set_set (pos_glyphs, c->cur_intersected_glyphs); + pos_glyphs.set (c->parent_active_glyphs ()); break; } } @@ -1313,12 +1350,16 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, input_value = input[seqIndex - 1]; } - intersected_glyphs_func (c->glyphs, input_data, input_value, pos_glyphs); + intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs); } } - hb_set_add (covered_seq_indicies, seqIndex); - c->push_cur_active_glyphs (pos_glyphs ? pos_glyphs : c->glyphs); + covered_seq_indicies->add (seqIndex); + if (has_pos_glyphs) { + c->push_cur_active_glyphs () = pos_glyphs; + } else { + c->push_cur_active_glyphs ().set (*c->glyphs); + } unsigned endIndex = inputCount; if (context_format == ContextFormat::CoverageBasedContext) @@ -1327,8 +1368,6 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, c->recurse (lookupRecord[i].lookupListIndex, covered_seq_indicies, seqIndex, endIndex); c->pop_cur_done_glyphs (); - if (pos_glyphs) - hb_set_destroy (pos_glyphs); } hb_set_destroy (covered_seq_indicies); @@ -1343,15 +1382,13 @@ static inline void recurse_lookups (context_t *c, c->recurse (lookupRecord[i].lookupListIndex); } -static inline bool apply_lookup (hb_ot_apply_context_t *c, +static inline void apply_lookup (hb_ot_apply_context_t *c, unsigned int count, /* Including the first glyph */ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */ - unsigned int match_length) + unsigned int match_end) { - TRACE_APPLY (nullptr); - hb_buffer_t *buffer = c->buffer; int end; @@ -1359,7 +1396,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c, * Adjust. */ { unsigned int bl = buffer->backtrack_len (); - end = bl + match_length; + end = bl + match_end - buffer->idx; int delta = bl - buffer->idx; /* Convert positions to new indexing. */ @@ -1461,8 +1498,6 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c, } (void) buffer->move_to (end); - - return_trace (true); } @@ -1550,17 +1585,25 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c, const LookupRecord lookupRecord[], ContextApplyLookupContext &lookup_context) { - unsigned int match_length = 0; - unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; - return match_input (c, - inputCount, input, - lookup_context.funcs.match, lookup_context.match_data, - &match_length, match_positions) - && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length), - apply_lookup (c, - inputCount, match_positions, - lookupCount, lookupRecord, - match_length)); + unsigned match_end = 0; + unsigned match_positions[HB_MAX_CONTEXT_LENGTH]; + if (match_input (c, + inputCount, input, + lookup_context.funcs.match, lookup_context.match_data, + &match_end, match_positions)) + { + c->buffer->unsafe_to_break (c->buffer->idx, match_end); + apply_lookup (c, + inputCount, match_positions, + lookupCount, lookupRecord, + match_end); + return true; + } + else + { + c->buffer->unsafe_to_concat (c->buffer->idx, match_end); + return false; + } } struct Rule @@ -1828,8 +1871,9 @@ struct ContextFormat1 void closure (hb_closure_context_t *c) const { - c->cur_intersected_glyphs->clear (); - get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); struct ContextClosureLookupContext lookup_context = { {intersects_glyph, intersected_glyph}, @@ -1838,10 +1882,14 @@ struct ContextFormat1 }; + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len)) - | hb_filter (c->parent_active_glyphs (), hb_first) + | hb_filter ([&] (hb_codepoint_t _) { + return c->previous_parent_active_glyphs ().has (_); + }, hb_first) | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const RuleSet&> (_.first, this+ruleSet[_.second]); }) | hb_apply ([&] (const hb_pair_t<unsigned, const RuleSet&>& _) { _.second.closure (c, _.first, lookup_context); }) ; + + c->pop_cur_done_glyphs (); } void closure_lookups (hb_closure_lookups_context_t *c) const @@ -1989,8 +2037,9 @@ struct ContextFormat2 if (!(this+coverage).intersects (c->glyphs)) return; - c->cur_intersected_glyphs->clear (); - get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); const ClassDef &class_def = this+classDef; @@ -2000,10 +2049,9 @@ struct ContextFormat2 &class_def }; - return + hb_enumerate (ruleSet) | hb_filter ([&] (unsigned _) - { return class_def.intersects_class (c->cur_intersected_glyphs, _); }, + { return class_def.intersects_class (&c->parent_active_glyphs (), _); }, hb_first) | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<RuleSet>&> _) { @@ -2011,6 +2059,8 @@ struct ContextFormat2 rule_set.closure (c, _.first, lookup_context); }) ; + + c->pop_cur_done_glyphs (); } void closure_lookups (hb_closure_lookups_context_t *c) const @@ -2183,8 +2233,10 @@ struct ContextFormat3 if (!(this+coverageZ[0]).intersects (c->glyphs)) return; - c->cur_intersected_glyphs->clear (); - get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); + const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount)); struct ContextClosureLookupContext lookup_context = { @@ -2196,6 +2248,8 @@ struct ContextFormat3 glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, 0, lookup_context); + + c->pop_cur_done_glyphs (); } void closure_lookups (hb_closure_lookups_context_t *c) const @@ -2452,25 +2506,38 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c, const LookupRecord lookupRecord[], ChainContextApplyLookupContext &lookup_context) { - unsigned int start_index = 0, match_length = 0, end_index = 0; - unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; - return match_input (c, - inputCount, input, - lookup_context.funcs.match, lookup_context.match_data[1], - &match_length, match_positions) - && match_backtrack (c, - backtrackCount, backtrack, - lookup_context.funcs.match, lookup_context.match_data[0], - &start_index) - && match_lookahead (c, - lookaheadCount, lookahead, - lookup_context.funcs.match, lookup_context.match_data[2], - match_length, &end_index) - && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index), - apply_lookup (c, - inputCount, match_positions, - lookupCount, lookupRecord, - match_length)); + unsigned end_index = c->buffer->idx; + unsigned match_end = 0; + unsigned match_positions[HB_MAX_CONTEXT_LENGTH]; + if (!(match_input (c, + inputCount, input, + lookup_context.funcs.match, lookup_context.match_data[1], + &match_end, match_positions) && (end_index = match_end) + && match_lookahead (c, + lookaheadCount, lookahead, + lookup_context.funcs.match, lookup_context.match_data[2], + match_end, &end_index))) + { + c->buffer->unsafe_to_concat (c->buffer->idx, end_index); + return false; + } + + unsigned start_index = c->buffer->out_len; + if (!match_backtrack (c, + backtrackCount, backtrack, + lookup_context.funcs.match, lookup_context.match_data[0], + &start_index)) + { + c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index); + return false; + } + + c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index); + apply_lookup (c, + inputCount, match_positions, + lookupCount, lookupRecord, + match_end); + return true; } struct ChainRule @@ -2802,8 +2869,9 @@ struct ChainContextFormat1 void closure (hb_closure_context_t *c) const { - c->cur_intersected_glyphs->clear (); - get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); struct ChainContextClosureLookupContext lookup_context = { {intersects_glyph, intersected_glyph}, @@ -2812,10 +2880,14 @@ struct ChainContextFormat1 }; + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len)) - | hb_filter (c->parent_active_glyphs (), hb_first) + | hb_filter ([&] (hb_codepoint_t _) { + return c->previous_parent_active_glyphs ().has (_); + }, hb_first) | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const ChainRuleSet&> (_.first, this+ruleSet[_.second]); }) | hb_apply ([&] (const hb_pair_t<unsigned, const ChainRuleSet&>& _) { _.second.closure (c, _.first, lookup_context); }) ; + + c->pop_cur_done_glyphs (); } void closure_lookups (hb_closure_lookups_context_t *c) const @@ -2964,8 +3036,10 @@ struct ChainContextFormat2 if (!(this+coverage).intersects (c->glyphs)) return; - c->cur_intersected_glyphs->clear (); - get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); + const ClassDef &backtrack_class_def = this+backtrackClassDef; const ClassDef &input_class_def = this+inputClassDef; @@ -2979,10 +3053,9 @@ struct ChainContextFormat2 &lookahead_class_def} }; - return + hb_enumerate (ruleSet) | hb_filter ([&] (unsigned _) - { return input_class_def.intersects_class (c->cur_intersected_glyphs, _); }, + { return input_class_def.intersects_class (&c->parent_active_glyphs (), _); }, hb_first) | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<ChainRuleSet>&> _) { @@ -2990,6 +3063,8 @@ struct ChainContextFormat2 chainrule_set.closure (c, _.first, lookup_context); }) ; + + c->pop_cur_done_glyphs (); } void closure_lookups (hb_closure_lookups_context_t *c) const @@ -3216,8 +3291,10 @@ struct ChainContextFormat3 if (!(this+input[0]).intersects (c->glyphs)) return; - c->cur_intersected_glyphs->clear (); - get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); @@ -3232,6 +3309,8 @@ struct ChainContextFormat3 lookahead.len, (const HBUINT16 *) lookahead.arrayZ, lookup.len, lookup.arrayZ, 0, lookup_context); + + c->pop_cur_done_glyphs (); } void closure_lookups (hb_closure_lookups_context_t *c) const @@ -3706,7 +3785,7 @@ struct GSUBGPOS for (unsigned i : feature_indices->iter ()) { hb_tag_t t = get_feature_tag (i); - if (t == unique_features.INVALID_KEY) continue; + if (t == HB_MAP_VALUE_INVALID) continue; if (!unique_features.has (t)) { hb_set_t* indices = hb_set_create (); @@ -3839,7 +3918,7 @@ struct GSUBGPOS template <typename T> struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { this->table = hb_sanitize_context_t ().reference_table<T> (face); if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face))) @@ -3861,8 +3940,7 @@ struct GSUBGPOS for (unsigned int i = 0; i < this->lookup_count; i++) this->accels[i].init (table->get_lookup (i)); } - - void fini () + ~accelerator_t () { for (unsigned int i = 0; i < this->lookup_count; i++) this->accels[i].fini (); diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc index 60733648c1..a599eea6e9 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.cc +++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc @@ -1491,10 +1491,9 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face, unsigned int lookup_index, hb_set_t *glyphs /* OUT */) { - hb_set_t cur_intersected_glyphs; hb_map_t done_lookups_glyph_count; hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set; - OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); + OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index); @@ -1520,10 +1519,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, const hb_set_t *lookups, hb_set_t *glyphs /* OUT */) { - hb_set_t cur_intersected_glyphs; hb_map_t done_lookups_glyph_count; hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set; - OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); + OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); const OT::GSUB& gsub = *face->table.GSUB->table; unsigned int iteration_count = 0; @@ -1890,7 +1888,7 @@ apply_string (OT::hb_ot_apply_context_t *c, apply_forward (c, accel); if (!Proxy::inplace) - buffer->swap_buffers (); + buffer->sync (); } else { diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh index 2c825e0c81..ede8f007db 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh @@ -482,10 +482,9 @@ _hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info) } static inline uint8_t -_hb_allocate_lig_id (hb_buffer_t *buffer) { +_hb_allocate_lig_id (hb_buffer_t *buffer) +{ uint8_t lig_id = buffer->next_serial () & 0x07; - if (unlikely (!lig_id)) - lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */ return lig_id; } diff --git a/thirdparty/harfbuzz/src/hb-ot-meta-table.hh b/thirdparty/harfbuzz/src/hb-ot-meta-table.hh index e31447f8fc..93e64c5327 100644 --- a/thirdparty/harfbuzz/src/hb-ot-meta-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-meta-table.hh @@ -71,9 +71,9 @@ struct meta struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { table = hb_sanitize_context_t ().reference_table<meta> (face); } - void fini () { table.destroy (); } + ~accelerator_t () { table.destroy (); } hb_blob_t *reference_entry (hb_tag_t tag) const { return table->dataMaps.lsearch (tag).reference_entry (table.get_blob ()); } @@ -119,7 +119,9 @@ struct meta DEFINE_SIZE_ARRAY (16, dataMaps); }; -struct meta_accelerator_t : meta::accelerator_t {}; +struct meta_accelerator_t : meta::accelerator_t { + meta_accelerator_t (hb_face_t *face) : meta::accelerator_t (face) {} +}; } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.cc b/thirdparty/harfbuzz/src/hb-ot-metrics.cc index dbd4a1ffbe..103808cf91 100644 --- a/thirdparty/harfbuzz/src/hb-ot-metrics.cc +++ b/thirdparty/harfbuzz/src/hb-ot-metrics.cc @@ -160,9 +160,50 @@ hb_ot_metrics_get_position (hb_font_t *font, (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true)) case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent); case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent); - case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: return GET_METRIC_Y (hhea, caretSlopeRise); - case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: return GET_METRIC_X (hhea, caretSlopeRun); + + case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: + case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: + { + unsigned mult = 1u; + + if (font->slant) + { + unsigned rise = face->table.hhea->caretSlopeRise; + unsigned upem = face->get_upem (); + mult = (rise && rise < upem) ? hb_min (upem / rise, 256u) : 1u; + } + + if (metrics_tag == HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE) + { + bool ret = GET_METRIC_Y (hhea, caretSlopeRise); + + if (position) + *position *= mult; + + return ret; + } + else + { + hb_position_t rise = 0; + + if (font->slant && position && GET_METRIC_Y (hhea, caretSlopeRise)) + rise = *position; + + bool ret = GET_METRIC_X (hhea, caretSlopeRun); + + if (position) + { + *position *= mult; + + if (font->slant) + *position += _hb_roundf (mult * font->slant_xy * rise); + } + + return ret; + } + } case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET: return GET_METRIC_X (hhea, caretOffset); + #ifndef HB_NO_VERTICAL case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE: return GET_METRIC_X (vhea, caretSlopeRise); case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN: return GET_METRIC_Y (vhea, caretSlopeRun); diff --git a/thirdparty/harfbuzz/src/hb-ot-name-table.hh b/thirdparty/harfbuzz/src/hb-ot-name-table.hh index c17bb4abb8..d52367e9b1 100644 --- a/thirdparty/harfbuzz/src/hb-ot-name-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-name-table.hh @@ -256,7 +256,7 @@ struct name }) ; - name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset)); + name_prime->serialize (c->serializer, it, std::addressof (this + stringOffset)); return_trace (name_prime->count); } @@ -279,7 +279,7 @@ struct name struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { this->table = hb_sanitize_context_t ().reference_table<name> (face); assert (this->table.get_length () >= this->table->stringOffset); @@ -288,7 +288,6 @@ struct name const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ, this->table->count); - this->names.init (); this->names.alloc (all_names.length); for (unsigned int i = 0; i < all_names.length; i++) @@ -318,10 +317,8 @@ struct name } this->names.resize (j); } - - void fini () + ~accelerator_t () { - this->names.fini (); this->table.destroy (); } @@ -373,7 +370,9 @@ struct name #undef entry_index #undef entry_score -struct name_accelerator_t : name::accelerator_t {}; +struct name_accelerator_t : name::accelerator_t { + name_accelerator_t (hb_face_t *face) : name::accelerator_t (face) {} +}; } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh index 504de2de74..0f3cd8e24f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh +++ b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh @@ -76,8 +76,7 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const hb_map_t old_new_index_map, old_gid_new_index_map; unsigned i = 0; - post::accelerator_t _post; - _post.init (c->plan->source); + post::accelerator_t _post (c->plan->source); hb_hashmap_t<hb_bytes_t, unsigned, std::nullptr_t, unsigned, nullptr, (unsigned)-1> glyph_name_to_new_index; for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++) @@ -128,9 +127,7 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const }) ; - bool ret = serialize (c->serializer, index_iter, &_post); - _post.fini (); - return_trace (ret); + return_trace (serialize (c->serializer, index_iter, &_post)); } } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh index 39de671707..a4844e94bc 100644 --- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh @@ -111,10 +111,9 @@ struct post struct accelerator_t { friend struct postV2Tail; - void init (hb_face_t *face) - { - index_to_offset.init (); + accelerator_t (hb_face_t *face) + { table = hb_sanitize_context_t ().reference_table<post> (face); unsigned int table_length = table.get_length (); @@ -132,9 +131,8 @@ struct post data += 1 + *data) index_to_offset.push (data - pool); } - void fini () + ~accelerator_t () { - index_to_offset.fini (); hb_free (gids_sorted_by_name.get ()); table.destroy (); } @@ -254,9 +252,9 @@ struct post private: uint32_t version; - const Array16Of<HBUINT16> *glyphNameIndex; + const Array16Of<HBUINT16> *glyphNameIndex = nullptr; hb_vector_t<uint32_t> index_to_offset; - const uint8_t *pool; + const uint8_t *pool = nullptr; hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name; }; @@ -307,7 +305,10 @@ struct post DEFINE_SIZE_MIN (32); }; -struct post_accelerator_t : post::accelerator_t {}; +struct post_accelerator_t : post::accelerator_t { + post_accelerator_t (hb_face_t *face) : post::accelerator_t (face) {} +}; + } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh index 41e3dd38ab..429974d05b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh @@ -87,6 +87,8 @@ #define OT_GLYPHID /* GlyphID */ \ OT_UINT16 +/* Shorthand. */ +#define G OT_GLYPHID #define OT_UARRAY(Name, Items) \ OT_LABEL_START(Name) \ @@ -183,8 +185,6 @@ Tag \ OT_OFFSET(manifest, Name) -/* Shorthand. */ -#define G OT_GLYPHID /* * Table Start @@ -300,14 +300,40 @@ OT_TABLE_END /* * Clean up */ + +#undef MANIFEST +#undef MANIFEST_LOOKUP + #undef OT_TABLE_START #undef OT_TABLE_END #undef OT_LABEL_START #undef OT_LABEL_END #undef OT_UINT8 #undef OT_UINT16 -#undef OT_DISTANCE #undef OT_COUNT +#undef OT_DISTANCE + +#undef OT_LABEL +#undef OT_LIST + +#undef OT_TAG +#undef OT_OFFSET +#undef OT_GLYPHID +#undef G +#undef OT_UARRAY +#undef OT_UHEADLESSARRAY + +#undef OT_LOOKUP_FLAG_IGNORE_MARKS +#undef OT_LOOKUP +#undef OT_SUBLOOKUP +#undef OT_COVERAGE1 +#undef OT_LOOKUP_TYPE_SUBST_SINGLE +#undef OT_LOOKUP_TYPE_SUBST_LIGATURE +#undef OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2 +#undef OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1 +#undef OT_LIGATURE_SET +#undef OT_LIGATURE + /* * Include a second time to get the table data... diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc index 222c5d6b71..2298aa92f2 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc @@ -321,6 +321,20 @@ arabic_joining (hb_buffer_t *buffer) info[prev].arabic_shaping_action() = entry->prev_action; buffer->unsafe_to_break (prev, i + 1); } + else + { + if (prev == UINT_MAX) + { + if (this_type >= JOINING_TYPE_R) + buffer->unsafe_to_concat_from_outbuffer (0, i + 1); + } + else + { + if (this_type >= JOINING_TYPE_R || + (2 <= state && state <= 5) /* States that have a possible prev_action. */) + buffer->unsafe_to_concat (prev, i + 1); + } + } info[i].arabic_shaping_action() = entry->curr_action; @@ -337,7 +351,14 @@ arabic_joining (hb_buffer_t *buffer) const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; if (entry->prev_action != NONE && prev != UINT_MAX) + { info[prev].arabic_shaping_action() = entry->prev_action; + buffer->unsafe_to_break (prev, buffer->len); + } + else if (2 <= state && state <= 5) /* States that have a possible prev_action. */ + { + buffer->unsafe_to_concat (prev, buffer->len); + } break; } } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc index 0d84a76b85..3bc9e9b961 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc @@ -140,7 +140,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, * * - LV can be precomposed, or decomposed. Lets call those * <LV> and <L,V>, - * - LVT can be fully precomposed, partically precomposed, or + * - LVT can be fully precomposed, partially precomposed, or * fully decomposed. Ie. <LVT>, <LV,T>, or <L,V,T>. * * The composition / decomposition is mechanical. However, not @@ -392,7 +392,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, */ (void) buffer->next_glyph (); } - buffer->swap_buffers (); + buffer->sync (); } static void diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc index 5a08f878dc..76092c7f38 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc @@ -96,7 +96,7 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font, else (void) buffer->next_glyph (); } - buffer->swap_buffers (); + buffer->sync (); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc index 4c3068173b..a1e27a83be 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc @@ -364,7 +364,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan, buffer->merge_out_clusters (start - 1, end); } } - buffer->swap_buffers (); + buffer->sync (); /* If font has Thai GSUB, we are done. */ if (plan->props.script == HB_SCRIPT_THAI && !plan->map.found_script[0]) diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc index 045731dfb4..d2cca105a4 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc @@ -435,7 +435,7 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, default: break; } - buffer->swap_buffers (); + buffer->sync (); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc b/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc index eb1bc79768..671f30327f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc @@ -446,6 +446,9 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan, return; #endif + if (!buffer->message (font, "start fallback mark")) + return; + _hb_buffer_assert_gsubgpos_vars (buffer); unsigned int start = 0; @@ -457,6 +460,8 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan, start = i; } position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing); + + (void) buffer->message (font, "end fallback mark"); } @@ -492,6 +497,9 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, #endif #ifndef HB_DISABLE_DEPRECATED + if (!buffer->message (font, "start fallback kern")) + return; + if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ? !font->has_glyph_h_kerning_func () : !font->has_glyph_v_kerning_func ()) @@ -508,6 +516,8 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, if (reverse) buffer->reverse (); + + (void) buffer->message (font, "end fallback kern"); #endif } @@ -525,6 +535,15 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED, for (unsigned int i = 0; i < count; i++) if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i])) { + /* If font had no ASCII space and we used the invisible glyph, give it a 1/4 EM default advance. */ + if (buffer->invisible && info[i].codepoint == buffer->invisible) + { + if (horizontal) + pos[i].x_advance = +font->x_scale / 4; + else + pos[i].y_advance = -font->y_scale / 4; + } + hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]); hb_codepoint_t glyph; typedef hb_unicode_funcs_t t; diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc index 839cc9122c..aa5a8eeaa3 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc @@ -193,7 +193,8 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor { hb_codepoint_t space_glyph; hb_unicode_funcs_t::space_t space_type = buffer->unicode->space_fallback_type (u); - if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_nominal_glyph (0x0020u, &space_glyph)) + if (space_type != hb_unicode_funcs_t::NOT_SPACE && + (c->font->get_nominal_glyph (0x0020, &space_glyph) || (space_glyph = buffer->invisible))) { _hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type); next_char (buffer, space_glyph); @@ -374,7 +375,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, decompose_multi_char_cluster (&c, end, always_short_circuit); } while (buffer->idx < count && buffer->successful); - buffer->swap_buffers (); + buffer->sync (); } @@ -477,7 +478,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (info_cc (buffer->prev()) == 0) starter = buffer->out_len - 1; } - buffer->swap_buffers (); + buffer->sync (); } } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc index 4dde3520d8..4bd8aaf03b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc @@ -566,7 +566,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) info.mask = buffer->cur().mask; (void) buffer->output_info (info); - buffer->swap_buffers (); + buffer->sync (); } static void @@ -1034,7 +1034,7 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) * hanging over the next glyph after the final reordering. * * Note: If fallback positinoing happens, we don't care about - * this as it will be overriden. + * this as it will be overridden. */ bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing && HB_DIRECTION_IS_FORWARD (c->buffer->props.direction); @@ -1120,7 +1120,7 @@ hb_propagate_flags (hb_buffer_t *buffer) /* Propagate cluster-level glyph flags to be the same on all cluster glyphs. * Simplifies using them. */ - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK)) + if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS)) return; hb_glyph_info_t *info = buffer->info; @@ -1129,11 +1129,7 @@ hb_propagate_flags (hb_buffer_t *buffer) { unsigned int mask = 0; for (unsigned int i = start; i < end; i++) - if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) - { - mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; - break; - } + mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED; if (mask) for (unsigned int i = start; i < end; i++) info[i].mask |= mask; @@ -1145,18 +1141,7 @@ hb_propagate_flags (hb_buffer_t *buffer) static void hb_ot_shape_internal (hb_ot_shape_context_t *c) { - c->buffer->deallocate_var_all (); - c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; - if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR))) - { - c->buffer->max_len = hb_max (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR, - (unsigned) HB_BUFFER_MAX_LEN_MIN); - } - if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR))) - { - c->buffer->max_ops = hb_max (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR, - (unsigned) HB_BUFFER_MAX_OPS_MIN); - } + c->buffer->enter (); /* Save the original direction, we use it later. */ c->target_direction = c->buffer->props.direction; @@ -1188,9 +1173,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) c->buffer->props.direction = c->target_direction; - c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT; - c->buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT; - c->buffer->deallocate_var_all (); + c->buffer->leave (); } diff --git a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh index 2c6316df4f..61d2814e93 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh @@ -6,8 +6,8 @@ * * on files with these headers: * - * <meta name="updated_at" content="2021-12-09 12:01 AM" /> - * File-Date: 2021-08-06 + * <meta name="updated_at" content="2022-01-28 10:00 PM" /> + * File-Date: 2021-12-29 */ #ifndef HB_OT_TAG_TABLE_HH @@ -66,7 +66,7 @@ static const LangTag ot_languages[] = { {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */ /*{"ang", HB_TAG('A','N','G',' ')},*/ /* Old English (ca. 450-1100) -> Anglo-Saxon */ {"aoa", HB_TAG('C','P','P',' ')}, /* Angolar -> Creoles */ - {"apa", HB_TAG('A','T','H',' ')}, /* Apache [family] -> Athapaskan */ + {"apa", HB_TAG('A','T','H',' ')}, /* Apache [collection] -> Athapaskan */ {"apc", HB_TAG('A','R','A',' ')}, /* North Levantine Arabic -> Arabic */ {"apd", HB_TAG('A','R','A',' ')}, /* Sudanese Arabic -> Arabic */ {"apj", HB_TAG('A','T','H',' ')}, /* Jicarilla Apache -> Athapaskan */ @@ -86,7 +86,7 @@ static const LangTag ot_languages[] = { {"arz", HB_TAG('A','R','A',' ')}, /* Egyptian Arabic -> Arabic */ {"as", HB_TAG('A','S','M',' ')}, /* Assamese */ /*{"ast", HB_TAG('A','S','T',' ')},*/ /* Asturian */ -/*{"ath", HB_TAG('A','T','H',' ')},*/ /* Athapascan [family] -> Athapaskan */ +/*{"ath", HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */ {"atj", HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */ {"atv", HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */ {"auj", HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */ @@ -110,10 +110,10 @@ static const LangTag ot_languages[] = { {"azn", HB_TAG('N','A','H',' ')}, /* Western Durango Nahuatl -> Nahuatl */ {"azz", HB_TAG('N','A','H',' ')}, /* Highland Puebla Nahuatl -> Nahuatl */ {"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */ - {"bad", HB_TAG('B','A','D','0')}, /* Banda [family] */ + {"bad", HB_TAG('B','A','D','0')}, /* Banda [collection] */ {"bag", HB_TAG_NONE }, /* Tuki != Baghelkhandi */ {"bah", HB_TAG('C','P','P',' ')}, /* Bahamas Creole English -> Creoles */ - {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [family] */ + {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [collection] */ {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolanguage] */ /*{"ban", HB_TAG('B','A','N',' ')},*/ /* Balinese */ /*{"bar", HB_TAG('B','A','R',' ')},*/ /* Bavarian */ @@ -135,7 +135,7 @@ static const LangTag ot_languages[] = { {"bea", HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */ {"beb", HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */ /*{"bem", HB_TAG('B','E','M',' ')},*/ /* Bemba (Zambia) */ - {"ber", HB_TAG('B','B','R',' ')}, /* Berber [family] */ + {"ber", HB_TAG('B','B','R',' ')}, /* Berber [collection] */ {"bew", HB_TAG('C','P','P',' ')}, /* Betawi -> Creoles */ {"bfl", HB_TAG('B','A','D','0')}, /* Banda-Ndélé -> Banda */ {"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */ @@ -203,7 +203,7 @@ static const LangTag ot_languages[] = { {"btd", HB_TAG('B','T','K',' ')}, /* Batak Dairi -> Batak */ {"bti", HB_TAG_NONE }, /* Burate != Beti */ {"btj", HB_TAG('M','L','Y',' ')}, /* Bacanese Malay -> Malay */ -/*{"btk", HB_TAG('B','T','K',' ')},*/ /* Batak [family] */ +/*{"btk", HB_TAG('B','T','K',' ')},*/ /* Batak [collection] */ {"btm", HB_TAG('B','T','M',' ')}, /* Batak Mandailing */ {"btm", HB_TAG('B','T','K',' ')}, /* Batak Mandailing -> Batak */ {"bto", HB_TAG('B','I','K',' ')}, /* Rinconada Bikol -> Bikol */ @@ -256,6 +256,8 @@ static const LangTag ot_languages[] = { {"chh", HB_TAG_NONE }, /* Chinook != Chattisgarhi */ {"chj", HB_TAG('C','C','H','N')}, /* Ojitlán Chinantec -> Chinantec */ {"chk", HB_TAG('C','H','K','0')}, /* Chuukese */ + {"chm", HB_TAG('H','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> High Mari */ + {"chm", HB_TAG('L','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> Low Mari */ {"chn", HB_TAG('C','P','P',' ')}, /* Chinook jargon -> Creoles */ /*{"cho", HB_TAG('C','H','O',' ')},*/ /* Choctaw */ {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */ @@ -297,10 +299,10 @@ static const LangTag ot_languages[] = { /*{"cop", HB_TAG('C','O','P',' ')},*/ /* Coptic */ {"coq", HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */ {"cpa", HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */ - {"cpe", HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [family] -> Creoles */ - {"cpf", HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [family] -> Creoles */ + {"cpe", HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [collection] -> Creoles */ + {"cpf", HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [collection] -> Creoles */ {"cpi", HB_TAG('C','P','P',' ')}, /* Chinese Pidgin English -> Creoles */ -/*{"cpp", HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [family] -> Creoles */ +/*{"cpp", HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [collection] -> Creoles */ {"cpx", HB_TAG('Z','H','S',' ')}, /* Pu-Xian Chinese -> Chinese, Simplified */ {"cqd", HB_TAG('H','M','N',' ')}, /* Chuanqiandian Cluster Miao -> Hmong */ {"cqu", HB_TAG('Q','U','H',' ')}, /* Chilean Quechua (retired code) -> Quechua (Bolivia) */ @@ -320,7 +322,7 @@ static const LangTag ot_languages[] = { {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */ {"crm", HB_TAG('L','C','R',' ')}, /* Moose Cree -> L-Cree */ {"crm", HB_TAG('C','R','E',' ')}, /* Moose Cree -> Cree */ - {"crp", HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [family] -> Creoles */ + {"crp", HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [collection] -> Creoles */ {"crr", HB_TAG_NONE }, /* Carolina Algonquian != Carrier */ {"crs", HB_TAG('C','P','P',' ')}, /* Seselwa Creole French -> Creoles */ {"crt", HB_TAG_NONE }, /* Iyojwa'ja Chorote != Crimean Tatar */ @@ -431,7 +433,7 @@ static const LangTag ot_languages[] = { {"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */ {"eto", HB_TAG('B','T','I',' ')}, /* Eton (Cameroon) -> Beti */ {"eu", HB_TAG('E','U','Q',' ')}, /* Basque */ - {"euq", HB_TAG_NONE }, /* Basque [family] != Basque */ + {"euq", HB_TAG_NONE }, /* Basque [collection] != Basque */ {"eve", HB_TAG('E','V','N',' ')}, /* Even */ {"evn", HB_TAG('E','V','K',' ')}, /* Evenki */ {"ewo", HB_TAG('B','T','I',' ')}, /* Ewondo -> Beti */ @@ -620,10 +622,11 @@ static const LangTag ot_languages[] = { {"ijc", HB_TAG('I','J','O',' ')}, /* Izon -> Ijo */ {"ije", HB_TAG('I','J','O',' ')}, /* Biseni -> Ijo */ {"ijn", HB_TAG('I','J','O',' ')}, /* Kalabari -> Ijo */ -/*{"ijo", HB_TAG('I','J','O',' ')},*/ /* Ijo [family] */ +/*{"ijo", HB_TAG('I','J','O',' ')},*/ /* Ijo [collection] */ {"ijs", HB_TAG('I','J','O',' ')}, /* Southeast Ijo -> Ijo */ {"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] -> Inupiat */ {"ike", HB_TAG('I','N','U',' ')}, /* Eastern Canadian Inuktitut -> Inuktitut */ + {"ike", HB_TAG('I','N','U','K')}, /* Eastern Canadian Inuktitut -> Nunavik Inuktitut */ {"ikt", HB_TAG('I','N','U',' ')}, /* Inuinnaqtun -> Inuktitut */ /*{"ilo", HB_TAG('I','L','O',' ')},*/ /* Iloko -> Ilokano */ {"in", HB_TAG('I','N','D',' ')}, /* Indonesian (retired code) */ @@ -638,6 +641,7 @@ static const LangTag ot_languages[] = { {"it", HB_TAG('I','T','A',' ')}, /* Italian */ {"itz", HB_TAG('M','Y','N',' ')}, /* Itzá -> Mayan */ {"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */ + {"iu", HB_TAG('I','N','U','K')}, /* Inuktitut [macrolanguage] -> Nunavik Inuktitut */ {"iw", HB_TAG('I','W','R',' ')}, /* Hebrew (retired code) */ {"ixl", HB_TAG('M','Y','N',' ')}, /* Ixil -> Mayan */ {"ja", HB_TAG('J','A','N',' ')}, /* Japanese */ @@ -667,7 +671,7 @@ static const LangTag ot_languages[] = { {"kab", HB_TAG('B','B','R',' ')}, /* Kabyle -> Berber */ {"kac", HB_TAG_NONE }, /* Kachin != Kachchi */ {"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */ - {"kar", HB_TAG('K','R','N',' ')}, /* Karen [family] */ + {"kar", HB_TAG('K','R','N',' ')}, /* Karen [collection] */ /*{"kaw", HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */ {"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */ {"kby", HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */ @@ -876,7 +880,7 @@ static const LangTag ot_languages[] = { {"mam", HB_TAG('M','A','M',' ')}, /* Mam */ {"mam", HB_TAG('M','Y','N',' ')}, /* Mam -> Mayan */ {"man", HB_TAG('M','N','K',' ')}, /* Mandingo [macrolanguage] -> Maninka */ - {"map", HB_TAG_NONE }, /* Austronesian [family] != Mapudungun */ + {"map", HB_TAG_NONE }, /* Austronesian [collection] != Mapudungun */ {"maw", HB_TAG_NONE }, /* Mampruli != Marwari */ {"max", HB_TAG('M','L','Y',' ')}, /* North Moluccan Malay -> Malay */ {"max", HB_TAG('C','P','P',' ')}, /* North Moluccan Malay -> Creoles */ @@ -936,6 +940,7 @@ static const LangTag ot_languages[] = { {"mnw", HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */ {"mnx", HB_TAG_NONE }, /* Manikion != Manx */ {"mo", HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */ + {"mo", HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */ {"mod", HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */ /*{"moh", HB_TAG('M','O','H',' ')},*/ /* Mohawk */ {"mok", HB_TAG_NONE }, /* Morori != Moksha */ @@ -958,7 +963,7 @@ static const LangTag ot_languages[] = { {"mts", HB_TAG_NONE }, /* Yora != Maltese */ {"mud", HB_TAG('C','P','P',' ')}, /* Mednyj Aleut -> Creoles */ {"mui", HB_TAG('M','L','Y',' ')}, /* Musi -> Malay */ - {"mun", HB_TAG_NONE }, /* Munda [family] != Mundari */ + {"mun", HB_TAG_NONE }, /* Munda [collection] != Mundari */ {"mup", HB_TAG('R','A','J',' ')}, /* Malvi -> Rajasthani */ {"muq", HB_TAG('H','M','N',' ')}, /* Eastern Xiangxi Miao -> Hmong */ /*{"mus", HB_TAG('M','U','S',' ')},*/ /* Creek -> Muscogee */ @@ -973,7 +978,7 @@ static const LangTag ot_languages[] = { {"mww", HB_TAG('H','M','N',' ')}, /* Hmong Daw -> Hmong */ {"my", HB_TAG('B','R','M',' ')}, /* Burmese */ {"mym", HB_TAG('M','E','N',' ')}, /* Me’en */ -/*{"myn", HB_TAG('M','Y','N',' ')},*/ /* Mayan [family] */ +/*{"myn", HB_TAG('M','Y','N',' ')},*/ /* Mayan [collection] */ {"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) -> Maninka */ {"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */ {"mzb", HB_TAG('B','B','R',' ')}, /* Tumzabt -> Berber */ @@ -982,7 +987,7 @@ static const LangTag ot_languages[] = { {"na", HB_TAG('N','A','U',' ')}, /* Nauru -> Nauruan */ {"nag", HB_TAG('N','A','G',' ')}, /* Naga Pidgin -> Naga-Assamese */ {"nag", HB_TAG('C','P','P',' ')}, /* Naga Pidgin -> Creoles */ -/*{"nah", HB_TAG('N','A','H',' ')},*/ /* Nahuatl [family] */ +/*{"nah", HB_TAG('N','A','H',' ')},*/ /* Nahuatl [collection] */ {"nan", HB_TAG('Z','H','S',' ')}, /* Min Nan Chinese -> Chinese, Simplified */ /*{"nap", HB_TAG('N','A','P',' ')},*/ /* Neapolitan */ {"nas", HB_TAG_NONE }, /* Naasioi != Naskapi */ @@ -1039,7 +1044,6 @@ static const LangTag ot_languages[] = { {"nln", HB_TAG('N','A','H',' ')}, /* Durango Nahuatl (retired code) -> Nahuatl */ {"nlv", HB_TAG('N','A','H',' ')}, /* Orizaba Nahuatl -> Nahuatl */ {"nn", HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk (Nynorsk, Norwegian) */ - {"nn", HB_TAG('N','O','R',' ')}, /* Norwegian Nynorsk -> Norwegian */ {"nnh", HB_TAG('B','M','L',' ')}, /* Ngiemboon -> Bamileke */ {"nnz", HB_TAG('B','M','L',' ')}, /* Nda'nda' -> Bamileke */ {"no", HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */ @@ -1093,7 +1097,7 @@ static const LangTag ot_languages[] = { {"otw", HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */ {"oua", HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */ {"pa", HB_TAG('P','A','N',' ')}, /* Punjabi */ - {"paa", HB_TAG_NONE }, /* Papuan [family] != Palestinian Aramaic */ + {"paa", HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */ /*{"pag", HB_TAG('P','A','G',' ')},*/ /* Pangasinan */ {"pal", HB_TAG_NONE }, /* Pahlavi != Pali */ /*{"pam", HB_TAG('P','A','M',' ')},*/ /* Pampanga -> Pampangan */ @@ -1308,6 +1312,9 @@ static const LangTag ot_languages[] = { {"sgo", HB_TAG_NONE }, /* Songa (retired code) != Sango */ /*{"sgs", HB_TAG('S','G','S',' ')},*/ /* Samogitian */ {"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage -> Chaha Gurage */ + {"sh", HB_TAG('B','O','S',' ')}, /* Serbo-Croatian [macrolanguage] -> Bosnian */ + {"sh", HB_TAG('H','R','V',' ')}, /* Serbo-Croatian [macrolanguage] -> Croatian */ + {"sh", HB_TAG('S','R','B',' ')}, /* Serbo-Croatian [macrolanguage] -> Serbian */ {"shi", HB_TAG('S','H','I',' ')}, /* Tachelhit */ {"shi", HB_TAG('B','B','R',' ')}, /* Tachelhit -> Berber */ {"shl", HB_TAG('Q','I','N',' ')}, /* Shendu -> Chin */ @@ -1329,7 +1336,7 @@ static const LangTag ot_languages[] = { {"skw", HB_TAG('C','P','P',' ')}, /* Skepi Creole Dutch -> Creoles */ {"sky", HB_TAG_NONE }, /* Sikaiana != Slovak */ {"sl", HB_TAG('S','L','V',' ')}, /* Slovenian */ - {"sla", HB_TAG_NONE }, /* Slavic [family] != Slavey */ + {"sla", HB_TAG_NONE }, /* Slavic [collection] != Slavey */ {"sm", HB_TAG('S','M','O',' ')}, /* Samoan */ {"sma", HB_TAG('S','S','M',' ')}, /* Southern Sami */ {"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */ @@ -1451,7 +1458,7 @@ static const LangTag ot_languages[] = { {"tpi", HB_TAG('C','P','P',' ')}, /* Tok Pisin -> Creoles */ {"tr", HB_TAG('T','R','K',' ')}, /* Turkish */ {"trf", HB_TAG('C','P','P',' ')}, /* Trinidadian Creole English -> Creoles */ - {"trk", HB_TAG_NONE }, /* Turkic [family] != Turkish */ + {"trk", HB_TAG_NONE }, /* Turkic [collection] != Turkish */ {"tru", HB_TAG('T','U','A',' ')}, /* Turoyo -> Turoyo Aramaic */ {"tru", HB_TAG('S','Y','R',' ')}, /* Turoyo -> Syriac */ {"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */ @@ -1593,7 +1600,7 @@ static const LangTag ot_languages[] = { {"zlq", HB_TAG('Z','H','A',' ')}, /* Liuqian Zhuang -> Zhuang */ {"zmi", HB_TAG('M','L','Y',' ')}, /* Negeri Sembilan Malay -> Malay */ {"zmz", HB_TAG('B','A','D','0')}, /* Mbandja -> Banda */ - {"znd", HB_TAG_NONE }, /* Zande [family] != Zande */ + {"znd", HB_TAG_NONE }, /* Zande [collection] != Zande */ {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */ {"zom", HB_TAG('Q','I','N',' ')}, /* Zou -> Chin */ {"zqe", HB_TAG('Z','H','A',' ')}, /* Qiubei Zhuang -> Zhuang */ @@ -2607,14 +2614,8 @@ hb_ot_tags_from_complex_language (const char *lang_str, if (0 == strcmp (&lang_str[1], "o-nyn")) { /* Norwegian Nynorsk (retired code) */ - unsigned int i; - hb_tag_t possible_tags[] = { - HB_TAG('N','Y','N',' '), /* Norwegian Nynorsk (Nynorsk, Norwegian) */ - HB_TAG('N','O','R',' '), /* Norwegian */ - }; - for (i = 0; i < 2 && i < *count; i++) - tags[i] = possible_tags[i]; - *count = i; + tags[0] = HB_TAG('N','Y','N',' '); /* Norwegian Nynorsk (Nynorsk, Norwegian) */ + *count = 1; return true; } break; @@ -2623,8 +2624,14 @@ hb_ot_tags_from_complex_language (const char *lang_str, && subtag_matches (lang_str, limit, "-md")) { /* Romanian; Moldova */ - tags[0] = HB_TAG('M','O','L',' '); /* Moldavian */ - *count = 1; + unsigned int i; + hb_tag_t possible_tags[] = { + HB_TAG('M','O','L',' '), /* Moldavian */ + HB_TAG('R','O','M',' '), /* Romanian */ + }; + for (i = 0; i < 2 && i < *count; i++) + tags[i] = possible_tags[i]; + *count = i; return true; } break; @@ -2813,15 +2820,15 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) case HB_TAG('A','R','K',' '): /* Rakhine */ return hb_language_from_string ("rki", -1); /* Rakhine */ case HB_TAG('A','T','H',' '): /* Athapaskan */ - return hb_language_from_string ("ath", -1); /* Athapascan [family] */ + return hb_language_from_string ("ath", -1); /* Athapascan [collection] */ case HB_TAG('B','B','R',' '): /* Berber */ - return hb_language_from_string ("ber", -1); /* Berber [family] */ + return hb_language_from_string ("ber", -1); /* Berber [collection] */ case HB_TAG('B','I','K',' '): /* Bikol */ return hb_language_from_string ("bik", -1); /* Bikol [macrolanguage] */ case HB_TAG('B','T','K',' '): /* Batak */ - return hb_language_from_string ("btk", -1); /* Batak [family] */ + return hb_language_from_string ("btk", -1); /* Batak [collection] */ case HB_TAG('C','P','P',' '): /* Creoles */ - return hb_language_from_string ("crp", -1); /* Creoles and pidgins [family] */ + return hb_language_from_string ("crp", -1); /* Creoles and pidgins [collection] */ case HB_TAG('C','R','R',' '): /* Carrier */ return hb_language_from_string ("crx", -1); /* Carrier */ case HB_TAG('D','G','R',' '): /* Dogri (macrolanguage) */ @@ -2838,6 +2845,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("fa", -1); /* Persian [macrolanguage] */ case HB_TAG('G','O','N',' '): /* Gondi */ return hb_language_from_string ("gon", -1); /* Gondi [macrolanguage] */ + case HB_TAG('H','M','A',' '): /* High Mari */ + return hb_language_from_string ("mrj", -1); /* Western Mari */ case HB_TAG('H','M','N',' '): /* Hmong */ return hb_language_from_string ("hmn", -1); /* Hmong [macrolanguage] */ case HB_TAG('H','N','D',' '): /* Hindko */ @@ -2847,7 +2856,7 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) case HB_TAG('I','B','A',' '): /* Iban */ return hb_language_from_string ("iba", -1); /* Iban */ case HB_TAG('I','J','O',' '): /* Ijo */ - return hb_language_from_string ("ijo", -1); /* Ijo [family] */ + return hb_language_from_string ("ijo", -1); /* Ijo [collection] */ case HB_TAG('I','N','U',' '): /* Inuktitut */ return hb_language_from_string ("iu", -1); /* Inuktitut [macrolanguage] */ case HB_TAG('I','P','K',' '): /* Inupiat */ @@ -2873,11 +2882,13 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) case HB_TAG('K','P','L',' '): /* Kpelle */ return hb_language_from_string ("kpe", -1); /* Kpelle [macrolanguage] */ case HB_TAG('K','R','N',' '): /* Karen */ - return hb_language_from_string ("kar", -1); /* Karen [family] */ + return hb_language_from_string ("kar", -1); /* Karen [collection] */ case HB_TAG('K','U','I',' '): /* Kui */ return hb_language_from_string ("uki", -1); /* Kui (India) */ case HB_TAG('K','U','R',' '): /* Kurdish */ return hb_language_from_string ("ku", -1); /* Kurdish [macrolanguage] */ + case HB_TAG('L','M','A',' '): /* Low Mari */ + return hb_language_from_string ("mhr", -1); /* Eastern Mari */ case HB_TAG('L','U','H',' '): /* Luyia */ return hb_language_from_string ("luy", -1); /* Luyia [macrolanguage] */ case HB_TAG('L','V','I',' '): /* Latvian */ @@ -2897,9 +2908,9 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) case HB_TAG('M','O','N','T'): /* Thailand Mon */ return hb_language_from_string ("mnw-TH", -1); /* Mon; Thailand */ case HB_TAG('M','Y','N',' '): /* Mayan */ - return hb_language_from_string ("myn", -1); /* Mayan [family] */ + return hb_language_from_string ("myn", -1); /* Mayan [collection] */ case HB_TAG('N','A','H',' '): /* Nahuatl */ - return hb_language_from_string ("nah", -1); /* Nahuatl [family] */ + return hb_language_from_string ("nah", -1); /* Nahuatl [collection] */ case HB_TAG('N','E','P',' '): /* Nepali */ return hb_language_from_string ("ne", -1); /* Nepali [macrolanguage] */ case HB_TAG('N','I','S',' '): /* Nisi */ @@ -2926,6 +2937,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("qwh", -1); /* Huaylas Ancash Quechua */ case HB_TAG('R','A','J',' '): /* Rajasthani */ return hb_language_from_string ("raj", -1); /* Rajasthani [macrolanguage] */ + case HB_TAG('R','O','M',' '): /* Romanian */ + return hb_language_from_string ("ro", -1); /* Romanian */ case HB_TAG('R','O','Y',' '): /* Romany */ return hb_language_from_string ("rom", -1); /* Romany [macrolanguage] */ case HB_TAG('S','Q','I',' '): /* Albanian */ diff --git a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh index 05f289db26..e066558683 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh @@ -263,7 +263,7 @@ struct fvar if (coords_length && *coords_length) { hb_array_t<const HBFixed> instanceCoords = instance->get_coordinates (axisCount) - .sub_array (0, *coords_length); + .sub_array (0, coords_length); for (unsigned int i = 0; i < instanceCoords.length; i++) coords[i] = instanceCoords.arrayZ[i].to_float (); } diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh index 49b5532d40..539213c339 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh @@ -399,7 +399,7 @@ struct gvar get_offset (glyphCount) - get_offset (0))); } - /* GlyphVariationData not sanitized here; must be checked while accessing each glyph varation data */ + /* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */ bool sanitize (hb_sanitize_context_t *c) const { return sanitize_shallow (c); } @@ -498,9 +498,9 @@ struct gvar public: struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { table = hb_sanitize_context_t ().reference_table<gvar> (face); } - void fini () { table.destroy (); } + ~accelerator_t () { table.destroy (); } private: struct x_getter { static float get (const contour_point_t &p) { return p.x; } }; @@ -698,7 +698,9 @@ no_more_gaps: DEFINE_SIZE_MIN (20); }; -struct gvar_accelerator_t : gvar::accelerator_t {}; +struct gvar_accelerator_t : gvar::accelerator_t { + gvar_accelerator_t (hb_face_t *face) : gvar::accelerator_t (face) {} +}; } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh index 074b6a3785..e9d90352f0 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh @@ -177,9 +177,6 @@ struct hvarvvar_subset_plan_t inner_maps.resize (var_store->get_sub_table_count ()); - for (unsigned int i = 0; i < inner_maps.length; i++) - inner_maps[i].init (); - if (unlikely (!index_map_plans.length || !inner_sets.length || !inner_maps.length)) return; bool retain_adv_map = false; @@ -229,8 +226,8 @@ struct hvarvvar_subset_plan_t for (unsigned int i = 0; i < inner_sets.length; i++) hb_set_destroy (inner_sets[i]); hb_set_destroy (adv_set); - inner_maps.fini_deep (); - index_map_plans.fini_deep (); + inner_maps.fini (); + index_map_plans.fini (); } hb_inc_bimap_t outer_map; diff --git a/thirdparty/harfbuzz/src/hb-ot-var.cc b/thirdparty/harfbuzz/src/hb-ot-var.cc index 6b42b45cd9..0376e26b4a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var.cc +++ b/thirdparty/harfbuzz/src/hb-ot-var.cc @@ -303,6 +303,9 @@ hb_ot_var_normalize_variations (hb_face_t *face, * values for the axis are mapped to the interval [-1,1], with the default * axis value mapped to 0. * + * The normalized values have 14 bits of fixed-point sub-integer precision as per + * OpenType specification. + * * Any additional scaling defined in the face's `avar` table is also * applied, as described at https://docs.microsoft.com/en-us/typography/opentype/spec/avar * diff --git a/thirdparty/harfbuzz/src/hb-ot-var.h b/thirdparty/harfbuzz/src/hb-ot-var.h index ce201d3b4f..05147cc25e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var.h +++ b/thirdparty/harfbuzz/src/hb-ot-var.h @@ -109,7 +109,7 @@ typedef enum { /*< flags >*/ * @tag: The #hb_tag_t tag identifying the design variation of the axis * @name_id: The `name` table Name ID that provides display names for the axis * @flags: The #hb_ot_var_axis_flags_t flags for the axis - * @min_value: The mininum value on the variation axis that the font covers + * @min_value: The minimum value on the variation axis that the font covers * @default_value: The position on the variation axis corresponding to the font's defaults * @max_value: The maximum value on the variation axis that the font covers * diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh index 5c46b4cccc..b1726d8beb 100644 --- a/thirdparty/harfbuzz/src/hb-repacker.hh +++ b/thirdparty/harfbuzz/src/hb-repacker.hh @@ -42,26 +42,13 @@ struct graph_t { struct vertex_t { - vertex_t () : - distance (0), - space (0), - parents (), - start (0), - end (0), - priority(0) {} - - void fini () { - obj.fini (); - parents.fini (); - } - hb_serialize_context_t::object_t obj; - int64_t distance; - int64_t space; + int64_t distance = 0 ; + int64_t space = 0 ; hb_vector_t<unsigned> parents; - unsigned start; - unsigned end; - unsigned priority; + unsigned start = 0; + unsigned end = 0; + unsigned priority = 0; bool is_shared () const { @@ -186,7 +173,7 @@ struct graph_t ~graph_t () { - vertices_.fini_deep (); + vertices_.fini (); } bool in_error () const @@ -309,7 +296,7 @@ struct graph_t remap_all_obj_indices (id_map, &sorted_graph); hb_swap (vertices_, sorted_graph); - sorted_graph.fini_deep (); + sorted_graph.fini (); } /* @@ -369,7 +356,7 @@ struct graph_t remap_all_obj_indices (id_map, &sorted_graph); hb_swap (vertices_, sorted_graph); - sorted_graph.fini_deep (); + sorted_graph.fini (); } /* @@ -402,11 +389,15 @@ struct graph_t while (roots) { unsigned next = HB_SET_VALUE_INVALID; + if (unlikely (!check_success (!roots.in_error ()))) break; if (!roots.next (&next)) break; hb_set_t connected_roots; find_connected_nodes (next, roots, visited, connected_roots); + if (unlikely (!check_success (!connected_roots.in_error ()))) break; + isolate_subgraph (connected_roots); + if (unlikely (!check_success (!connected_roots.in_error ()))) break; unsigned next_space = this->next_space (); num_roots_for_space_.push (0); @@ -423,6 +414,8 @@ struct graph_t // into the 32 bit space as needed, instead of using isolation. } + + return true; } @@ -865,7 +858,7 @@ struct graph_t // Redundant ones are filtered out later on by the visited set. // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf // for practical performance this is faster then using a more advanced queue - // (such as a fibonaacci queue) with a fast decrease priority. + // (such as a fibonacci queue) with a fast decrease priority. for (unsigned i = 0; i < vertices_.length; i++) { if (i == vertices_.length - 1) @@ -1074,6 +1067,7 @@ struct graph_t hb_set_t& visited, hb_set_t& connected) { + if (unlikely (!check_success (!visited.in_error ()))) return; if (visited.has (start_idx)) return; visited.add (start_idx); diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh index 823c0be8b5..6615f033c5 100644 --- a/thirdparty/harfbuzz/src/hb-serialize.hh +++ b/thirdparty/harfbuzz/src/hb-serialize.hh @@ -279,7 +279,7 @@ struct hb_serialize_context_t object_pool.release (obj); } - /* Set share to false when an object is unlikely sharable with others + /* Set share to false when an object is unlikely shareable with others * so not worth an attempt, or a contiguous table is serialized as * multiple consecutive objects in the reverse order so can't be shared. */ @@ -381,7 +381,7 @@ struct hb_serialize_context_t // Adding a virtual link from object a to object b will ensure that object b is always packed after // object a in the final serialized order. // - // This is useful in certain situtations where there needs to be a specific ordering in the + // This is useful in certain situations where there needs to be a specific ordering in the // final serialization. Such as when platform bugs require certain orderings, or to provide // guidance to the repacker for better offset overflow resolution. void add_virtual_link (objidx_t objidx) @@ -510,7 +510,7 @@ struct hb_serialize_context_t { return reinterpret_cast<Type *> (this->head); } template <typename Type> Type *start_embed (const Type &obj) const - { return start_embed (hb_addressof (obj)); } + { return start_embed (std::addressof (obj)); } bool err (hb_serialize_error_t err_type) { @@ -548,7 +548,7 @@ struct hb_serialize_context_t } template <typename Type> Type *embed (const Type &obj) - { return embed (hb_addressof (obj)); } + { return embed (std::addressof (obj)); } template <typename Type, typename ...Ts> auto _copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN @@ -595,19 +595,19 @@ struct hb_serialize_context_t } template <typename Type> Type *extend_size (Type &obj, size_t size) - { return extend_size (hb_addressof (obj), size); } + { return extend_size (std::addressof (obj), size); } template <typename Type> Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); } template <typename Type> - Type *extend_min (Type &obj) { return extend_min (hb_addressof (obj)); } + Type *extend_min (Type &obj) { return extend_min (std::addressof (obj)); } template <typename Type, typename ...Ts> Type *extend (Type *obj, Ts&&... ds) { return extend_size (obj, obj->get_size (std::forward<Ts> (ds)...)); } template <typename Type, typename ...Ts> Type *extend (Type &obj, Ts&&... ds) - { return extend (hb_addressof (obj), std::forward<Ts> (ds)...); } + { return extend (std::addressof (obj), std::forward<Ts> (ds)...); } /* Output routines. */ hb_bytes_t copy_bytes () const diff --git a/thirdparty/harfbuzz/src/hb-style.cc b/thirdparty/harfbuzz/src/hb-style.cc index f1b44cea53..c0c5c4832c 100644 --- a/thirdparty/harfbuzz/src/hb-style.cc +++ b/thirdparty/harfbuzz/src/hb-style.cc @@ -48,13 +48,12 @@ _hb_angle_to_ratio (float a) { return tanf (a * float (M_PI / 180.)); } -#if 0 + static inline float _hb_ratio_to_angle (float r) { return atanf (r) * float (180. / M_PI); } -#endif /** * hb_style_get_value: @@ -73,7 +72,8 @@ float hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag) { if (unlikely (style_tag == HB_STYLE_TAG_SLANT_RATIO)) - return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE)); + return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE)) + + font->slant; hb_face_t *face = font->face; @@ -109,7 +109,14 @@ hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag) : 12.f; } case HB_STYLE_TAG_SLANT_ANGLE: - return face->table.post->table->italicAngle.to_float (); + { + float angle = face->table.post->table->italicAngle.to_float (); + + if (font->slant) + angle = _hb_ratio_to_angle (font->slant + _hb_angle_to_ratio (angle)); + + return angle; + } case HB_STYLE_TAG_WIDTH: return face->table.OS2->has_data () ? face->table.OS2->get_width () diff --git a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh index 7fd96ca86d..18657705fa 100644 --- a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh +++ b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh @@ -275,60 +275,36 @@ struct subr_flattener_t struct subr_closures_t { - subr_closures_t () : valid (false), global_closure (nullptr) - { local_closures.init (); } - - void init (unsigned int fd_count) + subr_closures_t (unsigned int fd_count) : valid (false), global_closure (), local_closures () { valid = true; - global_closure = hb_set_create (); - if (global_closure == hb_set_get_empty ()) - valid = false; if (!local_closures.resize (fd_count)) valid = false; - - for (unsigned int i = 0; i < local_closures.length; i++) - { - local_closures[i] = hb_set_create (); - if (local_closures[i] == hb_set_get_empty ()) - valid = false; - } - } - - void fini () - { - hb_set_destroy (global_closure); - for (unsigned int i = 0; i < local_closures.length; i++) - hb_set_destroy (local_closures[i]); - local_closures.fini (); } void reset () { - hb_set_clear (global_closure); + global_closure.clear(); for (unsigned int i = 0; i < local_closures.length; i++) - hb_set_clear (local_closures[i]); + local_closures[i].clear(); } bool is_valid () const { return valid; } bool valid; - hb_set_t *global_closure; - hb_vector_t<hb_set_t *> local_closures; + hb_set_t global_closure; + hb_vector_t<hb_set_t> local_closures; }; struct parsed_cs_op_t : op_str_t { void init (unsigned int subr_num_ = 0) { - op_str_t::init (); subr_num = subr_num_; drop_flag = false; keep_flag = false; skip_flag = false; } - void fini () { op_str_t::fini (); } - bool for_drop () const { return drop_flag; } void set_drop () { if (!for_keep ()) drop_flag = true; } @@ -416,16 +392,6 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t> struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t> { - void init (unsigned int len_ = 0) - { - SUPER::init (); - if (unlikely (!resize (len_))) - return; - for (unsigned int i = 0; i < length; i++) - (*this)[i].init (); - } - void fini () { SUPER::fini_deep (); } - private: typedef hb_vector_t<parsed_cs_str_t> SUPER; }; @@ -496,7 +462,7 @@ struct subr_subset_param_t struct subr_remap_t : hb_inc_bimap_t { - void create (hb_set_t *closure) + void create (const hb_set_t *closure) { /* create a remapping of subroutine numbers from old to new. * no optimization based on usage counts. fonttools doesn't appear doing that either. @@ -526,19 +492,9 @@ struct subr_remap_t : hb_inc_bimap_t struct subr_remaps_t { - subr_remaps_t () + subr_remaps_t (unsigned int fdCount) { - global_remap.init (); - local_remaps.init (); - } - - ~subr_remaps_t () { fini (); } - - void init (unsigned int fdCount) - { - if (unlikely (!local_remaps.resize (fdCount))) return; - for (unsigned int i = 0; i < fdCount; i++) - local_remaps[i].init (); + local_remaps.resize (fdCount); } bool in_error() @@ -548,15 +504,9 @@ struct subr_remaps_t void create (subr_closures_t& closures) { - global_remap.create (closures.global_closure); + global_remap.create (&closures.global_closure); for (unsigned int i = 0; i < local_remaps.length; i++) - local_remaps[i].create (closures.local_closures[i]); - } - - void fini () - { - global_remap.fini (); - local_remaps.fini_deep (); + local_remaps[i].create (&closures.local_closures[i]); } subr_remap_t global_remap; @@ -567,21 +517,8 @@ template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typena struct subr_subsetter_t { subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_) - : acc (acc_), plan (plan_) - { - parsed_charstrings.init (); - parsed_global_subrs.init (); - parsed_local_subrs.init (); - } - - ~subr_subsetter_t () - { - closures.fini (); - remaps.fini (); - parsed_charstrings.fini_deep (); - parsed_global_subrs.fini_deep (); - parsed_local_subrs.fini_deep (); - } + : acc (acc_), plan (plan_), closures(acc_.fdCount), remaps(acc_.fdCount) + {} /* Subroutine subsetting with --no-desubroutinize runs in phases: * @@ -599,11 +536,8 @@ struct subr_subsetter_t */ bool subset (void) { - closures.init (acc.fdCount); - remaps.init (acc.fdCount); - - parsed_charstrings.init (plan->num_output_glyphs ()); - parsed_global_subrs.init (acc.globalSubrs->count); + parsed_charstrings.resize (plan->num_output_glyphs ()); + parsed_global_subrs.resize (acc.globalSubrs->count); if (unlikely (remaps.in_error() || parsed_charstrings.in_error () @@ -615,7 +549,7 @@ struct subr_subsetter_t for (unsigned int i = 0; i < acc.fdCount; i++) { - parsed_local_subrs[i].init (acc.privateDicts[i].localSubrs->count); + parsed_local_subrs[i].resize (acc.privateDicts[i].localSubrs->count); if (unlikely (parsed_local_subrs[i].in_error ())) return false; } if (unlikely (!closures.valid)) @@ -638,7 +572,7 @@ struct subr_subsetter_t subr_subset_param_t param; param.init (&parsed_charstrings[i], &parsed_global_subrs, &parsed_local_subrs[fd], - closures.global_closure, closures.local_closures[fd], + &closures.global_closure, &closures.local_closures[fd], plan->flags & HB_SUBSET_FLAGS_NO_HINTING); if (unlikely (!interp.interpret (param))) @@ -662,7 +596,7 @@ struct subr_subsetter_t subr_subset_param_t param; param.init (&parsed_charstrings[i], &parsed_global_subrs, &parsed_local_subrs[fd], - closures.global_closure, closures.local_closures[fd], + &closures.global_closure, &closures.local_closures[fd], plan->flags & HB_SUBSET_FLAGS_NO_HINTING); drop_hints_param_t drop; @@ -687,7 +621,7 @@ struct subr_subsetter_t subr_subset_param_t param; param.init (&parsed_charstrings[i], &parsed_global_subrs, &parsed_local_subrs[fd], - closures.global_closure, closures.local_closures[fd], + &closures.global_closure, &closures.local_closures[fd], plan->flags & HB_SUBSET_FLAGS_NO_HINTING); collect_subr_refs_in_str (parsed_charstrings[i], param); } diff --git a/thirdparty/harfbuzz/src/hb-subset-cff1.cc b/thirdparty/harfbuzz/src/hb-subset-cff1.cc index b4e24122c9..35fecd67bc 100644 --- a/thirdparty/harfbuzz/src/hb-subset-cff1.cc +++ b/thirdparty/harfbuzz/src/hb-subset-cff1.cc @@ -362,43 +362,11 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs struct cff_subset_plan { cff_subset_plan () - : info (), - orig_fdcount (0), - subset_fdcount (1), - subset_fdselect_format (0), - drop_hints (false), - desubroutinize(false) { - topdict_mod.init (); - subset_fdselect_ranges.init (); - fdmap.init (); - subset_charstrings.init (); - subset_globalsubrs.init (); - subset_localsubrs.init (); - fontdicts_mod.init (); - subset_enc_code_ranges.init (); - subset_enc_supp_codes.init (); - subset_charset_ranges.init (); - sidmap.init (); for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++) topDictModSIDs[i] = CFF_UNDEF_SID; } - ~cff_subset_plan () - { - topdict_mod.fini (); - subset_fdselect_ranges.fini (); - fdmap.fini (); - subset_charstrings.fini_deep (); - subset_globalsubrs.fini_deep (); - subset_localsubrs.fini_deep (); - fontdicts_mod.fini (); - subset_enc_code_ranges.fini (); - subset_enc_supp_codes.fini (); - subset_charset_ranges.fini (); - sidmap.fini (); - } - void plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan) { const Encoding *encoding = acc.encoding; @@ -672,9 +640,9 @@ struct cff_subset_plan { cff1_sub_table_info_t info; unsigned int num_glyphs; - unsigned int orig_fdcount; - unsigned int subset_fdcount; - unsigned int subset_fdselect_format; + unsigned int orig_fdcount = 0; + unsigned int subset_fdcount = 1; + unsigned int subset_fdselect_format = 0; hb_vector_t<code_pair_t> subset_fdselect_ranges; /* font dict index remap table from fullset FDArray to subset FDArray. @@ -686,7 +654,7 @@ struct cff_subset_plan { hb_vector_t<str_buff_vec_t> subset_localsubrs; hb_vector_t<cff1_font_dict_values_mod_t> fontdicts_mod; - bool drop_hints; + bool drop_hints = false; bool gid_renum; bool subset_encoding; @@ -702,7 +670,7 @@ struct cff_subset_plan { remap_sid_t sidmap; unsigned int topDictModSIDs[name_dict_values_t::ValCount]; - bool desubroutinize; + bool desubroutinize = false; }; static bool _serialize_cff1 (hb_serialize_context_t *c, diff --git a/thirdparty/harfbuzz/src/hb-subset-cff2.cc b/thirdparty/harfbuzz/src/hb-subset-cff2.cc index 896ae64016..92dd6b1d2c 100644 --- a/thirdparty/harfbuzz/src/hb-subset-cff2.cc +++ b/thirdparty/harfbuzz/src/hb-subset-cff2.cc @@ -233,29 +233,6 @@ struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs }; struct cff2_subset_plan { - cff2_subset_plan () - : orig_fdcount (0), - subset_fdcount(1), - subset_fdselect_size (0), - subset_fdselect_format (0), - drop_hints (false), - desubroutinize (false) - { - subset_fdselect_ranges.init (); - fdmap.init (); - subset_charstrings.init (); - subset_globalsubrs.init (); - subset_localsubrs.init (); - } - - ~cff2_subset_plan () - { - subset_fdselect_ranges.fini (); - fdmap.fini (); - subset_charstrings.fini_deep (); - subset_globalsubrs.fini_deep (); - subset_localsubrs.fini_deep (); - } bool create (const OT::cff2::accelerator_subset_t &acc, hb_subset_plan_t *plan) @@ -320,10 +297,10 @@ struct cff2_subset_plan { cff2_sub_table_info_t info; - unsigned int orig_fdcount; - unsigned int subset_fdcount; - unsigned int subset_fdselect_size; - unsigned int subset_fdselect_format; + unsigned int orig_fdcount = 0; + unsigned int subset_fdcount = 1; + unsigned int subset_fdselect_size = 0; + unsigned int subset_fdselect_format = 0; hb_vector_t<code_pair_t> subset_fdselect_ranges; hb_inc_bimap_t fdmap; @@ -332,8 +309,8 @@ struct cff2_subset_plan { str_buff_vec_t subset_globalsubrs; hb_vector_t<str_buff_vec_t> subset_localsubrs; - bool drop_hints; - bool desubroutinize; + bool drop_hints = false; + bool desubroutinize = false; }; static bool _serialize_cff2 (hb_serialize_context_t *c, @@ -473,12 +450,8 @@ _hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc, bool hb_subset_cff2 (hb_subset_context_t *c) { - OT::cff2::accelerator_subset_t acc; - acc.init (c->plan->source); - bool result = likely (acc.is_valid ()) && _hb_subset_cff2 (acc, c); - acc.fini (); - - return result; + OT::cff2::accelerator_subset_t acc (c->plan->source); + return acc.is_valid () && _hb_subset_cff2 (acc, c); } #endif diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc index 883ab82093..af4fcb8137 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.cc +++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc @@ -228,10 +228,8 @@ _cmap_closure (hb_face_t *face, const hb_set_t *unicodes, hb_set_t *glyphset) { - OT::cmap::accelerator_t cmap; - cmap.init (face); + OT::cmap::accelerator_t cmap (face); cmap.table->closure_glyphs (unicodes, glyphset); - cmap.fini (); } static void _colr_closure (hb_face_t *face, @@ -239,8 +237,7 @@ static void _colr_closure (hb_face_t *face, hb_map_t *palettes_map, hb_set_t *glyphs_colred) { - OT::COLR::accelerator_t colr; - colr.init (face); + OT::COLR::accelerator_t colr (face); if (!colr.is_valid ()) return; unsigned iteration_count = 0; @@ -263,7 +260,6 @@ static void _colr_closure (hb_face_t *face, colr.closure_V0palette_indices (glyphs_colred, &palette_indices); _remap_indexes (&layer_indices, layers_map); _remap_palette_indexes (&palette_indices, palettes_map); - colr.fini (); } static inline void @@ -294,8 +290,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, const hb_set_t *glyphs, hb_subset_plan_t *plan) { - OT::cmap::accelerator_t cmap; - cmap.init (plan->source); + OT::cmap::accelerator_t cmap (plan->source); constexpr static const int size_threshold = 4096; @@ -343,8 +338,6 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, + plan->codepoint_to_glyph->keys () | hb_sink (plan->unicodes); + plan->codepoint_to_glyph->values () | hb_sink (plan->_glyphset_gsub); - - cmap.fini (); } static void @@ -353,13 +346,9 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, bool close_over_gpos, bool close_over_gdef) { - OT::glyf::accelerator_t glyf; -#ifndef HB_NO_SUBSET_CFF - OT::cff1::accelerator_t cff; -#endif - glyf.init (plan->source); + OT::glyf::accelerator_t glyf (plan->source); #ifndef HB_NO_SUBSET_CFF - cff.init (plan->source); + OT::cff1::accelerator_t cff (plan->source); #endif plan->_glyphset_gsub->add (0); // Not-def @@ -419,11 +408,6 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, plan->layout_variation_indices, plan->layout_variation_idx_map); #endif - -#ifndef HB_NO_SUBSET_CFF - cff.fini (); -#endif - glyf.fini (); } static void diff --git a/thirdparty/harfbuzz/src/hb-uniscribe.cc b/thirdparty/harfbuzz/src/hb-uniscribe.cc index 0e5a114f7d..50f71ce9ce 100644 --- a/thirdparty/harfbuzz/src/hb-uniscribe.cc +++ b/thirdparty/harfbuzz/src/hb-uniscribe.cc @@ -878,7 +878,8 @@ retry: if (backward) hb_buffer_reverse (buffer); - buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK); + buffer->clear_glyph_flags (); + buffer->unsafe_to_break (); /* Wow, done! */ return true; diff --git a/thirdparty/harfbuzz/src/hb-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh index b0a1e5e966..6c7d32e49d 100644 --- a/thirdparty/harfbuzz/src/hb-vector.hh +++ b/thirdparty/harfbuzz/src/hb-vector.hh @@ -32,11 +32,14 @@ #include "hb-null.hh" -template <typename Type> -struct hb_vector_t +template <typename Type, + bool sorted=false> +struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty_t>::type { typedef Type item_t; static constexpr unsigned item_size = hb_static_size (Type); + using array_t = typename std::conditional<sorted, hb_sorted_array_t<Type>, hb_array_t<Type>>::type; + using c_array_t = typename std::conditional<sorted, hb_sorted_array_t<const Type>, hb_array_t<const Type>>::type; hb_vector_t () = default; hb_vector_t (std::initializer_list<Type> lst) : hb_vector_t () @@ -82,16 +85,10 @@ struct hb_vector_t void fini () { + shrink_vector (0); hb_free (arrayZ); init (); } - void fini_deep () - { - unsigned int count = length; - for (unsigned int i = 0; i < count; i++) - arrayZ[i].fini (); - fini (); - } void reset () { @@ -152,24 +149,24 @@ struct hb_vector_t template <typename T> hb_vector_t& operator << (T&& v) { push (std::forward<T> (v)); return *this; } - hb_array_t< Type> as_array () { return hb_array (arrayZ, length); } - hb_array_t<const Type> as_array () const { return hb_array (arrayZ, length); } + array_t as_array () { return hb_array (arrayZ, length); } + c_array_t as_array () const { return hb_array (arrayZ, length); } /* Iterator. */ - typedef hb_array_t<const Type> iter_t; - typedef hb_array_t< Type> writer_t; + typedef c_array_t iter_t; + typedef array_t writer_t; iter_t iter () const { return as_array (); } writer_t writer () { return as_array (); } operator iter_t () const { return iter (); } operator writer_t () { return writer (); } - hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const + c_array_t sub_array (unsigned int start_offset, unsigned int count) const { return as_array ().sub_array (start_offset, count); } - hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const + c_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const { return as_array ().sub_array (start_offset, count); } - hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count) + array_t sub_array (unsigned int start_offset, unsigned int count) { return as_array ().sub_array (start_offset, count); } - hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) + array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) { return as_array ().sub_array (start_offset, count); } hb_sorted_array_t<Type> as_sorted_array () @@ -192,6 +189,7 @@ struct hb_vector_t template <typename T> Type *push (T&& v) { + /* TODO Emplace? */ Type *p = push (); if (p == &Crap (Type)) // If push failed to allocate then don't copy v, since this may cause @@ -204,6 +202,92 @@ struct hb_vector_t bool in_error () const { return allocated < 0; } + template <typename T = Type, + hb_enable_if (std::is_trivially_copy_assignable<T>::value)> + Type * + realloc_vector (unsigned new_allocated) + { + return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type)); + } + template <typename T = Type, + hb_enable_if (!std::is_trivially_copy_assignable<T>::value)> + Type * + realloc_vector (unsigned new_allocated) + { + Type *new_array = (Type *) hb_malloc (new_allocated * sizeof (Type)); + if (likely (new_array)) + { + for (unsigned i = 0; i < length; i++) + new (std::addressof (new_array[i])) Type (); + for (unsigned i = 0; i < (unsigned) length; i++) + new_array[i] = std::move (arrayZ[i]); + unsigned old_length = length; + shrink_vector (0); + length = old_length; + hb_free (arrayZ); + } + return new_array; + } + + template <typename T = Type, + hb_enable_if (std::is_trivially_constructible<T>::value || + !std::is_default_constructible<T>::value)> + void + grow_vector (unsigned size) + { + memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ)); + length = size; + } + template <typename T = Type, + hb_enable_if (!std::is_trivially_constructible<T>::value && + std::is_default_constructible<T>::value)> + void + grow_vector (unsigned size) + { + while (length < size) + { + length++; + new (std::addressof (arrayZ[length - 1])) Type (); + } + } + + template <typename T = Type, + hb_enable_if (std::is_trivially_destructible<T>::value)> + void + shrink_vector (unsigned size) + { + length = size; + } + template <typename T = Type, + hb_enable_if (!std::is_trivially_destructible<T>::value)> + void + shrink_vector (unsigned size) + { + while ((unsigned) length > size) + { + arrayZ[(unsigned) length - 1].~Type (); + length--; + } + } + + template <typename T = Type, + hb_enable_if (std::is_trivially_copy_assignable<T>::value)> + void + shift_down_vector (unsigned i) + { + memmove (static_cast<void *> (&arrayZ[i - 1]), + static_cast<void *> (&arrayZ[i]), + (length - i) * sizeof (Type)); + } + template <typename T = Type, + hb_enable_if (!std::is_trivially_copy_assignable<T>::value)> + void + shift_down_vector (unsigned i) + { + for (; i < length; i++) + arrayZ[i - 1] = std::move (arrayZ[i]); + } + /* Allocate for size but don't adjust length. */ bool alloc (unsigned int size) { @@ -225,7 +309,7 @@ struct hb_vector_t (new_allocated < (unsigned) allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type)); if (likely (!overflows)) - new_array = (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type)); + new_array = realloc_vector (new_allocated); if (unlikely (!new_array)) { @@ -246,7 +330,9 @@ struct hb_vector_t return false; if (size > length) - memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ)); + grow_vector (size); + else if (size < length) + shrink_vector (size); length = size; return true; @@ -255,48 +341,38 @@ struct hb_vector_t Type pop () { if (!length) return Null (Type); - return std::move (arrayZ[--length]); /* Does this move actually work? */ + Type v = std::move (arrayZ[length - 1]); + arrayZ[length - 1].~Type (); + length--; + return v; } void remove (unsigned int i) { if (unlikely (i >= length)) return; - memmove (static_cast<void *> (&arrayZ[i]), - static_cast<void *> (&arrayZ[i + 1]), - (length - i - 1) * sizeof (Type)); + arrayZ[i].~Type (); + shift_down_vector (i + 1); length--; } void shrink (int size_) { unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; - if (size < length) - length = size; - } + if (size >= length) + return; - template <typename T> - Type *find (T v) - { - for (unsigned int i = 0; i < length; i++) - if (arrayZ[i] == v) - return &arrayZ[i]; - return nullptr; - } - template <typename T> - const Type *find (T v) const - { - for (unsigned int i = 0; i < length; i++) - if (arrayZ[i] == v) - return &arrayZ[i]; - return nullptr; + shrink_vector (size); } + + /* Sorting API. */ void qsort (int (*cmp)(const void*, const void*)) { as_array ().qsort (cmp); } void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) { as_array ().qsort (start, end); } + /* Unsorted search API. */ template <typename T> Type *lsearch (const T &x, Type *not_found = nullptr) { return as_array ().lsearch (x, not_found); } @@ -306,47 +382,25 @@ struct hb_vector_t template <typename T> bool lfind (const T &x, unsigned *pos = nullptr) const { return as_array ().lfind (x, pos); } -}; -template <typename Type> -struct hb_sorted_vector_t : hb_vector_t<Type> -{ - hb_sorted_vector_t () = default; - ~hb_sorted_vector_t () = default; - hb_sorted_vector_t (hb_sorted_vector_t& o) = default; - hb_sorted_vector_t (hb_sorted_vector_t &&o) = default; - hb_sorted_vector_t (std::initializer_list<Type> lst) : hb_vector_t<Type> (lst) {} - template <typename Iterable, - hb_requires (hb_is_iterable (Iterable))> - hb_sorted_vector_t (const Iterable &o) : hb_vector_t<Type> (o) {} - hb_sorted_vector_t& operator = (const hb_sorted_vector_t &o) = default; - hb_sorted_vector_t& operator = (hb_sorted_vector_t &&o) = default; - friend void swap (hb_sorted_vector_t& a, hb_sorted_vector_t& b) - { hb_swap ((hb_vector_t<Type>&) (a), (hb_vector_t<Type>&) (b)); } - - hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->length); } - hb_sorted_array_t<const Type> as_array () const { return hb_sorted_array (this->arrayZ, this->length); } - - /* Iterator. */ - typedef hb_sorted_array_t<const Type> const_iter_t; - typedef hb_sorted_array_t< Type> iter_t; - const_iter_t iter () const { return as_array (); } - const_iter_t citer () const { return as_array (); } - iter_t iter () { return as_array (); } - operator iter_t () { return iter (); } - operator const_iter_t () const { return iter (); } - - template <typename T> + /* Sorted search API. */ + template <typename T, + bool Sorted=sorted, hb_enable_if (Sorted)> Type *bsearch (const T &x, Type *not_found = nullptr) { return as_array ().bsearch (x, not_found); } - template <typename T> + template <typename T, + bool Sorted=sorted, hb_enable_if (Sorted)> const Type *bsearch (const T &x, const Type *not_found = nullptr) const { return as_array ().bsearch (x, not_found); } - template <typename T> + template <typename T, + bool Sorted=sorted, hb_enable_if (Sorted)> bool bfind (const T &x, unsigned int *i = nullptr, hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, unsigned int to_store = (unsigned int) -1) const { return as_array ().bfind (x, i, not_found, to_store); } }; +template <typename Type> +using hb_sorted_vector_t = hb_vector_t<Type, true>; + #endif /* HB_VECTOR_HH */ diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index 52b124b745..91ccb3dcde 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -47,20 +47,20 @@ HB_BEGIN_DECLS * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 2 +#define HB_VERSION_MINOR 3 /** * HB_VERSION_MICRO: * * The micro component of the library version available at compile-time. */ -#define HB_VERSION_MICRO 0 +#define HB_VERSION_MICRO 1 /** * HB_VERSION_STRING: * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "3.2.0" +#define HB_VERSION_STRING "3.3.1" /** * HB_VERSION_ATLEAST: diff --git a/thirdparty/libwebp/AUTHORS b/thirdparty/libwebp/AUTHORS index 30abde0326..8307c2099d 100644 --- a/thirdparty/libwebp/AUTHORS +++ b/thirdparty/libwebp/AUTHORS @@ -32,6 +32,7 @@ Contributors: - Pascal Massimino (pascal dot massimino at gmail dot com) - PaweÅ‚ Hajdan, Jr (phajdan dot jr at chromium dot org) - Pierre Joye (pierre dot php at gmail dot com) +- Roberto Alanis (alanisbaez at google dot com) - Sam Clegg (sbc at chromium dot org) - Scott Hancher (seh at google dot com) - Scott LaVarnway (slavarnway at google dot com) diff --git a/thirdparty/libwebp/src/dec/vp8_dec.c b/thirdparty/libwebp/src/dec/vp8_dec.c index 5f405e4c2a..2003935ec4 100644 --- a/thirdparty/libwebp/src/dec/vp8_dec.c +++ b/thirdparty/libwebp/src/dec/vp8_dec.c @@ -403,7 +403,7 @@ static const uint8_t kZigzag[16] = { 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 }; -// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2 +// See section 13-2: https://datatracker.ietf.org/doc/html/rfc6386#section-13.2 static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { int v; if (!VP8GetBit(br, p[3], "coeffs")) { diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h index 20526a87c4..9af22f8cc6 100644 --- a/thirdparty/libwebp/src/dec/vp8i_dec.h +++ b/thirdparty/libwebp/src/dec/vp8i_dec.h @@ -32,7 +32,7 @@ extern "C" { // version numbers #define DEC_MAJ_VERSION 1 #define DEC_MIN_VERSION 2 -#define DEC_REV_VERSION 1 +#define DEC_REV_VERSION 2 // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // Constraints are: We need to store one 16x16 block of luma samples (y), diff --git a/thirdparty/libwebp/src/dec/vp8l_dec.c b/thirdparty/libwebp/src/dec/vp8l_dec.c index 73c3b54fff..78db014030 100644 --- a/thirdparty/libwebp/src/dec/vp8l_dec.c +++ b/thirdparty/libwebp/src/dec/vp8l_dec.c @@ -84,7 +84,7 @@ static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = { // to 256 (green component values) + 24 (length prefix values) // + color_cache_size (between 0 and 2048). // All values computed for 8-bit first level lookup with Mark Adler's tool: -// http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c +// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c #define FIXED_TABLE_SIZE (630 * 3 + 410) static const uint16_t kTableSize[12] = { FIXED_TABLE_SIZE + 654, diff --git a/thirdparty/libwebp/src/demux/anim_decode.c b/thirdparty/libwebp/src/demux/anim_decode.c index 2bf4dcffe0..e077ffb536 100644 --- a/thirdparty/libwebp/src/demux/anim_decode.c +++ b/thirdparty/libwebp/src/demux/anim_decode.c @@ -23,6 +23,14 @@ #define NUM_CHANNELS 4 +// Channel extraction from a uint32_t representation of a uint8_t RGBA/BGRA +// buffer. +#ifdef WORDS_BIGENDIAN +#define CHANNEL_SHIFT(i) (24 - (i) * 8) +#else +#define CHANNEL_SHIFT(i) ((i) * 8) +#endif + typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int); static void BlendPixelRowNonPremult(uint32_t* const src, const uint32_t* const dst, int num_pixels); @@ -209,35 +217,35 @@ static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a, const uint8_t dst_channel = (dst >> shift) & 0xff; const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a; assert(blend_unscaled < (1ULL << 32) / scale); - return (blend_unscaled * scale) >> 24; + return (blend_unscaled * scale) >> CHANNEL_SHIFT(3); } // Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha. static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) { - const uint8_t src_a = (src >> 24) & 0xff; + const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff; if (src_a == 0) { return dst; } else { - const uint8_t dst_a = (dst >> 24) & 0xff; + const uint8_t dst_a = (dst >> CHANNEL_SHIFT(3)) & 0xff; // This is the approximate integer arithmetic for the actual formula: // dst_factor_a = (dst_a * (255 - src_a)) / 255. const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8; const uint8_t blend_a = src_a + dst_factor_a; const uint32_t scale = (1UL << 24) / blend_a; - const uint8_t blend_r = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 0); - const uint8_t blend_g = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 8); - const uint8_t blend_b = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 16); + const uint8_t blend_r = BlendChannelNonPremult( + src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(0)); + const uint8_t blend_g = BlendChannelNonPremult( + src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(1)); + const uint8_t blend_b = BlendChannelNonPremult( + src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(2)); assert(src_a + dst_factor_a < 256); - return (blend_r << 0) | - (blend_g << 8) | - (blend_b << 16) | - ((uint32_t)blend_a << 24); + return ((uint32_t)blend_r << CHANNEL_SHIFT(0)) | + ((uint32_t)blend_g << CHANNEL_SHIFT(1)) | + ((uint32_t)blend_b << CHANNEL_SHIFT(2)) | + ((uint32_t)blend_a << CHANNEL_SHIFT(3)); } } @@ -247,7 +255,7 @@ static void BlendPixelRowNonPremult(uint32_t* const src, const uint32_t* const dst, int num_pixels) { int i; for (i = 0; i < num_pixels; ++i) { - const uint8_t src_alpha = (src[i] >> 24) & 0xff; + const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff; if (src_alpha != 0xff) { src[i] = BlendPixelNonPremult(src[i], dst[i]); } @@ -264,7 +272,7 @@ static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) { // Blend 'src' over 'dst' assuming they are pre-multiplied by alpha. static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) { - const uint8_t src_a = (src >> 24) & 0xff; + const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff; return src + ChannelwiseMultiply(dst, 256 - src_a); } @@ -274,7 +282,7 @@ static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, int num_pixels) { int i; for (i = 0; i < num_pixels; ++i) { - const uint8_t src_alpha = (src[i] >> 24) & 0xff; + const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff; if (src_alpha != 0xff) { src[i] = BlendPixelPremult(src[i], dst[i]); } diff --git a/thirdparty/libwebp/src/demux/demux.c b/thirdparty/libwebp/src/demux/demux.c index 547a7725de..f04a2b8450 100644 --- a/thirdparty/libwebp/src/demux/demux.c +++ b/thirdparty/libwebp/src/demux/demux.c @@ -25,7 +25,7 @@ #define DMUX_MAJ_VERSION 1 #define DMUX_MIN_VERSION 2 -#define DMUX_REV_VERSION 1 +#define DMUX_REV_VERSION 2 typedef struct { size_t start_; // start location of the data diff --git a/thirdparty/libwebp/src/dsp/dsp.h b/thirdparty/libwebp/src/dsp/dsp.h index 513e159bb3..c4f57e4d5b 100644 --- a/thirdparty/libwebp/src/dsp/dsp.h +++ b/thirdparty/libwebp/src/dsp/dsp.h @@ -119,7 +119,12 @@ extern "C" { #define WEBP_USE_NEON #endif -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) +// Note: ARM64 is supported in Visual Studio 2017, but requires the direct +// inclusion of arm64_neon.h; Visual Studio 2019 includes this file in +// arm_neon.h. +#if defined(_MSC_VER) && \ + ((_MSC_VER >= 1700 && defined(_M_ARM)) || \ + (_MSC_VER >= 1920 && defined(_M_ARM64))) #define WEBP_USE_NEON #define WEBP_USE_INTRINSICS #endif diff --git a/thirdparty/libwebp/src/dsp/enc_neon.c b/thirdparty/libwebp/src/dsp/enc_neon.c index 43bf1245c5..601962ba76 100644 --- a/thirdparty/libwebp/src/dsp/enc_neon.c +++ b/thirdparty/libwebp/src/dsp/enc_neon.c @@ -9,7 +9,7 @@ // // ARM NEON version of speed-critical encoding functions. // -// adapted from libvpx (http://www.webmproject.org/code/) +// adapted from libvpx (https://www.webmproject.org/code/) #include "src/dsp/dsp.h" diff --git a/thirdparty/libwebp/src/dsp/lossless.c b/thirdparty/libwebp/src/dsp/lossless.c index d8bbb02b35..84a54296fd 100644 --- a/thirdparty/libwebp/src/dsp/lossless.c +++ b/thirdparty/libwebp/src/dsp/lossless.c @@ -107,63 +107,77 @@ static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { //------------------------------------------------------------------------------ // Predictors -uint32_t VP8LPredictor0_C(uint32_t left, const uint32_t* const top) { +uint32_t VP8LPredictor0_C(const uint32_t* const left, + const uint32_t* const top) { (void)top; (void)left; return ARGB_BLACK; } -uint32_t VP8LPredictor1_C(uint32_t left, const uint32_t* const top) { +uint32_t VP8LPredictor1_C(const uint32_t* const left, + const uint32_t* const top) { (void)top; - return left; + return *left; } -uint32_t VP8LPredictor2_C(uint32_t left, const uint32_t* const top) { +uint32_t VP8LPredictor2_C(const uint32_t* const left, + const uint32_t* const top) { (void)left; return top[0]; } -uint32_t VP8LPredictor3_C(uint32_t left, const uint32_t* const top) { +uint32_t VP8LPredictor3_C(const uint32_t* const left, + const uint32_t* const top) { (void)left; return top[1]; } -uint32_t VP8LPredictor4_C(uint32_t left, const uint32_t* const top) { +uint32_t VP8LPredictor4_C(const uint32_t* const left, + const uint32_t* const top) { (void)left; return top[-1]; } -uint32_t VP8LPredictor5_C(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average3(left, top[0], top[1]); +uint32_t VP8LPredictor5_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average3(*left, top[0], top[1]); return pred; } -uint32_t VP8LPredictor6_C(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[-1]); +uint32_t VP8LPredictor6_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(*left, top[-1]); return pred; } -uint32_t VP8LPredictor7_C(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[0]); +uint32_t VP8LPredictor7_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(*left, top[0]); return pred; } -uint32_t VP8LPredictor8_C(uint32_t left, const uint32_t* const top) { +uint32_t VP8LPredictor8_C(const uint32_t* const left, + const uint32_t* const top) { const uint32_t pred = Average2(top[-1], top[0]); (void)left; return pred; } -uint32_t VP8LPredictor9_C(uint32_t left, const uint32_t* const top) { +uint32_t VP8LPredictor9_C(const uint32_t* const left, + const uint32_t* const top) { const uint32_t pred = Average2(top[0], top[1]); (void)left; return pred; } -uint32_t VP8LPredictor10_C(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average4(left, top[-1], top[0], top[1]); +uint32_t VP8LPredictor10_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average4(*left, top[-1], top[0], top[1]); return pred; } -uint32_t VP8LPredictor11_C(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Select(top[0], left, top[-1]); +uint32_t VP8LPredictor11_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Select(top[0], *left, top[-1]); return pred; } -uint32_t VP8LPredictor12_C(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); +uint32_t VP8LPredictor12_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractFull(*left, top[0], top[-1]); return pred; } -uint32_t VP8LPredictor13_C(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); +uint32_t VP8LPredictor13_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractHalf(*left, top[0], top[-1]); return pred; } diff --git a/thirdparty/libwebp/src/dsp/lossless.h b/thirdparty/libwebp/src/dsp/lossless.h index ebd316d1ed..c26c6bca07 100644 --- a/thirdparty/libwebp/src/dsp/lossless.h +++ b/thirdparty/libwebp/src/dsp/lossless.h @@ -28,23 +28,38 @@ extern "C" { //------------------------------------------------------------------------------ // Decoding -typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top); +typedef uint32_t (*VP8LPredictorFunc)(const uint32_t* const left, + const uint32_t* const top); extern VP8LPredictorFunc VP8LPredictors[16]; -uint32_t VP8LPredictor0_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor1_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor2_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor3_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor4_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor5_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor6_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor7_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor8_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor9_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor10_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor11_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor12_C(uint32_t left, const uint32_t* const top); -uint32_t VP8LPredictor13_C(uint32_t left, const uint32_t* const top); +uint32_t VP8LPredictor0_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor1_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor2_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor3_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor4_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor5_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor6_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor7_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor8_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor9_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor10_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor11_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor12_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor13_C(const uint32_t* const left, + const uint32_t* const top); // These Add/Sub function expects upper[-1] and out[-1] to be readable. typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* in, diff --git a/thirdparty/libwebp/src/dsp/lossless_common.h b/thirdparty/libwebp/src/dsp/lossless_common.h index 96a106f9ee..6a2f736b5e 100644 --- a/thirdparty/libwebp/src/dsp/lossless_common.h +++ b/thirdparty/libwebp/src/dsp/lossless_common.h @@ -179,7 +179,7 @@ static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \ int x; \ assert(upper != NULL); \ for (x = 0; x < num_pixels; ++x) { \ - const uint32_t pred = (PREDICTOR)(out[x - 1], upper + x); \ + const uint32_t pred = (PREDICTOR)(&out[x - 1], upper + x); \ out[x] = VP8LAddPixels(in[x], pred); \ } \ } diff --git a/thirdparty/libwebp/src/dsp/lossless_enc.c b/thirdparty/libwebp/src/dsp/lossless_enc.c index c3e8537ade..1580631e38 100644 --- a/thirdparty/libwebp/src/dsp/lossless_enc.c +++ b/thirdparty/libwebp/src/dsp/lossless_enc.c @@ -745,7 +745,7 @@ static void PredictorSub##PREDICTOR_I##_C(const uint32_t* in, \ assert(upper != NULL); \ for (x = 0; x < num_pixels; ++x) { \ const uint32_t pred = \ - VP8LPredictor##PREDICTOR_I##_C(in[x - 1], upper + x); \ + VP8LPredictor##PREDICTOR_I##_C(&in[x - 1], upper + x); \ out[x] = VP8LSubPixels(in[x], pred); \ } \ } diff --git a/thirdparty/libwebp/src/dsp/lossless_mips_dsp_r2.c b/thirdparty/libwebp/src/dsp/lossless_mips_dsp_r2.c index 9888854d57..bfe5ea6b38 100644 --- a/thirdparty/libwebp/src/dsp/lossless_mips_dsp_r2.c +++ b/thirdparty/libwebp/src/dsp/lossless_mips_dsp_r2.c @@ -188,46 +188,51 @@ static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, return Average2(Average2(a0, a1), Average2(a2, a3)); } -static uint32_t Predictor5_MIPSdspR2(uint32_t left, const uint32_t* const top) { - return Average3(left, top[0], top[1]); +static uint32_t Predictor5_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average3(*left, top[0], top[1]); } -static uint32_t Predictor6_MIPSdspR2(uint32_t left, const uint32_t* const top) { - return Average2(left, top[-1]); +static uint32_t Predictor6_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average2(*left, top[-1]); } -static uint32_t Predictor7_MIPSdspR2(uint32_t left, const uint32_t* const top) { - return Average2(left, top[0]); +static uint32_t Predictor7_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average2(*left, top[0]); } -static uint32_t Predictor8_MIPSdspR2(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor8_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { (void)left; return Average2(top[-1], top[0]); } -static uint32_t Predictor9_MIPSdspR2(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor9_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { (void)left; return Average2(top[0], top[1]); } -static uint32_t Predictor10_MIPSdspR2(uint32_t left, +static uint32_t Predictor10_MIPSdspR2(const uint32_t* const left, const uint32_t* const top) { - return Average4(left, top[-1], top[0], top[1]); + return Average4(*left, top[-1], top[0], top[1]); } -static uint32_t Predictor11_MIPSdspR2(uint32_t left, +static uint32_t Predictor11_MIPSdspR2(const uint32_t* const left, const uint32_t* const top) { - return Select(top[0], left, top[-1]); + return Select(top[0], *left, top[-1]); } -static uint32_t Predictor12_MIPSdspR2(uint32_t left, +static uint32_t Predictor12_MIPSdspR2(const uint32_t* const left, const uint32_t* const top) { - return ClampedAddSubtractFull(left, top[0], top[-1]); + return ClampedAddSubtractFull(*left, top[0], top[-1]); } -static uint32_t Predictor13_MIPSdspR2(uint32_t left, +static uint32_t Predictor13_MIPSdspR2(const uint32_t* const left, const uint32_t* const top) { - return ClampedAddSubtractHalf(left, top[0], top[-1]); + return ClampedAddSubtractHalf(*left, top[0], top[-1]); } // Add green to blue and red channels (i.e. perform the inverse transform of diff --git a/thirdparty/libwebp/src/dsp/lossless_neon.c b/thirdparty/libwebp/src/dsp/lossless_neon.c index 76a1b6f873..89e3e013a0 100644 --- a/thirdparty/libwebp/src/dsp/lossless_neon.c +++ b/thirdparty/libwebp/src/dsp/lossless_neon.c @@ -188,17 +188,21 @@ static WEBP_INLINE uint32_t Average3_NEON(uint32_t a0, uint32_t a1, return avg; } -static uint32_t Predictor5_NEON(uint32_t left, const uint32_t* const top) { - return Average3_NEON(left, top[0], top[1]); +static uint32_t Predictor5_NEON(const uint32_t* const left, + const uint32_t* const top) { + return Average3_NEON(*left, top[0], top[1]); } -static uint32_t Predictor6_NEON(uint32_t left, const uint32_t* const top) { - return Average2_NEON(left, top[-1]); +static uint32_t Predictor6_NEON(const uint32_t* const left, + const uint32_t* const top) { + return Average2_NEON(*left, top[-1]); } -static uint32_t Predictor7_NEON(uint32_t left, const uint32_t* const top) { - return Average2_NEON(left, top[0]); +static uint32_t Predictor7_NEON(const uint32_t* const left, + const uint32_t* const top) { + return Average2_NEON(*left, top[0]); } -static uint32_t Predictor13_NEON(uint32_t left, const uint32_t* const top) { - return ClampedAddSubtractHalf_NEON(left, top[0], top[-1]); +static uint32_t Predictor13_NEON(const uint32_t* const left, + const uint32_t* const top) { + return ClampedAddSubtractHalf_NEON(*left, top[0], top[-1]); } // Batch versions of those functions. diff --git a/thirdparty/libwebp/src/dsp/lossless_sse2.c b/thirdparty/libwebp/src/dsp/lossless_sse2.c index 3a0eb440db..396cb0bdfc 100644 --- a/thirdparty/libwebp/src/dsp/lossless_sse2.c +++ b/thirdparty/libwebp/src/dsp/lossless_sse2.c @@ -138,42 +138,51 @@ static WEBP_INLINE uint32_t Average4_SSE2(uint32_t a0, uint32_t a1, return output; } -static uint32_t Predictor5_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average3_SSE2(left, top[0], top[1]); +static uint32_t Predictor5_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average3_SSE2(*left, top[0], top[1]); return pred; } -static uint32_t Predictor6_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2_SSE2(left, top[-1]); +static uint32_t Predictor6_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(*left, top[-1]); return pred; } -static uint32_t Predictor7_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2_SSE2(left, top[0]); +static uint32_t Predictor7_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(*left, top[0]); return pred; } -static uint32_t Predictor8_SSE2(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor8_SSE2(const uint32_t* const left, + const uint32_t* const top) { const uint32_t pred = Average2_SSE2(top[-1], top[0]); (void)left; return pred; } -static uint32_t Predictor9_SSE2(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor9_SSE2(const uint32_t* const left, + const uint32_t* const top) { const uint32_t pred = Average2_SSE2(top[0], top[1]); (void)left; return pred; } -static uint32_t Predictor10_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average4_SSE2(left, top[-1], top[0], top[1]); +static uint32_t Predictor10_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average4_SSE2(*left, top[-1], top[0], top[1]); return pred; } -static uint32_t Predictor11_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Select_SSE2(top[0], left, top[-1]); +static uint32_t Predictor11_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Select_SSE2(top[0], *left, top[-1]); return pred; } -static uint32_t Predictor12_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractFull_SSE2(left, top[0], top[-1]); +static uint32_t Predictor12_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractFull_SSE2(*left, top[0], top[-1]); return pred; } -static uint32_t Predictor13_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractHalf_SSE2(left, top[0], top[-1]); +static uint32_t Predictor13_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractHalf_SSE2(*left, top[0], top[-1]); return pred; } diff --git a/thirdparty/libwebp/src/dsp/msa_macro.h b/thirdparty/libwebp/src/dsp/msa_macro.h index de026a1d9e..51f6c643ab 100644 --- a/thirdparty/libwebp/src/dsp/msa_macro.h +++ b/thirdparty/libwebp/src/dsp/msa_macro.h @@ -14,6 +14,10 @@ #ifndef WEBP_DSP_MSA_MACRO_H_ #define WEBP_DSP_MSA_MACRO_H_ +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + #include <stdint.h> #include <msa.h> @@ -1389,4 +1393,5 @@ static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) { } while (0) #define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__) +#endif // WEBP_USE_MSA #endif // WEBP_DSP_MSA_MACRO_H_ diff --git a/thirdparty/libwebp/src/dsp/neon.h b/thirdparty/libwebp/src/dsp/neon.h index aa1dea1301..c591f9b9a7 100644 --- a/thirdparty/libwebp/src/dsp/neon.h +++ b/thirdparty/libwebp/src/dsp/neon.h @@ -12,10 +12,12 @@ #ifndef WEBP_DSP_NEON_H_ #define WEBP_DSP_NEON_H_ -#include <arm_neon.h> - #include "src/dsp/dsp.h" +#if defined(WEBP_USE_NEON) + +#include <arm_neon.h> + // Right now, some intrinsics functions seem slower, so we disable them // everywhere except newer clang/gcc or aarch64 where the inline assembly is // incompatible. @@ -98,4 +100,5 @@ static WEBP_INLINE int32x4x4_t Transpose4x4_NEON(const int32x4x4_t rows) { } while (0) #endif +#endif // WEBP_USE_NEON #endif // WEBP_DSP_NEON_H_ diff --git a/thirdparty/libwebp/src/dsp/yuv.h b/thirdparty/libwebp/src/dsp/yuv.h index c12be1d094..66a397d117 100644 --- a/thirdparty/libwebp/src/dsp/yuv.h +++ b/thirdparty/libwebp/src/dsp/yuv.h @@ -10,7 +10,7 @@ // inline YUV<->RGB conversion function // // The exact naming is Y'CbCr, following the ITU-R BT.601 standard. -// More information at: http://en.wikipedia.org/wiki/YCbCr +// More information at: https://en.wikipedia.org/wiki/YCbCr // Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 // U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 // V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 diff --git a/thirdparty/libwebp/src/enc/frame_enc.c b/thirdparty/libwebp/src/enc/frame_enc.c index af538d83ba..b93d9e5b99 100644 --- a/thirdparty/libwebp/src/enc/frame_enc.c +++ b/thirdparty/libwebp/src/enc/frame_enc.c @@ -778,6 +778,7 @@ int VP8EncTokenLoop(VP8Encoder* const enc) { // Roughly refresh the proba eight times per pass int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; int num_pass_left = enc->config_->pass; + int remaining_progress = 40; // percents const int do_search = enc->do_search_; VP8EncIterator it; VP8EncProba* const proba = &enc->proba_; @@ -805,6 +806,9 @@ int VP8EncTokenLoop(VP8Encoder* const enc) { uint64_t size_p0 = 0; uint64_t distortion = 0; int cnt = max_count; + // The final number of passes is not trivial to know in advance. + const int pass_progress = remaining_progress / (2 + num_pass_left); + remaining_progress -= pass_progress; VP8IteratorInit(enc, &it); SetLoopParams(enc, stats.q); if (is_last_pass) { @@ -832,7 +836,7 @@ int VP8EncTokenLoop(VP8Encoder* const enc) { StoreSideInfo(&it); VP8StoreFilterStats(&it); VP8IteratorExport(&it); - ok = VP8IteratorProgress(&it, 20); + ok = VP8IteratorProgress(&it, pass_progress); } VP8IteratorSaveBoundary(&it); } while (ok && VP8IteratorNext(&it)); @@ -878,7 +882,8 @@ int VP8EncTokenLoop(VP8Encoder* const enc) { ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, (const uint8_t*)proba->coeffs_, 1); } - ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); + ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + remaining_progress, + &enc->percent_); return PostLoopFinalize(&it, ok); } diff --git a/thirdparty/libwebp/src/enc/predictor_enc.c b/thirdparty/libwebp/src/enc/predictor_enc.c index 2e6762ea0d..2b5c767280 100644 --- a/thirdparty/libwebp/src/enc/predictor_enc.c +++ b/thirdparty/libwebp/src/enc/predictor_enc.c @@ -249,7 +249,7 @@ static WEBP_INLINE void GetResidual( } else if (x == 0) { predict = upper_row[x]; // Top. } else { - predict = pred_func(current_row[x - 1], upper_row + x); + predict = pred_func(¤t_row[x - 1], upper_row + x); } #if (WEBP_NEAR_LOSSLESS == 1) if (max_quantization == 1 || mode == 0 || y == 0 || y == height - 1 || diff --git a/thirdparty/libwebp/src/enc/quant_enc.c b/thirdparty/libwebp/src/enc/quant_enc.c index 01eb565c7f..6cede28ab4 100644 --- a/thirdparty/libwebp/src/enc/quant_enc.c +++ b/thirdparty/libwebp/src/enc/quant_enc.c @@ -585,6 +585,9 @@ static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate, return rate * lambda + RD_DISTO_MULT * distortion; } +// Coefficient type. +enum { TYPE_I16_AC = 0, TYPE_I16_DC = 1, TYPE_CHROMA_A = 2, TYPE_I4_AC = 3 }; + static int TrellisQuantizeBlock(const VP8Encoder* const enc, int16_t in[16], int16_t out[16], int ctx0, int coeff_type, @@ -593,7 +596,7 @@ static int TrellisQuantizeBlock(const VP8Encoder* const enc, const ProbaArray* const probas = enc->proba_.coeffs_[coeff_type]; CostArrayPtr const costs = (CostArrayPtr)enc->proba_.remapped_costs_[coeff_type]; - const int first = (coeff_type == 0) ? 1 : 0; + const int first = (coeff_type == TYPE_I16_AC) ? 1 : 0; Node nodes[16][NUM_NODES]; ScoreState score_states[2][NUM_NODES]; ScoreState* ss_cur = &SCORE_STATE(0, MIN_DELTA); @@ -657,16 +660,17 @@ static int TrellisQuantizeBlock(const VP8Encoder* const enc, // test all alternate level values around level0. for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { Node* const cur = &NODE(n, m); - int level = level0 + m; + const int level = level0 + m; const int ctx = (level > 2) ? 2 : level; const int band = VP8EncBands[n + 1]; score_t base_score; - score_t best_cur_score = MAX_COST; - int best_prev = 0; // default, in case + score_t best_cur_score; + int best_prev; + score_t cost, score; - ss_cur[m].score = MAX_COST; ss_cur[m].costs = costs[n + 1][ctx]; if (level < 0 || level > thresh_level) { + ss_cur[m].score = MAX_COST; // Node is dead. continue; } @@ -682,18 +686,24 @@ static int TrellisQuantizeBlock(const VP8Encoder* const enc, } // Inspect all possible non-dead predecessors. Retain only the best one. - for (p = -MIN_DELTA; p <= MAX_DELTA; ++p) { + // The base_score is added to all scores so it is only added for the final + // value after the loop. + cost = VP8LevelCost(ss_prev[-MIN_DELTA].costs, level); + best_cur_score = + ss_prev[-MIN_DELTA].score + RDScoreTrellis(lambda, cost, 0); + best_prev = -MIN_DELTA; + for (p = -MIN_DELTA + 1; p <= MAX_DELTA; ++p) { // Dead nodes (with ss_prev[p].score >= MAX_COST) are automatically // eliminated since their score can't be better than the current best. - const score_t cost = VP8LevelCost(ss_prev[p].costs, level); + cost = VP8LevelCost(ss_prev[p].costs, level); // Examine node assuming it's a non-terminal one. - const score_t score = - base_score + ss_prev[p].score + RDScoreTrellis(lambda, cost, 0); + score = ss_prev[p].score + RDScoreTrellis(lambda, cost, 0); if (score < best_cur_score) { best_cur_score = score; best_prev = p; } } + best_cur_score += base_score; // Store best finding in current node. cur->sign = sign; cur->level = level; @@ -701,11 +711,11 @@ static int TrellisQuantizeBlock(const VP8Encoder* const enc, ss_cur[m].score = best_cur_score; // Now, record best terminal node (and thus best entry in the graph). - if (level != 0) { + if (level != 0 && best_cur_score < best_score) { const score_t last_pos_cost = (n < 15) ? VP8BitCost(0, probas[band][ctx][0]) : 0; const score_t last_pos_score = RDScoreTrellis(lambda, last_pos_cost, 0); - const score_t score = best_cur_score + last_pos_score; + score = best_cur_score + last_pos_score; if (score < best_score) { best_score = score; best_path[0] = n; // best eob position @@ -717,10 +727,16 @@ static int TrellisQuantizeBlock(const VP8Encoder* const enc, } // Fresh start - memset(in + first, 0, (16 - first) * sizeof(*in)); - memset(out + first, 0, (16 - first) * sizeof(*out)); + // Beware! We must preserve in[0]/out[0] value for TYPE_I16_AC case. + if (coeff_type == TYPE_I16_AC) { + memset(in + 1, 0, 15 * sizeof(*in)); + memset(out + 1, 0, 15 * sizeof(*out)); + } else { + memset(in, 0, 16 * sizeof(*in)); + memset(out, 0, 16 * sizeof(*out)); + } if (best_path[0] == -1) { - return 0; // skip! + return 0; // skip! } { @@ -775,9 +791,9 @@ static int ReconstructIntra16(VP8EncIterator* const it, for (y = 0, n = 0; y < 4; ++y) { for (x = 0; x < 4; ++x, ++n) { const int ctx = it->top_nz_[x] + it->left_nz_[y]; - const int non_zero = - TrellisQuantizeBlock(enc, tmp[n], rd->y_ac_levels[n], ctx, 0, - &dqm->y1_, dqm->lambda_trellis_i16_); + const int non_zero = TrellisQuantizeBlock( + enc, tmp[n], rd->y_ac_levels[n], ctx, TYPE_I16_AC, &dqm->y1_, + dqm->lambda_trellis_i16_); it->top_nz_[x] = it->left_nz_[y] = non_zero; rd->y_ac_levels[n][0] = 0; nz |= non_zero << n; @@ -818,7 +834,7 @@ static int ReconstructIntra4(VP8EncIterator* const it, if (DO_TRELLIS_I4 && it->do_trellis_) { const int x = it->i4_ & 3, y = it->i4_ >> 2; const int ctx = it->top_nz_[x] + it->left_nz_[y]; - nz = TrellisQuantizeBlock(enc, tmp, levels, ctx, 3, &dqm->y1_, + nz = TrellisQuantizeBlock(enc, tmp, levels, ctx, TYPE_I4_AC, &dqm->y1_, dqm->lambda_trellis_i4_); } else { nz = VP8EncQuantizeBlock(tmp, levels, &dqm->y1_); @@ -927,9 +943,9 @@ static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd, for (y = 0; y < 2; ++y) { for (x = 0; x < 2; ++x, ++n) { const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - const int non_zero = - TrellisQuantizeBlock(enc, tmp[n], rd->uv_levels[n], ctx, 2, - &dqm->uv_, dqm->lambda_trellis_uv_); + const int non_zero = TrellisQuantizeBlock( + enc, tmp[n], rd->uv_levels[n], ctx, TYPE_CHROMA_A, &dqm->uv_, + dqm->lambda_trellis_uv_); it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = non_zero; nz |= non_zero << n; } diff --git a/thirdparty/libwebp/src/enc/vp8i_enc.h b/thirdparty/libwebp/src/enc/vp8i_enc.h index 67e9509367..b4bba08f27 100644 --- a/thirdparty/libwebp/src/enc/vp8i_enc.h +++ b/thirdparty/libwebp/src/enc/vp8i_enc.h @@ -32,7 +32,7 @@ extern "C" { // version numbers #define ENC_MAJ_VERSION 1 #define ENC_MIN_VERSION 2 -#define ENC_REV_VERSION 1 +#define ENC_REV_VERSION 2 enum { MAX_LF_LEVELS = 64, // Maximum loop filter level MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost diff --git a/thirdparty/libwebp/src/mux/muxi.h b/thirdparty/libwebp/src/mux/muxi.h index 330da66754..d9bf9b3770 100644 --- a/thirdparty/libwebp/src/mux/muxi.h +++ b/thirdparty/libwebp/src/mux/muxi.h @@ -29,7 +29,7 @@ extern "C" { #define MUX_MAJ_VERSION 1 #define MUX_MIN_VERSION 2 -#define MUX_REV_VERSION 1 +#define MUX_REV_VERSION 2 // Chunk object. typedef struct WebPChunk WebPChunk; diff --git a/thirdparty/libwebp/src/utils/huffman_encode_utils.c b/thirdparty/libwebp/src/utils/huffman_encode_utils.c index fd7a47d8f7..585db91951 100644 --- a/thirdparty/libwebp/src/utils/huffman_encode_utils.c +++ b/thirdparty/libwebp/src/utils/huffman_encode_utils.c @@ -161,7 +161,7 @@ static void SetBitDepths(const HuffmanTree* const tree, // especially when population counts are longer than 2**tree_limit, but // we are not planning to use this with extremely long blocks. // -// See http://en.wikipedia.org/wiki/Huffman_coding +// See https://en.wikipedia.org/wiki/Huffman_coding static void GenerateOptimalTree(const uint32_t* const histogram, int histogram_size, HuffmanTree* tree, int tree_depth_limit, diff --git a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c index f65b6cdbb6..97e7893704 100644 --- a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c +++ b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c @@ -30,7 +30,7 @@ #define DFIX 4 // extra precision for ordered dithering #define DSIZE 4 // dithering size (must be a power of two) -// cf. http://en.wikipedia.org/wiki/Ordered_dithering +// cf. https://en.wikipedia.org/wiki/Ordered_dithering static const uint8_t kOrderedDither[DSIZE][DSIZE] = { { 0, 8, 2, 10 }, // coefficients are in DFIX fixed-point precision { 12, 4, 14, 6 }, diff --git a/thirdparty/libwebp/src/utils/utils.c b/thirdparty/libwebp/src/utils/utils.c index 9e464c16ce..a7c3a70fef 100644 --- a/thirdparty/libwebp/src/utils/utils.c +++ b/thirdparty/libwebp/src/utils/utils.c @@ -23,7 +23,7 @@ // alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, // and not multi-thread safe!). // An interesting alternative is valgrind's 'massif' tool: -// http://valgrind.org/docs/manual/ms-manual.html +// https://valgrind.org/docs/manual/ms-manual.html // Here is an example command line: /* valgrind --tool=massif --massif-out-file=massif.out \ --stacks=yes --alloc-fn=WebPSafeMalloc --alloc-fn=WebPSafeCalloc diff --git a/thirdparty/libwebp/src/webp/decode.h b/thirdparty/libwebp/src/webp/decode.h index 44fcd64a84..d98247509a 100644 --- a/thirdparty/libwebp/src/webp/decode.h +++ b/thirdparty/libwebp/src/webp/decode.h @@ -85,7 +85,7 @@ WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, // Upon return, the Y buffer has a stride returned as '*stride', while U and V // have a common stride returned as '*uv_stride'. // Return NULL in case of error. -// (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr +// (*) Also named Y'CbCr. See: https://en.wikipedia.org/wiki/YCbCr WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, int* width, int* height, uint8_t** u, uint8_t** v, |