diff options
206 files changed, 3282 insertions, 1247 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 892b74c26a..8308c4fe53 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -483,6 +483,10 @@ void OS::dump_resources_to_file(const String &p_file) { ::OS::get_singleton()->dump_resources_to_file(p_file.utf8().get_data()); } +Error OS::move_to_trash(const String &p_path) const { + return ::OS::get_singleton()->move_to_trash(p_path); +} + String OS::get_user_data_dir() const { return ::OS::get_singleton()->get_user_data_dir(); } @@ -597,6 +601,7 @@ void OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_static_memory_usage"), &OS::get_static_memory_usage); ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &OS::get_static_memory_peak_usage); + ClassDB::bind_method(D_METHOD("move_to_trash", "path"), &OS::move_to_trash); ClassDB::bind_method(D_METHOD("get_user_data_dir"), &OS::get_user_data_dir); ClassDB::bind_method(D_METHOD("get_system_dir", "dir", "shared_storage"), &OS::get_system_dir, DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_config_dir"), &OS::get_config_dir); diff --git a/core/core_bind.h b/core/core_bind.h index 591cacdabb..bc68be3f62 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -235,6 +235,7 @@ public: String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const; + Error move_to_trash(const String &p_path) const; String get_user_data_dir() const; String get_config_dir() const; String get_data_dir() const; diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 425261aa6c..c3506a7eea 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -169,7 +169,7 @@ public: EngineDebugger::get_singleton()->send_message("performance:profile_frame", arr); } - PerformanceProfiler(Object *p_performance) { + explicit PerformanceProfiler(Object *p_performance) { performance = p_performance; } }; diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h index aada92da60..fdb312ae68 100644 --- a/core/debugger/remote_debugger.h +++ b/core/debugger/remote_debugger.h @@ -108,7 +108,7 @@ public: void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type); void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false); - RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer); + explicit RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer); ~RemoteDebugger(); }; diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp index 950500884e..e9362b4ea4 100644 --- a/core/debugger/remote_debugger_peer.cpp +++ b/core/debugger/remote_debugger_peer.cpp @@ -93,7 +93,7 @@ RemoteDebuggerPeerTCP::~RemoteDebuggerPeerTCP() { } void RemoteDebuggerPeerTCP::_write_out() { - while (tcp_client->poll(NetSocket::POLL_TYPE_OUT) == OK) { + while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED && tcp_client->wait(NetSocket::POLL_TYPE_OUT) == OK) { uint8_t *buf = out_buf.ptrw(); if (out_left <= 0) { if (out_queue.size() == 0) { @@ -119,7 +119,7 @@ void RemoteDebuggerPeerTCP::_write_out() { } void RemoteDebuggerPeerTCP::_read_in() { - while (tcp_client->poll(NetSocket::POLL_TYPE_IN) == OK) { + while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED && tcp_client->wait(NetSocket::POLL_TYPE_IN) == OK) { uint8_t *buf = in_buf.ptrw(); if (in_left <= 0) { if (in_queue.size() > max_queued_messages) { @@ -167,6 +167,7 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po tcp_client->connect_to_host(ip, port); for (int i = 0; i < tries; i++) { + tcp_client->poll(); if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) { print_verbose("Remote Debugger: Connected!"); break; @@ -213,6 +214,7 @@ void RemoteDebuggerPeerTCP::poll() { } void RemoteDebuggerPeerTCP::_poll() { + tcp_client->poll(); if (connected) { _write_out(); _read_in(); diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp index 34a11758f8..076d04a5eb 100644 --- a/core/extension/native_extension.cpp +++ b/core/extension/native_extension.cpp @@ -49,10 +49,10 @@ class NativeExtensionMethodBind : public MethodBind { bool vararg; protected: - virtual Variant::Type _gen_argument_type(int p_arg) const { + virtual Variant::Type _gen_argument_type(int p_arg) const override { return Variant::Type(get_argument_type_func(method_userdata, p_arg)); } - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { GDNativePropertyInfo pinfo; get_argument_info_func(method_userdata, p_arg, &pinfo); PropertyInfo ret; @@ -66,11 +66,13 @@ protected: } public: - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { return GodotTypeInfo::Metadata(get_argument_metadata_func(method_userdata, p_arg)); } +#endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { Variant ret; GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance(); GDNativeCallError ce{ GDNATIVE_CALL_OK, 0, 0 }; @@ -80,16 +82,16 @@ public: r_error.expected = ce.expected; return ret; } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug."); GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance(); ptrcall_func(method_userdata, extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret); } - virtual bool is_vararg() const { + virtual bool is_vararg() const override { return false; } - NativeExtensionMethodBind(const GDNativeExtensionClassMethodInfo *p_method_info) { + explicit NativeExtensionMethodBind(const GDNativeExtensionClassMethodInfo *p_method_info) { method_userdata = p_method_info->method_userdata; call_func = p_method_info->call_func; ptrcall_func = p_method_info->ptrcall_func; diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index c6e14ffee7..ba120de68b 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -32,6 +32,7 @@ #include "core/io/file_access_encrypted.h" #include "core/object/script_language.h" +#include "core/os/os.h" #include "core/version.h" #include <stdio.h> @@ -131,32 +132,69 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, return false; } - f->seek(p_offset); + bool pck_header_found = false; + // Search for the header at the start offset - standalone PCK file. + f->seek(p_offset); uint32_t magic = f->get_32(); + if (magic == PACK_HEADER_MAGIC) { + pck_header_found = true; + } - if (magic != PACK_HEADER_MAGIC) { - // loading with offset feature not supported for self contained exe files - ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Loading self-contained executable with offset not supported."); + // Search for the header in the executable "pck" section - self contained executable. + if (!pck_header_found) { + // Loading with offset feature not supported for self contained exe files. + if (p_offset != 0) { + ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported."); + } - //maybe at the end.... self contained exe - f->seek_end(); - f->seek(f->get_position() - 4); - magic = f->get_32(); - if (magic != PACK_HEADER_MAGIC) { - return false; + int64_t pck_off = OS::get_singleton()->get_embedded_pck_offset(); + if (pck_off != 0) { + // Search for the header, in case PCK start and section have different alignment. + for (int i = 0; i < 8; i++) { + f->seek(pck_off); + magic = f->get_32(); + if (magic == PACK_HEADER_MAGIC) { +#ifdef DEBUG_ENABLED + print_verbose("PCK header found in executable pck section, loading from offset 0x" + String::num_int64(pck_off - 4, 16)); +#endif + pck_header_found = true; + break; + } + pck_off++; + } } - f->seek(f->get_position() - 12); + } - uint64_t ds = f->get_64(); - f->seek(f->get_position() - ds - 8); + // Search for the header at the end of file - self contained executable. + if (!pck_header_found) { + // Loading with offset feature not supported for self contained exe files. + if (p_offset != 0) { + ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported."); + } + f->seek_end(); + f->seek(f->get_position() - 4); magic = f->get_32(); - if (magic != PACK_HEADER_MAGIC) { - return false; + + if (magic == PACK_HEADER_MAGIC) { + f->seek(f->get_position() - 12); + uint64_t ds = f->get_64(); + f->seek(f->get_position() - ds - 8); + magic = f->get_32(); + if (magic == PACK_HEADER_MAGIC) { +#ifdef DEBUG_ENABLED + print_verbose("PCK header found at the end of executable, loading from offset 0x" + String::num_int64(f->get_position() - 4, 16)); +#endif + pck_header_found = true; + } } } + if (!pck_header_found) { + return false; + } + uint32_t version = f->get_32(); uint32_t ver_major = f->get_32(); uint32_t ver_minor = f->get_32(); diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 44df2029bd..17e87c835a 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -93,7 +93,7 @@ private: PathMD5() {} - PathMD5(const Vector<uint8_t> &p_buf) { + explicit PathMD5(const Vector<uint8_t> &p_buf) { a = *((uint64_t *)&p_buf[0]); b = *((uint64_t *)&p_buf[8]); } diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp index f920799677..d983d86b99 100644 --- a/core/io/http_client_tcp.cpp +++ b/core/io/http_client_tcp.cpp @@ -264,6 +264,9 @@ void HTTPClientTCP::close() { } Error HTTPClientTCP::poll() { + if (tcp_connection.is_valid()) { + tcp_connection->poll(); + } switch (status) { case STATUS_RESOLVING: { ERR_FAIL_COND_V(resolving == IP::RESOLVER_INVALID_ID, ERR_BUG); diff --git a/core/io/logger.h b/core/io/logger.h index e3ac00f11c..8ac086e376 100644 --- a/core/io/logger.h +++ b/core/io/logger.h @@ -67,7 +67,7 @@ public: */ class StdLogger : public Logger { public: - virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0; + virtual void logv(const char *p_format, va_list p_list, bool p_err) override _PRINTF_FORMAT_ATTRIBUTE_2_0; virtual ~StdLogger() {} }; @@ -87,19 +87,19 @@ class RotatedFileLogger : public Logger { void rotate_file(); public: - RotatedFileLogger(const String &p_base_path, int p_max_files = 10); + explicit RotatedFileLogger(const String &p_base_path, int p_max_files = 10); - virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0; + virtual void logv(const char *p_format, va_list p_list, bool p_err) override _PRINTF_FORMAT_ATTRIBUTE_2_0; }; class CompositeLogger : public Logger { Vector<Logger *> loggers; public: - CompositeLogger(Vector<Logger *> p_loggers); + explicit CompositeLogger(Vector<Logger *> p_loggers); - virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0; - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR); + virtual void logv(const char *p_format, va_list p_list, bool p_err) override _PRINTF_FORMAT_ATTRIBUTE_2_0; + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR) override; void add_logger(Logger *p_logger); diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index 503eb17cae..84d1f3ebd4 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -242,7 +242,7 @@ Error PacketPeerUDP::connect_to_host(const IPAddress &p_host, int p_port) { return OK; } -bool PacketPeerUDP::is_connected_to_host() const { +bool PacketPeerUDP::is_socket_connected() const { return connected; } @@ -348,7 +348,7 @@ void PacketPeerUDP::_bind_methods() { ClassDB::bind_method(D_METHOD("wait"), &PacketPeerUDP::wait); ClassDB::bind_method(D_METHOD("is_bound"), &PacketPeerUDP::is_bound); ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &PacketPeerUDP::connect_to_host); - ClassDB::bind_method(D_METHOD("is_connected_to_host"), &PacketPeerUDP::is_connected_to_host); + ClassDB::bind_method(D_METHOD("is_socket_connected"), &PacketPeerUDP::is_socket_connected); ClassDB::bind_method(D_METHOD("get_packet_ip"), &PacketPeerUDP::_get_packet_ip); ClassDB::bind_method(D_METHOD("get_packet_port"), &PacketPeerUDP::get_packet_port); ClassDB::bind_method(D_METHOD("get_local_port"), &PacketPeerUDP::get_local_port); diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 444a6dd5ba..a174cf5347 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -79,7 +79,7 @@ public: void disconnect_shared_socket(); // Used by UDPServer Error store_packet(IPAddress p_ip, uint32_t p_port, uint8_t *p_buf, int p_buf_size); // Used internally and by UDPServer Error connect_to_host(const IPAddress &p_host, int p_port); - bool is_connected_to_host() const; + bool is_socket_connected() const; IPAddress get_packet_address() const; int get_packet_port() const; diff --git a/core/io/resource.cpp b/core/io/resource.cpp index bf91438810..96efffd49b 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -257,7 +257,7 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const { List<PropertyInfo> plist; get_property_list(&plist); - Ref<Resource> r = (Resource *)ClassDB::instantiate(get_class()); + Ref<Resource> r = static_cast<Resource *>(ClassDB::instantiate(get_class())); ERR_FAIL_COND_V(r.is_null(), Ref<Resource>()); for (const PropertyInfo &E : plist) { diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 6d5784a8ab..c5c2021e6e 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -32,8 +32,28 @@ #include "core/config/project_settings.h" -Error StreamPeerTCP::_poll_connection() { - ERR_FAIL_COND_V(status != STATUS_CONNECTING || !_sock.is_valid() || !_sock->is_open(), FAILED); +Error StreamPeerTCP::poll() { + if (status == STATUS_CONNECTED) { + Error err; + err = _sock->poll(NetSocket::POLL_TYPE_IN, 0); + if (err == OK) { + // FIN received + if (_sock->get_available_bytes() == 0) { + disconnect_from_host(); + return OK; + } + } + // Also poll write + err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0); + if (err != OK && err != ERR_BUSY) { + // Got an error + disconnect_from_host(); + status = STATUS_ERROR; + return err; + } + } else if (status != STATUS_CONNECTING) { + return OK; + } Error err = _sock->connect_to_host(peer_host, peer_port); @@ -121,22 +141,7 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) { Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) { ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); - if (status == STATUS_NONE || status == STATUS_ERROR) { - return FAILED; - } - if (status != STATUS_CONNECTED) { - if (_poll_connection() != OK) { - return FAILED; - } - - if (status != STATUS_CONNECTED) { - r_sent = 0; - return OK; - } - } - - if (!_sock->is_open()) { return FAILED; } @@ -179,21 +184,10 @@ Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool } Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) { - if (!is_connected_to_host()) { + if (status != STATUS_CONNECTED) { return FAILED; } - if (status == STATUS_CONNECTING) { - if (_poll_connection() != OK) { - return FAILED; - } - - if (status != STATUS_CONNECTED) { - r_received = 0; - return OK; - } - } - Error err; int to_read = p_bytes; int total_read = 0; @@ -243,36 +237,11 @@ Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool } void StreamPeerTCP::set_no_delay(bool p_enabled) { - ERR_FAIL_COND(!is_connected_to_host()); + ERR_FAIL_COND(!_sock.is_valid() || !_sock->is_open()); _sock->set_tcp_no_delay_enabled(p_enabled); } -bool StreamPeerTCP::is_connected_to_host() const { - return _sock.is_valid() && _sock->is_open() && (status == STATUS_CONNECTED || status == STATUS_CONNECTING); -} - -StreamPeerTCP::Status StreamPeerTCP::get_status() { - if (status == STATUS_CONNECTING) { - _poll_connection(); - } else if (status == STATUS_CONNECTED) { - Error err; - err = _sock->poll(NetSocket::POLL_TYPE_IN, 0); - if (err == OK) { - // FIN received - if (_sock->get_available_bytes() == 0) { - disconnect_from_host(); - return status; - } - } - // Also poll write - err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0); - if (err != OK && err != ERR_BUSY) { - // Got an error - disconnect_from_host(); - status = STATUS_ERROR; - } - } - +StreamPeerTCP::Status StreamPeerTCP::get_status() const { return status; } @@ -287,7 +256,7 @@ void StreamPeerTCP::disconnect_from_host() { peer_port = 0; } -Error StreamPeerTCP::poll(NetSocket::PollType p_type, int timeout) { +Error StreamPeerTCP::wait(NetSocket::PollType p_type, int timeout) { ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE); return _sock->poll(p_type, timeout); } @@ -346,7 +315,7 @@ Error StreamPeerTCP::_connect(const String &p_address, int p_port) { void StreamPeerTCP::_bind_methods() { ClassDB::bind_method(D_METHOD("bind", "port", "host"), &StreamPeerTCP::bind, DEFVAL("*")); ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect); - ClassDB::bind_method(D_METHOD("is_connected_to_host"), &StreamPeerTCP::is_connected_to_host); + ClassDB::bind_method(D_METHOD("poll"), &StreamPeerTCP::poll); ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status); ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host); ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port); diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index bf49cc8a5f..39c2e84346 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -55,7 +55,6 @@ protected: uint16_t peer_port = 0; Error _connect(const String &p_address, int p_port); - Error _poll_connection(); Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block); Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block); @@ -66,19 +65,21 @@ public: Error bind(int p_port, const IPAddress &p_host); Error connect_to_host(const IPAddress &p_host, int p_port); - bool is_connected_to_host() const; IPAddress get_connected_host() const; int get_connected_port() const; int get_local_port() const; void disconnect_from_host(); int get_available_bytes() const override; - Status get_status(); + Status get_status() const; void set_no_delay(bool p_enabled); - // Poll functions (wait or check for writable, readable) - Error poll(NetSocket::PollType p_type, int timeout = 0); + // Poll socket updating its state. + Error poll(); + + // Wait or check for writable, readable. + Error wait(NetSocket::PollType p_type, int timeout = 0); // Read/Write from StreamPeer Error put_data(const uint8_t *p_data, int p_bytes) override; diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp index bd292f4c2a..23a0b5dd54 100644 --- a/core/math/convex_hull.cpp +++ b/core/math/convex_hull.cpp @@ -509,7 +509,7 @@ public: Face() { } - void init(Vertex *p_a, Vertex *p_b, Vertex *p_c) { + void init(Vertex *p_a, const Vertex *p_b, const Vertex *p_c) { nearby_vertex = p_a; origin = p_a->point; dir0 = *p_b - *p_a; @@ -614,7 +614,7 @@ private: static Orientation get_orientation(const Edge *p_prev, const Edge *p_next, const Point32 &p_s, const Point32 &p_t); Edge *find_max_angle(bool p_ccw, const Vertex *p_start, const Point32 &p_s, const Point64 &p_rxs, const Point64 &p_ssxrxs, Rational64 &p_min_cot); - void find_edge_for_coplanar_faces(Vertex *p_c0, Vertex *p_c1, Edge *&p_e0, Edge *&p_e1, Vertex *p_stop0, Vertex *p_stop1); + void find_edge_for_coplanar_faces(Vertex *p_c0, Vertex *p_c1, Edge *&p_e0, Edge *&p_e1, const Vertex *p_stop0, const Vertex *p_stop1); Edge *new_edge_pair(Vertex *p_from, Vertex *p_to); @@ -1189,7 +1189,7 @@ ConvexHullInternal::Edge *ConvexHullInternal::find_max_angle(bool p_ccw, const V return min_edge; } -void ConvexHullInternal::find_edge_for_coplanar_faces(Vertex *p_c0, Vertex *p_c1, Edge *&p_e0, Edge *&p_e1, Vertex *p_stop0, Vertex *p_stop1) { +void ConvexHullInternal::find_edge_for_coplanar_faces(Vertex *p_c0, Vertex *p_c1, Edge *&p_e0, Edge *&p_e1, const Vertex *p_stop0, const Vertex *p_stop1) { Edge *start0 = p_e0; Edge *start1 = p_e1; Point32 et0 = start0 ? start0->target->point : p_c0->point; diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp index bd22bffb1f..f76de079e4 100644 --- a/core/math/geometry_3d.cpp +++ b/core/math/geometry_3d.cpp @@ -904,8 +904,8 @@ Vector<Vector3> Geometry3D::compute_convex_mesh_points(const Plane *p_planes, in /* dt of 1d function using squared distance */ static void edt(float *f, int stride, int n) { float *d = (float *)alloca(sizeof(float) * n + sizeof(int) * n + sizeof(float) * (n + 1)); - int *v = (int *)&(d[n]); - float *z = (float *)&v[n]; + int *v = reinterpret_cast<int *>(&(d[n])); + float *z = reinterpret_cast<float *>(&v[n]); int k = 0; v[0] = 0; diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index b741277872..068bc0397e 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -103,6 +103,9 @@ public: static _ALWAYS_INLINE_ double log(double p_x) { return ::log(p_x); } static _ALWAYS_INLINE_ float log(float p_x) { return ::logf(p_x); } + static _ALWAYS_INLINE_ double log1p(double p_x) { return ::log1p(p_x); } + static _ALWAYS_INLINE_ float log1p(float p_x) { return ::log1pf(p_x); } + static _ALWAYS_INLINE_ double log2(double p_x) { return ::log2(p_x); } static _ALWAYS_INLINE_ float log2(float p_x) { return ::log2f(p_x); } diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index fd86a02b90..61ce965bc3 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -37,6 +37,8 @@ #define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock); #define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock); +#ifdef DEBUG_METHODS_ENABLED + MethodDefinition D_METHOD(const char *p_name) { MethodDefinition md; md.name = StaticCString::create(p_name); @@ -224,6 +226,8 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_ return md; } +#endif + ClassDB::APIType ClassDB::current_api = API_CORE; void ClassDB::set_current_api(APIType p_api) { @@ -1420,8 +1424,13 @@ void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method type->method_map[p_method->get_name()] = p_method; } +#ifdef DEBUG_METHODS_ENABLED MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) { StringName mdname = method_name.name; +#else +MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount) { + StringName mdname = StaticCString::create(method_name); +#endif OBJTYPE_WLOCK; ERR_FAIL_COND_V(!p_bind, nullptr); diff --git a/core/object/class_db.h b/core/object/class_db.h index 5da8523743..333a3307e2 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -45,6 +45,8 @@ #define DEFVAL(m_defval) (m_defval) +#ifdef DEBUG_METHODS_ENABLED + struct MethodDefinition { StringName name; Vector<StringName> args; @@ -70,6 +72,14 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12, const char *p_arg13); +#else + +// When DEBUG_METHODS_ENABLED is set this will let the engine know +// the argument names for easier debugging. +#define D_METHOD(m_c, ...) m_c + +#endif + class ClassDB { public: enum APIType { @@ -134,7 +144,11 @@ public: static HashMap<StringName, StringName> resource_base_extensions; static HashMap<StringName, StringName> compat_classes; +#ifdef DEBUG_METHODS_ENABLED static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount); +#else + static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount); +#endif static APIType current_api; diff --git a/core/object/method_bind.cpp b/core/object/method_bind.cpp index a79adb7c6c..a208c1a2b2 100644 --- a/core/object/method_bind.cpp +++ b/core/object/method_bind.cpp @@ -69,8 +69,6 @@ PropertyInfo MethodBind::get_argument_info(int p_argument) const { PropertyInfo info = _gen_argument_type_info(p_argument); #ifdef DEBUG_METHODS_ENABLED info.name = p_argument < arg_names.size() ? String(arg_names[p_argument]) : String("arg" + itos(p_argument)); -#else - info.name = String("arg" + itos(p_argument)); #endif return info; } diff --git a/core/object/method_bind.h b/core/object/method_bind.h index bde6cba199..2870195911 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -152,7 +152,7 @@ protected: MethodInfo method_info; public: - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { if (p_arg < 0) { return _gen_return_type_info(); } else if (p_arg < method_info.arguments.size()) { @@ -162,23 +162,23 @@ public: } } - virtual Variant::Type _gen_argument_type(int p_arg) const { + virtual Variant::Type _gen_argument_type(int p_arg) const override { return _gen_argument_type_info(p_arg).type; } #ifdef DEBUG_METHODS_ENABLED - virtual GodotTypeInfo::Metadata get_argument_meta(int) const { + virtual GodotTypeInfo::Metadata get_argument_meta(int) const override { return GodotTypeInfo::METADATA_NONE; } #endif - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { ERR_FAIL(); // Can't call. } virtual bool is_const() const { return false; } - virtual bool is_vararg() const { return true; } + virtual bool is_vararg() const override { return true; } MethodBindVarArgBase( R (T::*p_method)(const Variant **, int, Callable::CallError &), @@ -224,7 +224,7 @@ class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, v friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>; public: - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>::method)(p_args, p_arg_count, r_error); return {}; } @@ -255,7 +255,7 @@ class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>; public: - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { return (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)(p_args, p_arg_count, r_error); } @@ -303,7 +303,7 @@ protected: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wlogical-op" #endif - virtual Variant::Type _gen_argument_type(int p_arg) const { + virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); } else { @@ -314,7 +314,7 @@ protected: #pragma GCC diagnostic pop #endif - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { PropertyInfo pi; call_get_argument_type_info<P...>(p_arg, pi); return pi; @@ -322,25 +322,25 @@ protected: public: #ifdef DEBUG_METHODS_ENABLED - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { return call_get_argument_metadata<P...>(p_arg); } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { #ifdef TYPED_METHOD_BIND call_with_variant_args_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); #else - call_with_variant_args_dv((MB_T *)(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); + call_with_variant_args_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); #endif return Variant(); } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { #ifdef TYPED_METHOD_BIND call_with_ptr_args<T, P...>(static_cast<T *>(p_object), method, p_args); #else - call_with_ptr_args<MB_T, P...>((MB_T *)(p_object), method, p_args); + call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args); #endif } @@ -378,7 +378,7 @@ protected: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wlogical-op" #endif - virtual Variant::Type _gen_argument_type(int p_arg) const { + virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); } else { @@ -389,7 +389,7 @@ protected: #pragma GCC diagnostic pop #endif - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { PropertyInfo pi; call_get_argument_type_info<P...>(p_arg, pi); return pi; @@ -397,25 +397,25 @@ protected: public: #ifdef DEBUG_METHODS_ENABLED - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { return call_get_argument_metadata<P...>(p_arg); } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { #ifdef TYPED_METHOD_BIND call_with_variant_argsc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); #else - call_with_variant_argsc_dv((MB_T *)(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); + call_with_variant_argsc_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); #endif return Variant(); } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { #ifdef TYPED_METHOD_BIND call_with_ptr_argsc<T, P...>(static_cast<T *>(p_object), method, p_args); #else - call_with_ptr_argsc<MB_T, P...>((MB_T *)(p_object), method, p_args); + call_with_ptr_argsc<MB_T, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args); #endif } @@ -455,7 +455,7 @@ protected: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wlogical-op" #endif - virtual Variant::Type _gen_argument_type(int p_arg) const { + virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); } else { @@ -463,7 +463,7 @@ protected: } } - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { PropertyInfo pi; call_get_argument_type_info<P...>(p_arg, pi); @@ -478,7 +478,7 @@ protected: public: #ifdef DEBUG_METHODS_ENABLED - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { if (p_arg >= 0) { return call_get_argument_metadata<P...>(p_arg); } else { @@ -487,21 +487,21 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { Variant ret; #ifdef TYPED_METHOD_BIND call_with_variant_args_ret_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); #else - call_with_variant_args_ret_dv((MB_T *)p_object, method, p_args, p_arg_count, ret, r_error, get_default_arguments()); + call_with_variant_args_ret_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); #endif return ret; } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { #ifdef TYPED_METHOD_BIND call_with_ptr_args_ret<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); #else - call_with_ptr_args_ret<MB_T, R, P...>((MB_T *)(p_object), method, p_args, r_ret); + call_with_ptr_args_ret<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret); #endif } @@ -542,7 +542,7 @@ protected: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wlogical-op" #endif - virtual Variant::Type _gen_argument_type(int p_arg) const { + virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); } else { @@ -550,7 +550,7 @@ protected: } } - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { PropertyInfo pi; call_get_argument_type_info<P...>(p_arg, pi); @@ -565,7 +565,7 @@ protected: public: #ifdef DEBUG_METHODS_ENABLED - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { if (p_arg >= 0) { return call_get_argument_metadata<P...>(p_arg); } else { @@ -574,21 +574,21 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { Variant ret; #ifdef TYPED_METHOD_BIND call_with_variant_args_retc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); #else - call_with_variant_args_retc_dv((MB_T *)(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); + call_with_variant_args_retc_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); #endif return ret; } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { #ifdef TYPED_METHOD_BIND call_with_ptr_args_retc<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); #else - call_with_ptr_args_retc<MB_T, R, P...>((MB_T *)(p_object), method, p_args, r_ret); + call_with_ptr_args_retc<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret); #endif } @@ -626,7 +626,7 @@ protected: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wlogical-op" #endif - virtual Variant::Type _gen_argument_type(int p_arg) const { + virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); } else { @@ -637,7 +637,7 @@ protected: #pragma GCC diagnostic pop #endif - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { PropertyInfo pi; call_get_argument_type_info<P...>(p_arg, pi); return pi; @@ -645,18 +645,18 @@ protected: public: #ifdef DEBUG_METHODS_ENABLED - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { return call_get_argument_metadata<P...>(p_arg); } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { (void)p_object; // unused call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments()); return Variant(); } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { (void)p_object; (void)r_ret; call_with_ptr_args_static_method(function, p_args); @@ -689,7 +689,7 @@ protected: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wlogical-op" #endif - virtual Variant::Type _gen_argument_type(int p_arg) const { + virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); } else { @@ -700,7 +700,7 @@ protected: #pragma GCC diagnostic pop #endif - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { PropertyInfo pi; call_get_argument_type_info<P...>(p_arg, pi); @@ -712,7 +712,7 @@ protected: public: #ifdef DEBUG_METHODS_ENABLED - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { if (p_arg >= 0) { return call_get_argument_metadata<P...>(p_arg); } else { @@ -721,13 +721,13 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { Variant ret; call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments()); return ret; } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { (void)p_object; call_with_ptr_args_static_method_ret(function, p_args, r_ret); } diff --git a/core/os/keyboard.h b/core/os/keyboard.h index a21d81b2e7..3176a8a210 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -294,7 +294,7 @@ enum class Key { enum class KeyModifierMask { CODE_MASK = ((1 << 25) - 1), ///< Apply this mask to any keycode to remove modifiers. - MODIFIER_MASK = (0xFF << 24), ///< Apply this mask to isolate modifiers. + MODIFIER_MASK = (0x7F << 24), ///< Apply this mask to isolate modifiers. SHIFT = (1 << 25), ALT = (1 << 26), META = (1 << 27), diff --git a/core/os/os.cpp b/core/os/os.cpp index 846aeb16c5..4f7095b0fc 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -237,6 +237,11 @@ String OS::get_locale_language() const { return get_locale().left(3).replace("_", ""); } +// Embedded PCK offset. +uint64_t OS::get_embedded_pck_offset() const { + return 0; +} + // Helper function to ensure that a dir name/path will be valid on the OS String OS::get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator) const { Vector<String> invalid_chars = String(": * ? \" < > |").split(" "); diff --git a/core/os/os.h b/core/os/os.h index b3c66ff18c..9ec0dd7728 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -264,6 +264,8 @@ public: virtual String get_locale() const; String get_locale_language() const; + virtual uint64_t get_embedded_pck_offset() const; + String get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator = false) const; virtual String get_godot_dir_name() const; diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 7199121932..a2b1e4c428 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -4124,15 +4124,11 @@ String String::path_to(const String &p_path) const { dst += "/"; } - String base; - if (src.begins_with("res://") && dst.begins_with("res://")) { - base = "res:/"; src = src.replace("res://", "/"); dst = dst.replace("res://", "/"); } else if (src.begins_with("user://") && dst.begins_with("user://")) { - base = "user:/"; src = src.replace("user://", "/"); dst = dst.replace("user://", "/"); @@ -4147,7 +4143,6 @@ String String::path_to(const String &p_path) const { return p_path; //impossible to do this } - base = src_begin; src = src.substr(src_begin.length(), src.length()); dst = dst.substr(dst_begin.length(), dst.length()); } diff --git a/core/templates/oa_hash_map.h b/core/templates/oa_hash_map.h index e4d9323c45..25c21d1802 100644 --- a/core/templates/oa_hash_map.h +++ b/core/templates/oa_hash_map.h @@ -246,13 +246,17 @@ public: return false; } - /** - * returns true if the value was found, false otherwise. - * - * if r_data is not nullptr then the value will be written to the object - * it points to. - */ - TValue *lookup_ptr(const TKey &p_key) const { + const TValue *lookup_ptr(const TKey &p_key) const { + uint32_t pos = 0; + bool exists = _lookup_pos(p_key, pos); + + if (exists) { + return &values[pos]; + } + return nullptr; + } + + TValue *lookup_ptr(const TKey &p_key) { uint32_t pos = 0; bool exists = _lookup_pos(p_key, pos); diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index b3e909b489..da5d73d519 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -184,7 +184,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { if (p_type_from == p_type_to) { return true; } - if (p_type_to == NIL && p_type_from != NIL) { //nil can convert to anything + if (p_type_to == NIL) { //nil can convert to anything return true; } @@ -490,7 +490,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type if (p_type_from == p_type_to) { return true; } - if (p_type_to == NIL && p_type_from != NIL) { //nil can convert to anything + if (p_type_to == NIL) { //nil can convert to anything return true; } diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index f1daf1de13..9dae0720d9 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1239,10 +1239,10 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const { void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants) { ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); - _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; + const _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; #ifdef DEBUG_ENABLED - for (List<StringName>::Element *E = cd.value_ordered.front(); E; E = E->next()) { + for (const List<StringName>::Element *E = cd.value_ordered.front(); E; E = E->next()) { p_constants->push_back(E->get()); #else for (const KeyValue<StringName, int> &E : cd.value) { @@ -1251,7 +1251,7 @@ void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_c } #ifdef DEBUG_ENABLED - for (List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) { + for (const List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) { p_constants->push_back(E->get()); #else for (const KeyValue<StringName, Variant> &E : cd.variant_value) { diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index e889a1bb40..5fc6df8f39 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -344,7 +344,6 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri if (string_name) { r_token.type = TK_STRING_NAME; r_token.value = StringName(str); - string_name = false; //reset } else { r_token.type = TK_STRING; r_token.value = str; diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index da6513a08b..0021b2f857 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -266,7 +266,7 @@ - Greater than 1.0 (exclusive): Ease in [/codeblock] [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/ease_cheatsheet.png]ease() curve values cheatsheet[/url] - See also [method smoothstep]. If you need to perform more advanced transitions, use [Tween] or [AnimationPlayer]. + See also [method smoothstep]. If you need to perform more advanced transitions, use [method Tween.interpolate_value]. </description> </method> <method name="error_string"> @@ -2013,7 +2013,7 @@ <constant name="KEY_CODE_MASK" value="33554431" enum="KeyModifierMask"> Key Code mask. </constant> - <constant name="KEY_MODIFIER_MASK" value="-16777216" enum="KeyModifierMask"> + <constant name="KEY_MODIFIER_MASK" value="2130706432" enum="KeyModifierMask"> Modifier key mask. </constant> <constant name="KEY_MASK_SHIFT" value="33554432" enum="KeyModifierMask"> diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml index 7d72cd867c..bd16fd3936 100644 --- a/doc/classes/Directory.xml +++ b/doc/classes/Directory.xml @@ -196,7 +196,8 @@ <return type="int" enum="Error" /> <argument index="0" name="path" type="String" /> <description> - Deletes the target file or an empty directory. The argument can be relative to the current directory, or an absolute path. If the target directory is not empty, the operation will fail. + Permanently deletes the target file or an empty directory. The argument can be relative to the current directory, or an absolute path. If the target directory is not empty, the operation will fail. + If you don't want to delete the file/directory permanently, use [method OS.move_to_trash] instead. Returns one of the [enum Error] code constants ([code]OK[/code] on success). </description> </method> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index d28bf80a1e..7bbb2ae26c 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -470,6 +470,12 @@ Returns the [EditorInterface] object that gives you control over Godot editor's window and its functionalities. </description> </method> + <method name="get_export_as_menu"> + <return type="PopupMenu" /> + <description> + Returns the [PopupMenu] under [b]Scene > Export As...[/b]. + </description> + </method> <method name="get_script_create_dialog"> <return type="ScriptCreateDialog" /> <description> diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml index 3de0d0dbe9..53894bad87 100644 --- a/doc/classes/GPUParticles2D.xml +++ b/doc/classes/GPUParticles2D.xml @@ -57,6 +57,9 @@ <member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta" default="true"> If [code]true[/code], results in fractional delta calculation which has a smoother particles display effect. </member> + <member name="interpolate" type="bool" setter="set_interpolate" getter="get_interpolate" default="true"> + Enables particle interpolation, which makes the particle movement smoother when their [member fixed_fps] is lower than the screen refresh rate. + </member> <member name="lifetime" type="float" setter="set_lifetime" getter="get_lifetime" default="1.0"> Amount of time each particle will exist. </member> diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index 899b5dec27..c4bd18db69 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -90,6 +90,7 @@ If [code]true[/code], results in fractional delta calculation which has a smoother particles display effect. </member> <member name="interpolate" type="bool" setter="set_interpolate" getter="get_interpolate" default="true"> + Enables particle interpolation, which makes the particle movement smoother when their [member fixed_fps] is lower than the screen refresh rate. </member> <member name="lifetime" type="float" setter="set_lifetime" getter="get_lifetime" default="1.0"> Amount of time each particle will exist. diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index c3552c9f62..948c4b253f 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -376,7 +376,8 @@ <argument index="0" name="duration_ms" type="int" default="500" /> <description> Vibrate Android and iOS devices. - [b]Note:[/b] It needs [code]VIBRATE[/code] permission for Android at export settings. iOS does not support duration. + [b]Note:[/b] For Android, it requires enabling the [code]VIBRATE[/code] permission in the export preset. + [b]Note:[/b] For iOS, specifying the duration is supported in iOS 13 and later. </description> </method> <method name="warp_mouse"> diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml index ac17886183..059d147979 100644 --- a/doc/classes/MultiplayerAPI.xml +++ b/doc/classes/MultiplayerAPI.xml @@ -6,7 +6,7 @@ <description> This class implements the high-level multiplayer API. See also [MultiplayerPeer]. By default, [SceneTree] has a reference to this class that is used to provide multiplayer capabilities (i.e. RPCs) across the whole scene. - It is possible to override the MultiplayerAPI instance used by specific Nodes by setting the [member Node.custom_multiplayer] property, effectively allowing to run both client and server in the same scene. + It is possible to override the MultiplayerAPI instance used by specific tree branches by calling the [method SceneTree.set_multiplayer] method, effectively allowing to run both client and server in the same scene. [b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice. [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android. </description> @@ -53,7 +53,7 @@ <method name="poll"> <return type="void" /> <description> - Method used for polling the MultiplayerAPI. You only need to worry about this if you are using [member Node.custom_multiplayer] override or you set [member SceneTree.multiplayer_poll] to [code]false[/code]. By default, [SceneTree] will poll its MultiplayerAPI for you. + Method used for polling the MultiplayerAPI. You only need to worry about this if you set [member SceneTree.multiplayer_poll] to [code]false[/code]. By default, [SceneTree] will poll its MultiplayerAPI(s) for you. [b]Note:[/b] This method results in RPCs being called, so they will be executed in the same context of this function (e.g. [code]_process[/code], [code]physics[/code], [Thread]). </description> </method> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 56c80078b3..c9795856d5 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -745,14 +745,11 @@ </method> </methods> <members> - <member name="custom_multiplayer" type="MultiplayerAPI" setter="set_custom_multiplayer" getter="get_custom_multiplayer"> - The override to the default [MultiplayerAPI]. Set to [code]null[/code] to use the default [SceneTree] one. - </member> <member name="editor_description" type="String" setter="set_editor_description" getter="get_editor_description" default=""""> Add a custom description to a node. It will be displayed in a tooltip when hovered in editor's scene tree. </member> <member name="multiplayer" type="MultiplayerAPI" setter="" getter="get_multiplayer"> - The [MultiplayerAPI] instance associated with this node. Either the [member custom_multiplayer], or the default SceneTree one (if inside tree). + The [MultiplayerAPI] instance associated with this node. See [method SceneTree.get_multiplayer]. </member> <member name="name" type="StringName" setter="set_name" getter="get_name"> The name of the node. This name is unique among the siblings (other child nodes from the same parent). When set to an existing name, the node will be automatically renamed. diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index b2e325d226..f45bee4db4 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -455,6 +455,14 @@ [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> + <method name="move_to_trash" qualifiers="const"> + <return type="int" enum="Error" /> + <argument index="0" name="path" type="String" /> + <description> + Moves the file or directory to the system's recycle bin. See also [method Directory.remove]. + [b]Note:[/b] If the user has disabled the recycle bin on their system, the file will be permanently deleted instead. + </description> + </method> <method name="open_midi_inputs"> <return type="void" /> <description> diff --git a/doc/classes/PacketPeerUDP.xml b/doc/classes/PacketPeerUDP.xml index 580bf60518..7c6622be3c 100644 --- a/doc/classes/PacketPeerUDP.xml +++ b/doc/classes/PacketPeerUDP.xml @@ -61,7 +61,7 @@ Returns whether this [PacketPeerUDP] is bound to an address and can receive packets. </description> </method> - <method name="is_connected_to_host" qualifiers="const"> + <method name="is_socket_connected" qualifiers="const"> <return type="bool" /> <description> Returns [code]true[/code] if the UDP socket is open and has been connected to a remote address. See [method connect_to_host]. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index ee32677b3a..7c6d6d1c10 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -578,9 +578,19 @@ <member name="gui/theme/default_font_antialiased" type="bool" setter="" getter="" default="true"> If set to [code]true[/code], default font uses 8-bit anitialiased glyph rendering. See [member FontData.antialiased]. </member> + <member name="gui/theme/default_font_generate_mipmaps" type="bool" setter="" getter="" default="false"> + If set to [code]true[/code], the default font will have mipmaps generated. This prevents text from looking grainy when a [Control] is scaled down, or when a [Label3D] is viewed from a long distance (if [member Label3D.texture_filter] is set to a mode that displays mipmaps). + Enabling [member gui/theme/default_font_generate_mipmaps] increases font generation time and memory usage. Only enable this setting if you actually need it. + [b]Note:[/b] This setting does not affect custom [Font]s used within the project. + </member> <member name="gui/theme/default_font_hinting" type="int" setter="" getter="" default="1"> Default font hinting mode. See [member FontData.hinting]. </member> + <member name="gui/theme/default_font_multichannel_signed_distance_field" type="bool" setter="" getter="" default="false"> + If set to [code]true[/code], the default font will use multichannel signed distance field (MSDF) for crisp rendering at any size. Since this approach does not rely on rasterizing the font every time its size changes, this allows for resizing the font in real-time without any performance penalty. Text will also not look grainy for [Control]s that are scaled down (or for [Label3D]s viewed from a long distance). + MSDF font rendering can be combined with [member gui/theme/default_font_generate_mipmaps] to further improve font rendering quality when scaled down. + [b]Note:[/b] This setting does not affect custom [Font]s used within the project. + </member> <member name="gui/theme/default_font_subpixel_positioning" type="int" setter="" getter="" default="1"> Default font glyph sub-pixel positioning mode. See [member FontData.subpixel_positioning]. </member> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 77023d2126..ddff766b17 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -99,6 +99,13 @@ Returns the current frame number, i.e. the total frame count since the application started. </description> </method> + <method name="get_multiplayer" qualifiers="const"> + <return type="MultiplayerAPI" /> + <argument index="0" name="for_path" type="NodePath" default="NodePath("")" /> + <description> + Return the [MultiplayerAPI] configured for the given path, or the default one if [code]for_path[/code] is empty. + </description> + </method> <method name="get_node_count" qualifiers="const"> <return type="int" /> <description> @@ -193,6 +200,14 @@ Sets the given [code]property[/code] to [code]value[/code] on all members of the given group, respecting the given [enum GroupCallFlags]. </description> </method> + <method name="set_multiplayer"> + <return type="void" /> + <argument index="0" name="multiplayer" type="MultiplayerAPI" /> + <argument index="1" name="root_path" type="NodePath" default="NodePath("")" /> + <description> + Sets a custom [MultiplayerAPI] with the given [code]root_path[/code] (controlling also the relative subpaths), or override the default one if [code]root_path[/code] is empty. + </description> + </method> <method name="set_quit_on_go_back"> <return type="void" /> <argument index="0" name="enabled" type="bool" /> @@ -215,9 +230,6 @@ <member name="edited_scene_root" type="Node" setter="set_edited_scene_root" getter="get_edited_scene_root"> The root of the edited scene. </member> - <member name="multiplayer" type="MultiplayerAPI" setter="set_multiplayer" getter="get_multiplayer"> - The default [MultiplayerAPI] instance for this [SceneTree]. - </member> <member name="multiplayer_poll" type="bool" setter="set_multiplayer_poll_enabled" getter="is_multiplayer_poll_enabled" default="true"> If [code]true[/code] (default value), enables automatic polling of the [MultiplayerAPI] for this SceneTree during [signal process_frame]. If [code]false[/code], you need to manually call [method MultiplayerAPI.poll] to process network packets and deliver RPCs. This allows running RPCs in a different loop (e.g. physics, thread, specific time step) and for manual [Mutex] protection when accessing the [MultiplayerAPI] from threads. diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml index 80a36acacc..f271220989 100644 --- a/doc/classes/Skeleton3D.xml +++ b/doc/classes/Skeleton3D.xml @@ -111,6 +111,14 @@ <return type="Transform3D" /> <argument index="0" name="bone_idx" type="int" /> <description> + Returns the global pose override transform for [code]bone_idx[/code]. + </description> + </method> + <method name="get_bone_global_rest" qualifiers="const"> + <return type="Transform3D" /> + <argument index="0" name="bone_idx" type="int" /> + <description> + Returns the global rest transform for [code]bone_idx[/code]. </description> </method> <method name="get_bone_local_pose_override" qualifiers="const"> diff --git a/doc/classes/StreamPeerTCP.xml b/doc/classes/StreamPeerTCP.xml index a1f1f1be79..f06cf5c7a2 100644 --- a/doc/classes/StreamPeerTCP.xml +++ b/doc/classes/StreamPeerTCP.xml @@ -51,16 +51,16 @@ Returns the local port to which this peer is bound. </description> </method> - <method name="get_status"> + <method name="get_status" qualifiers="const"> <return type="int" enum="StreamPeerTCP.Status" /> <description> Returns the status of the connection, see [enum Status]. </description> </method> - <method name="is_connected_to_host" qualifiers="const"> - <return type="bool" /> + <method name="poll"> + <return type="int" enum="Error" /> <description> - Returns [code]true[/code] if this peer is currently connected or is connecting to a host, [code]false[/code] otherwise. + Poll the socket, updating its state. See [method get_status]. </description> </method> <method name="set_no_delay"> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index 9453bb9e2a..259c800a78 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -330,10 +330,10 @@ [b]Note:[/b] Enabling [code]collision_animatable[/code] may have a small performance impact, only do it if the TileMap is moving and has colliding tiles. </member> <member name="collision_visibility_mode" type="int" setter="set_collision_visibility_mode" getter="get_collision_visibility_mode" enum="TileMap.VisibilityMode" default="0"> - Show or hide the TileMap's collision shapes. If set to [code]VISIBILITY_MODE_DEFAULT[/code], this depends on the show collision debug settings. + Show or hide the TileMap's collision shapes. If set to [constant VISIBILITY_MODE_DEFAULT], this depends on the show collision debug settings. </member> <member name="navigation_visibility_mode" type="int" setter="set_navigation_visibility_mode" getter="get_navigation_visibility_mode" enum="TileMap.VisibilityMode" default="0"> - Show or hide the TileMap's collision shapes. If set to [code]VISIBILITY_MODE_DEFAULT[/code], this depends on the show navigation debug settings. + Show or hide the TileMap's collision shapes. If set to [constant VISIBILITY_MODE_DEFAULT], this depends on the show navigation debug settings. </member> <member name="tile_set" type="TileSet" setter="set_tileset" getter="get_tileset"> The assigned [TileSet]. diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index 72f32f39c2..2ec8bb287c 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -6,7 +6,7 @@ <description> Tweens are mostly useful for animations requiring a numerical property to be interpolated over a range of values. The name [i]tween[/i] comes from [i]in-betweening[/i], an animation technique where you specify [i]keyframes[/i] and the computer interpolates the frames that appear between them. [Tween] is more suited than [AnimationPlayer] for animations where you don't know the final values in advance. For example, interpolating a dynamically-chosen camera zoom value is best done with a [Tween]; it would be difficult to do the same thing with an [AnimationPlayer] node. Tweens are also more light-weight than [AnimationPlayer], so they are very much suited for simple animations or general tasks that don't require visual tweaking provided by the editor. They can be used in a fire-and-forget manner for some logic that normally would be done by code. You can e.g. make something shoot periodically by using a looped [CallbackTweener] with a delay. - A [Tween] can be created by using either [method SceneTree.create_tween] or [method Node.create_tween]. [Tween]s created manually (i.e. by using [code]Tween.new()[/code]) are invalid. They can't be used for tweening values, but you can do manual interpolation with [method interpolate_value]. + A [Tween] can be created by using either [method SceneTree.create_tween] or [method Node.create_tween]. [Tween]s created manually (i.e. by using [code]Tween.new()[/code]) are invalid and can't be used for tweening values. A [Tween] animation is composed of a sequence of [Tweener]s, which by default are executed one after another. You can create a sequence by appending [Tweener]s to the [Tween]. Animating something with a [Tweener] is called tweening. Example tweening sequence looks like this: [codeblock] var tween = get_tree().create_tween() @@ -79,7 +79,7 @@ [b]Note:[/code] As it results from accumulating frame deltas, the time returned after the [Tween] has finished animating will be slightly greater than the actual [Tween] duration. </description> </method> - <method name="interpolate_value"> + <method name="interpolate_value" qualifiers="static"> <return type="Variant" /> <argument index="0" name="initial_value" type="Variant" /> <argument index="1" name="delta_value" type="Variant" /> @@ -105,7 +105,7 @@ <method name="is_valid"> <return type="bool" /> <description> - Returns whether the [Tween] is valid. A valid [Tween] is a [Tween] contained by the scene tree (i.e. the array from [method SceneTree.get_processed_tweens] will contain this [Tween]). [Tween] might become invalid when it has finished tweening or was killed, also when created with [code]Tween.new()[/code]. Invalid [Tween] can't have [Tweener]s appended, because it can't animate them. You can however still use [method interpolate_value]. + Returns whether the [Tween] is valid. A valid [Tween] is a [Tween] contained by the scene tree (i.e. the array from [method SceneTree.get_processed_tweens] will contain this [Tween]). [Tween] might become invalid when it has finished tweening or was killed, also when created with [code]Tween.new()[/code]. Invalid [Tween] can't have [Tweener]s appended, because it can't animate them. </description> </method> <method name="kill"> diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 441b049b50..ebf538351e 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -823,24 +823,24 @@ void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) { } // TODO maybe dont use -void RasterizerCanvasGLES3::_end_batch(uint32_t &r_index) { +void RasterizerCanvasGLES3::_end_batch(uint32_t p_index) { for (int i = 0; i < 4; i++) { - state.instance_data_array[r_index].modulation[i] = 0.0; - state.instance_data_array[r_index].ninepatch_margins[i] = 0.0; - state.instance_data_array[r_index].src_rect[i] = 0.0; - state.instance_data_array[r_index].dst_rect[i] = 0.0; + state.instance_data_array[p_index].modulation[i] = 0.0; + state.instance_data_array[p_index].ninepatch_margins[i] = 0.0; + state.instance_data_array[p_index].src_rect[i] = 0.0; + state.instance_data_array[p_index].dst_rect[i] = 0.0; } - state.instance_data_array[r_index].flags = uint32_t(0); - state.instance_data_array[r_index].color_texture_pixel_size[0] = 0.0; - state.instance_data_array[r_index].color_texture_pixel_size[1] = 0.0; + state.instance_data_array[p_index].flags = uint32_t(0); + state.instance_data_array[p_index].color_texture_pixel_size[0] = 0.0; + state.instance_data_array[p_index].color_texture_pixel_size[1] = 0.0; - state.instance_data_array[r_index].pad[0] = 0.0; - state.instance_data_array[r_index].pad[1] = 0.0; + state.instance_data_array[p_index].pad[0] = 0.0; + state.instance_data_array[p_index].pad[1] = 0.0; - state.instance_data_array[r_index].lights[0] = uint32_t(0); - state.instance_data_array[r_index].lights[1] = uint32_t(0); - state.instance_data_array[r_index].lights[2] = uint32_t(0); - state.instance_data_array[r_index].lights[3] = uint32_t(0); + state.instance_data_array[p_index].lights[0] = uint32_t(0); + state.instance_data_array[p_index].lights[1] = uint32_t(0); + state.instance_data_array[p_index].lights[2] = uint32_t(0); + state.instance_data_array[p_index].lights[3] = uint32_t(0); } RID RasterizerCanvasGLES3::light_create() { @@ -1102,8 +1102,8 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec { glBindBuffer(GL_ARRAY_BUFFER, pb.vertex_buffer); glBufferData(GL_ARRAY_BUFFER, stride * vertex_count * sizeof(float), nullptr, GL_STATIC_DRAW); // TODO may not be necessary - const uint8_t *r = polygon_buffer.ptr(); - float *fptr = (float *)r; + uint8_t *r = polygon_buffer.ptrw(); + float *fptr = reinterpret_cast<float *>(r); uint32_t *uptr = (uint32_t *)r; uint32_t base_offset = 0; { diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index a962796b2f..99b079b8bb 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -270,7 +270,7 @@ public: void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false); void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index); void _render_batch(uint32_t &p_max_index); - void _end_batch(uint32_t &p_max_index); + void _end_batch(uint32_t p_index); void _allocate_instance_data_buffer(); void initialize(); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 1382573461..08d6dd25cf 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -411,7 +411,7 @@ void RasterizerSceneGLES3::voxel_gi_set_quality(RS::VoxelGIQuality) { void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { } -void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { } void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 12bb21a5a0..1c78c66c20 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -196,7 +196,7 @@ public: void voxel_gi_set_quality(RS::VoxelGIQuality) override; void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override; void set_scene_pass(uint64_t p_pass) override; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index 0c27b76ed8..a6c35b6837 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -379,7 +379,7 @@ float AudioDriverPulseAudio::get_latency() { } void AudioDriverPulseAudio::thread_func(void *p_udata) { - AudioDriverPulseAudio *ad = (AudioDriverPulseAudio *)p_udata; + AudioDriverPulseAudio *ad = static_cast<AudioDriverPulseAudio *>(p_udata); unsigned int write_ofs = 0; size_t avail_bytes = 0; uint64_t default_device_msec = OS::get_singleton()->get_ticks_msec(); diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 400802686e..59b4c34c3f 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -6255,7 +6255,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma //validate with inputs for (uint32_t i = 0; i < 32; i++) { - if (!(shader->vertex_input_mask & (1 << i))) { + if (!(shader->vertex_input_mask & (1UL << i))) { continue; } bool found = false; diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index a084a10528..e724d4ccdb 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -586,20 +586,20 @@ public: pi.name = "value"; p_list->push_back(pi); } else { - PropertyHint hint = PROPERTY_HINT_NONE; - String hint_string; + PropertyHint val_hint = PROPERTY_HINT_NONE; + String val_hint_string; if (v.get_type() == Variant::OBJECT) { // Could actually check the object property if exists..? Yes I will! Ref<Resource> res = v; if (res.is_valid()) { - hint = PROPERTY_HINT_RESOURCE_TYPE; - hint_string = res->get_class(); + val_hint = PROPERTY_HINT_RESOURCE_TYPE; + val_hint_string = res->get_class(); } } if (v.get_type() != Variant::NIL) { - p_list->push_back(PropertyInfo(v.get_type(), "value", hint, hint_string)); + p_list->push_back(PropertyInfo(v.get_type(), "value", val_hint, val_hint_string)); } } @@ -1264,20 +1264,20 @@ public: pi.name = "value"; p_list->push_back(pi); } else { - PropertyHint hint = PROPERTY_HINT_NONE; - String hint_string; + PropertyHint val_hint = PROPERTY_HINT_NONE; + String val_hint_string; if (v.get_type() == Variant::OBJECT) { // Could actually check the object property if exists..? Yes I will! Ref<Resource> res = v; if (res.is_valid()) { - hint = PROPERTY_HINT_RESOURCE_TYPE; - hint_string = res->get_class(); + val_hint = PROPERTY_HINT_RESOURCE_TYPE; + val_hint_string = res->get_class(); } } if (v.get_type() != Variant::NIL) { - p_list->push_back(PropertyInfo(v.get_type(), "value", hint, hint_string)); + p_list->push_back(PropertyInfo(v.get_type(), "value", val_hint, val_hint_string)); } } } @@ -1572,7 +1572,6 @@ void AnimationTimelineEdit::_notification(int p_what) { Color color_time_dec = color; color_time_dec.a *= 0.5; #define SC_ADJ 100 - int min = 30; int dec = 1; int step = 1; int decimals = 2; @@ -1588,7 +1587,7 @@ void AnimationTimelineEdit::_notification(int p_what) { const int max_sc_width = String::num(max_sc).length() * max_digit_width; while (!step_found) { - min = max_sc_width; + int min = max_sc_width; if (decimals > 0) { min += period_width + max_digit_width * decimals; } @@ -2552,7 +2551,7 @@ bool AnimationTrackEdit::_is_value_key_valid(const Variant &p_key_value, Variant } Ref<Texture2D> AnimationTrackEdit::_get_key_type_icon() const { - Ref<Texture2D> type_icons[9] = { + const Ref<Texture2D> type_icons[9] = { get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")), get_theme_icon(SNAME("KeyTrackPosition"), SNAME("EditorIcons")), get_theme_icon(SNAME("KeyTrackRotation"), SNAME("EditorIcons")), @@ -4077,12 +4076,20 @@ Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() { if (player->has_animation(SceneStringNames::get_singleton()->RESET)) { return player->get_animation(SceneStringNames::get_singleton()->RESET); } else { + Ref<AnimationLibrary> al; + if (!player->has_animation_library("")) { + al.instantiate(); + player->add_animation_library("", al); + } else { + al = player->get_animation_library(""); + } + Ref<Animation> reset_anim; reset_anim.instantiate(); reset_anim->set_length(ANIM_MIN_LENGTH); - undo_redo->add_do_method(player, "add_animation", SceneStringNames::get_singleton()->RESET, reset_anim); + undo_redo->add_do_method(al.ptr(), "add_animation", SceneStringNames::get_singleton()->RESET, reset_anim); undo_redo->add_do_method(AnimationPlayerEditor::get_singleton(), "_animation_player_changed", player); - undo_redo->add_undo_method(player, "remove_animation", SceneStringNames::get_singleton()->RESET); + undo_redo->add_undo_method(al.ptr(), "remove_animation", SceneStringNames::get_singleton()->RESET); undo_redo->add_undo_method(AnimationPlayerEditor::get_singleton(), "_animation_player_changed", player); return reset_anim; } diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp index f8bf12227a..bea95d873e 100644 --- a/editor/audio_stream_preview.cpp +++ b/editor/audio_stream_preview.cpp @@ -101,7 +101,7 @@ void AudioStreamPreviewGenerator::_update_emit(ObjectID p_id) { } void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) { - Preview *preview = (Preview *)p_preview; + Preview *preview = static_cast<Preview *>(p_preview); float muxbuff_chunk_s = 0.25; diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 0f8667f81a..c9d612d4dd 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -365,6 +365,24 @@ void ConnectDialog::init(ConnectionData p_cd, bool p_edit) { deferred->set_pressed(b_deferred); oneshot->set_pressed(b_oneshot); + + MethodInfo r_signal; + Ref<Script> source_script = source->get_script(); + if (source_script.is_valid() && source_script->has_script_signal(signal)) { + List<MethodInfo> signals; + source_script->get_script_signal_list(&signals); + for (MethodInfo &mi : signals) { + if (mi.name == signal) { + r_signal = mi; + break; + } + } + } else { + ClassDB::get_signal(source->get_class(), signal, &r_signal); + } + + unbind_count->set_max(r_signal.arguments.size()); + unbind_count->set_value(p_cd.unbinds); _unbind_count_changed(p_cd.unbinds); @@ -619,6 +637,7 @@ void ConnectionsDock::_make_or_edit_connection() { if (add_script_function) { // Pick up args here before "it" is deleted by update_tree. script_function_args = it->get_metadata(0).operator Dictionary()["args"]; + script_function_args.resize(script_function_args.size() - cd.unbinds); for (int i = 0; i < cd.binds.size(); i++) { script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cd.binds[i].get_type())); } diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 58a9175df1..74993f567a 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -1820,6 +1820,18 @@ bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); + Error err = prepare_template(p_preset, p_debug, p_path, p_flags); + if (err == OK) { + err = export_project_data(p_preset, p_debug, p_path, p_flags); + } + + return err; +} + +Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { + if (!DirAccess::exists(p_path.get_base_dir())) { + return ERR_FILE_BAD_PATH; + } String custom_debug = p_preset->get("custom_template/debug"); String custom_release = p_preset->get("custom_template/release"); @@ -1841,49 +1853,52 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr da->make_dir_recursive(p_path.get_base_dir()); Error err = da->copy(template_path, p_path, get_chmod_flags()); - if (err == OK) { - String pck_path; - if (p_preset->get("binary_format/embed_pck")) { - pck_path = p_path; - } else { - pck_path = p_path.get_basename() + ".pck"; - } + return err; +} - Vector<SharedObject> so_files; +Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { + String pck_path; + if (p_preset->get("binary_format/embed_pck")) { + pck_path = p_path; + } else { + pck_path = p_path.get_basename() + ".pck"; + } - int64_t embedded_pos; - int64_t embedded_size; - err = save_pack(p_preset, p_debug, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); - if (err == OK && p_preset->get("binary_format/embed_pck")) { - if (embedded_size >= 0x100000000 && !p_preset->get("binary_format/64_bits")) { - EditorNode::get_singleton()->show_warning(TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB.")); - return ERR_INVALID_PARAMETER; - } + Vector<SharedObject> so_files; - err = fixup_embedded_pck(p_path, embedded_pos, embedded_size); + int64_t embedded_pos; + int64_t embedded_size; + Error err = save_pack(p_preset, p_debug, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); + if (err == OK && p_preset->get("binary_format/embed_pck")) { + if (embedded_size >= 0x100000000 && !p_preset->get("binary_format/64_bits")) { + EditorNode::get_singleton()->show_warning(TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB.")); + return ERR_INVALID_PARAMETER; } - if (err == OK && !so_files.is_empty()) { - // If shared object files, copy them. - for (int i = 0; i < so_files.size() && err == OK; i++) { - String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path); - String target_path; - if (so_files[i].target.is_empty()) { - target_path = p_path.get_base_dir().plus_file(src_path.get_file()); - } else { - target_path = p_path.get_base_dir().plus_file(so_files[i].target).plus_file(src_path.get_file()); - } + err = fixup_embedded_pck(p_path, embedded_pos, embedded_size); + } - if (da->dir_exists(src_path)) { - err = da->make_dir_recursive(target_path); - if (err == OK) { - err = da->copy_dir(src_path, target_path, -1, true); - } - } else { - err = da->copy(src_path, target_path); - if (err == OK) { - err = sign_shared_object(p_preset, p_debug, target_path); - } + if (err == OK && !so_files.is_empty()) { + // If shared object files, copy them. + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + for (int i = 0; i < so_files.size() && err == OK; i++) { + String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path); + String target_path; + if (so_files[i].target.is_empty()) { + target_path = p_path.get_base_dir().plus_file(src_path.get_file()); + } else { + target_path = p_path.get_base_dir().plus_file(so_files[i].target).plus_file(src_path.get_file()); + } + + if (da->dir_exists(src_path)) { + err = da->make_dir_recursive(target_path); + if (err == OK) { + err = da->copy_dir(src_path, target_path, -1, true); + } + } else { + err = da->copy(src_path, target_path); + if (err == OK) { + err = sign_shared_object(p_preset, p_debug, target_path); } } } diff --git a/editor/editor_export.h b/editor/editor_export.h index 236f4d129c..ab09c98941 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -442,6 +442,10 @@ public: virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); virtual String get_template_file_name(const String &p_target, const String &p_arch) const = 0; + Error prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags); + Error export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags); + + void set_extension(const String &p_extension, const String &p_feature_key = "default"); void set_name(const String &p_name); void set_os_name(const String &p_name); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index bd9b0ae1c8..5d47b87fbf 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -3515,7 +3515,9 @@ void EditorInspector::_notification(int p_what) { get_v_scroll_bar()->call_deferred(SNAME("set_value"), update_scroll_request); update_scroll_request = -1; } - if (refresh_countdown > 0) { + if (update_tree_pending) { + refresh_countdown = float(EditorSettings::get_singleton()->get("docks/property_editor/auto_refresh_interval")); + } else if (refresh_countdown > 0) { refresh_countdown -= get_process_delta_time(); if (refresh_countdown <= 0) { for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 3cc4821f95..113f01caae 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -134,6 +134,7 @@ #include "editor/plugins/asset_library_editor_plugin.h" #include "editor/plugins/audio_stream_editor_plugin.h" #include "editor/plugins/audio_stream_randomizer_editor_plugin.h" +#include "editor/plugins/bit_map_editor_plugin.h" #include "editor/plugins/camera_3d_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/collision_polygon_2d_editor_plugin.h" @@ -171,6 +172,7 @@ #include "editor/plugins/physical_bone_3d_editor_plugin.h" #include "editor/plugins/polygon_2d_editor_plugin.h" #include "editor/plugins/polygon_3d_editor_plugin.h" +#include "editor/plugins/ray_cast_2d_editor_plugin.h" #include "editor/plugins/replication_editor_plugin.h" #include "editor/plugins/resource_preloader_editor_plugin.h" #include "editor/plugins/root_motion_editor_plugin.h" @@ -2658,25 +2660,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { project_export->popup_export(); } break; - case FILE_EXPORT_MESH_LIBRARY: { - if (!editor_data.get_edited_scene_root()) { - show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); - break; - } - - List<String> extensions; - Ref<MeshLibrary> ml(memnew(MeshLibrary)); - ResourceSaver::get_recognized_extensions(ml, &extensions); - file_export_lib->clear_filters(); - for (const String &E : extensions) { - file_export_lib->add_filter("*." + E); - } - - file_export_lib->popup_file_dialog(); - file_export_lib->set_title(TTR("Export Mesh Library")); - - } break; - case FILE_EXTERNAL_OPEN_SCENE: { if (unsaved_cache && !p_confirmed) { confirmation->get_ok_button()->set_text(TTR("Open")); @@ -3020,6 +3003,40 @@ void EditorNode::_tool_menu_option(int p_idx) { } } +void EditorNode::_export_as_menu_option(int p_idx) { + if (p_idx == 0) { // MeshLibrary + current_menu_option = FILE_EXPORT_MESH_LIBRARY; + + if (!editor_data.get_edited_scene_root()) { + show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); + return; + } + + List<String> extensions; + Ref<MeshLibrary> ml(memnew(MeshLibrary)); + ResourceSaver::get_recognized_extensions(ml, &extensions); + file_export_lib->clear_filters(); + for (const String &E : extensions) { + file_export_lib->add_filter("*." + E); + } + + file_export_lib->popup_file_dialog(); + file_export_lib->set_title(TTR("Export Mesh Library")); + } else { // Custom menu options added by plugins + if (export_as_menu->get_item_submenu(p_idx).is_empty()) { // If not a submenu + Callable callback = export_as_menu->get_item_metadata(p_idx); + Callable::CallError ce; + Variant result; + callback.call(nullptr, 0, result, ce); + + if (ce.error != Callable::CallError::CALL_OK) { + String err = Variant::get_callable_error_text(callback, nullptr, 0, ce); + ERR_PRINT("Error calling function from export_as menu: " + err); + } + } + } +} + int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) { for (int i = p_start; i < editor_data.get_edited_scene_count(); i++) { if (!editor_data.get_edited_scene_root(i)) { @@ -4094,22 +4111,28 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p ERR_FAIL_COND_V_MSG(p_class.is_empty(), nullptr, "Class name cannot be empty."); if (ScriptServer::is_global_class(p_class)) { - Ref<ImageTexture> icon; - Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_class); - StringName name = p_class; - - while (script.is_valid()) { - name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); - String current_icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); - icon = _load_custom_class_icon(current_icon_path); + String class_name = p_class; + Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(class_name); + + while (true) { + String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(class_name); + Ref<Texture> icon = _load_custom_class_icon(icon_path); if (icon.is_valid()) { - return icon; + return icon; // Current global class has icon. } - script = script->get_base_script(); - } - if (icon.is_null()) { - icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(name), SNAME("EditorIcons")); + // Find next global class along the inheritance chain. + do { + Ref<Script> base_script = script->get_base_script(); + if (base_script.is_null()) { + // We've reached a native class, use its icon. + String base_type; + script->get_language()->get_global_class_name(script->get_path(), &base_type); + return gui_base->get_theme_icon(base_type, "EditorIcons"); + } + script = base_script; + class_name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + } while (class_name.is_empty()); } } @@ -5465,6 +5488,10 @@ void EditorNode::remove_tool_menu_item(const String &p_name) { } } +PopupMenu *EditorNode::get_export_as_menu() { + return export_as_menu; +} + void EditorNode::_global_menu_scene(const Variant &p_tag) { int idx = (int)p_tag; scene_tabs->set_current_tab(idx); @@ -6439,12 +6466,12 @@ EditorNode::EditorNode() { p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTR("Quick Open Script..."), KeyModifierMask::CMD + KeyModifierMask::ALT + Key::O), FILE_QUICK_OPEN_SCRIPT); p->add_separator(); - PopupMenu *pm_export = memnew(PopupMenu); - pm_export->set_name("Export"); - p->add_child(pm_export); - p->add_submenu_item(TTR("Convert To..."), "Export"); - pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_MeshLibrary", TTR("MeshLibrary...")), FILE_EXPORT_MESH_LIBRARY); - pm_export->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option)); + export_as_menu = memnew(PopupMenu); + export_as_menu->set_name("Export"); + p->add_child(export_as_menu); + p->add_submenu_item(TTR("Export As..."), "Export"); + export_as_menu->add_shortcut(ED_SHORTCUT("editor/export_as_mesh_library", TTR("MeshLibrary...")), FILE_EXPORT_MESH_LIBRARY); + export_as_menu->connect("index_pressed", callable_mp(this, &EditorNode::_export_as_menu_option)); p->add_separator(); p->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO, true); @@ -7066,6 +7093,8 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(TextControlEditorPlugin)); add_editor_plugin(memnew(ControlEditorPlugin)); add_editor_plugin(memnew(GradientTexture2DEditorPlugin)); + add_editor_plugin(memnew(BitMapEditorPlugin)); + add_editor_plugin(memnew(RayCast2DEditorPlugin)); for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) { add_editor_plugin(EditorPlugins::create(i)); @@ -7084,6 +7113,7 @@ EditorNode::EditorNode() { resource_preview->add_preview_generator(Ref<EditorMeshPreviewPlugin>(memnew(EditorMeshPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorBitmapPreviewPlugin>(memnew(EditorBitmapPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorFontPreviewPlugin>(memnew(EditorFontPreviewPlugin))); + resource_preview->add_preview_generator(Ref<EditorGradientPreviewPlugin>(memnew(EditorGradientPreviewPlugin))); { Ref<StandardMaterial3DConversionPlugin> spatial_mat_convert; diff --git a/editor/editor_node.h b/editor/editor_node.h index c6c1f09938..82118b8b70 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -323,6 +323,7 @@ private: MenuButton *settings_menu = nullptr; MenuButton *help_menu = nullptr; PopupMenu *tool_menu = nullptr; + PopupMenu *export_as_menu = nullptr; Button *export_button = nullptr; Button *prev_scene = nullptr; Button *play_button = nullptr; @@ -524,6 +525,7 @@ private: void _save_screenshot(NodePath p_path); void _tool_menu_option(int p_idx); + void _export_as_menu_option(int p_idx); void _update_file_menu_opened(); void _update_file_menu_closed(); @@ -840,6 +842,8 @@ public: void add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu); void remove_tool_menu_item(const String &p_name); + PopupMenu *get_export_as_menu(); + void save_all_scenes(); void save_scene_list(Vector<String> p_scene_filenames); void restart_editor(); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 6596c245bc..639846861b 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -524,6 +524,10 @@ void EditorPlugin::remove_tool_menu_item(const String &p_name) { EditorNode::get_singleton()->remove_tool_menu_item(p_name); } +PopupMenu *EditorPlugin::get_export_as_menu() { + return EditorNode::get_singleton()->get_export_as_menu(); +} + void EditorPlugin::set_input_event_forwarding_always_enabled() { input_event_forwarding_always_enabled = true; EditorPluginList *always_input_forwarding_list = EditorNode::get_singleton()->get_editor_plugins_force_input_forwarding(); @@ -870,6 +874,7 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("add_tool_menu_item", "name", "callable"), &EditorPlugin::add_tool_menu_item); ClassDB::bind_method(D_METHOD("add_tool_submenu_item", "name", "submenu"), &EditorPlugin::add_tool_submenu_item); ClassDB::bind_method(D_METHOD("remove_tool_menu_item", "name"), &EditorPlugin::remove_tool_menu_item); + ClassDB::bind_method(D_METHOD("get_export_as_menu"), &EditorPlugin::get_export_as_menu); ClassDB::bind_method(D_METHOD("add_custom_type", "type", "base", "script", "icon"), &EditorPlugin::add_custom_type); ClassDB::bind_method(D_METHOD("remove_custom_type", "type"), &EditorPlugin::remove_custom_type); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 1a5be7a89b..c666b4639d 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -220,6 +220,8 @@ public: void add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu); void remove_tool_menu_item(const String &p_name); + PopupMenu *get_export_as_menu(); + void set_input_event_forwarding_always_enabled(); bool is_input_event_forwarding_always_enabled() { return input_event_forwarding_always_enabled; } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 677d22cb62..581a807e27 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3361,10 +3361,8 @@ struct EditorPropertyRangeHint { static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const String &p_hint_text, double p_default_step) { EditorPropertyRangeHint hint; hint.step = p_default_step; - bool degrees = false; - + Vector<String> slices = p_hint_text.split(","); 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)); @@ -3381,11 +3379,7 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri hint.hide_slider = false; for (int i = 2; i < slices.size(); i++) { String slice = slices[i].strip_edges(); - if (slice == "radians") { - hint.radians = true; - } else if (slice == "degrees") { - degrees = true; - } else if (slice == "or_greater") { + if (slice == "or_greater") { hint.greater = true; } else if (slice == "or_lesser") { hint.lesser = true; @@ -3393,11 +3387,20 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri hint.hide_slider = true; } else if (slice == "exp") { hint.exp_range = true; - } else if (slice.begins_with("suffix:")) { - hint.suffix = " " + slice.replace_first("suffix:", "").strip_edges(); } } } + bool degrees = false; + for (int i = 0; i < slices.size(); i++) { + String slice = slices[i].strip_edges(); + if (slice == "radians") { + hint.radians = true; + } else if (slice == "degrees") { + degrees = true; + } else if (slice.begins_with("suffix:")) { + hint.suffix = " " + slice.replace_first("suffix:", "").strip_edges(); + } + } if ((hint.radians || degrees) && hint.suffix.is_empty()) { hint.suffix = U"\u00B0"; diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index f59ba66862..ffbe50285c 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -209,46 +209,13 @@ void EditorPropertyArray::_object_id_selected(const StringName &p_property, Obje void EditorPropertyArray::update_property() { Variant array = get_edited_object()->get(get_edited_property()); - String arrtype = ""; - switch (array_type) { - case Variant::ARRAY: { - arrtype = "Array"; - } break; - - // Arrays. - case Variant::PACKED_BYTE_ARRAY: { - arrtype = "PackedByteArray"; - } break; - case Variant::PACKED_INT32_ARRAY: { - arrtype = "PackedInt32Array"; - } break; - case Variant::PACKED_FLOAT32_ARRAY: { - arrtype = "PackedFloat32Array"; - } break; - case Variant::PACKED_INT64_ARRAY: { - arrtype = "PackedInt64Array"; - } break; - case Variant::PACKED_FLOAT64_ARRAY: { - arrtype = "PackedFloat64Array"; - } break; - case Variant::PACKED_STRING_ARRAY: { - arrtype = "PackedStringArray"; - } break; - case Variant::PACKED_VECTOR2_ARRAY: { - arrtype = "PackedVector2Array"; - } break; - case Variant::PACKED_VECTOR3_ARRAY: { - arrtype = "PackedVector3Array"; - } break; - case Variant::PACKED_COLOR_ARRAY: { - arrtype = "PackedColorArray"; - } break; - default: { - } + String array_type_name = Variant::get_type_name(array_type); + if (array_type == Variant::ARRAY && subtype != Variant::NIL) { + array_type_name = vformat("%s[%s]", array_type_name, Variant::get_type_name(subtype)); } if (array.get_type() == Variant::NIL) { - edit->set_text(String("(Nil) ") + arrtype); + edit->set_text(vformat(TTR("(Nil) %s"), array_type_name)); edit->set_pressed(false); if (vbox) { set_bottom_editor(nullptr); @@ -264,7 +231,7 @@ void EditorPropertyArray::update_property() { page_index = MIN(page_index, max_page); int offset = page_index * page_length; - edit->set_text(arrtype + " (size " + itos(size) + ")"); + edit->set_text(vformat(TTR("%s (size %s)"), array_type_name, itos(size))); bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); if (edit->is_pressed() != unfolded) { diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index a1d09d4df3..3c68a715c3 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -90,7 +90,8 @@ void EditorResourcePicker::_update_resource_preview(const String &p_path, const if (p_preview.is_valid()) { preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox(SNAME("normal"))->get_default_margin(SIDE_LEFT) + get_theme_constant(SNAME("h_separation"), SNAME("Button"))); - if (Ref<GradientTexture1D>(edited_resource).is_valid()) { + // Resource-specific stretching. + if (Ref<GradientTexture1D>(edited_resource).is_valid() || Ref<Gradient>(edited_resource).is_valid()) { preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE); assign_button->set_custom_minimum_size(Size2(1, 1)); } else { diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index 574acdff1c..6a2ff50ee0 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -98,67 +98,79 @@ Error EditorRun::run(const String &p_scene) { screen_rect.position = DisplayServer::get_singleton()->screen_get_position(screen); screen_rect.size = DisplayServer::get_singleton()->screen_get_size(screen); - Size2 window_size; - window_size.x = ProjectSettings::get_singleton()->get("display/window/size/viewport_width"); - window_size.y = ProjectSettings::get_singleton()->get("display/window/size/viewport_height"); - - Size2 desired_size; - desired_size.x = ProjectSettings::get_singleton()->get("display/window/size/window_width_override"); - desired_size.y = ProjectSettings::get_singleton()->get("display/window/size/window_height_override"); - if (desired_size.x > 0 && desired_size.y > 0) { - window_size = desired_size; - } - int window_placement = EditorSettings::get_singleton()->get("run/window_placement/rect"); - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_HIDPI)) { - bool hidpi_proj = ProjectSettings::get_singleton()->get("display/window/dpi/allow_hidpi"); - int display_scale = 1; + if (screen_rect != Rect2()) { + Size2 window_size; + window_size.x = ProjectSettings::get_singleton()->get("display/window/size/viewport_width"); + window_size.y = ProjectSettings::get_singleton()->get("display/window/size/viewport_height"); + + Size2 desired_size; + desired_size.x = ProjectSettings::get_singleton()->get("display/window/size/window_width_override"); + desired_size.y = ProjectSettings::get_singleton()->get("display/window/size/window_height_override"); + if (desired_size.x > 0 && desired_size.y > 0) { + window_size = desired_size; + } - if (OS::get_singleton()->is_hidpi_allowed()) { - if (hidpi_proj) { - display_scale = 1; // Both editor and project runs in hiDPI mode, do not scale. - } else { - display_scale = DisplayServer::get_singleton()->screen_get_max_scale(); // Editor is in hiDPI mode, project is not, scale down. - } - } else { - if (hidpi_proj) { - display_scale = (1.f / DisplayServer::get_singleton()->screen_get_max_scale()); // Editor is not in hiDPI mode, project is, scale up. + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_HIDPI)) { + bool hidpi_proj = ProjectSettings::get_singleton()->get("display/window/dpi/allow_hidpi"); + int display_scale = 1; + + if (OS::get_singleton()->is_hidpi_allowed()) { + if (hidpi_proj) { + display_scale = 1; // Both editor and project runs in hiDPI mode, do not scale. + } else { + display_scale = DisplayServer::get_singleton()->screen_get_max_scale(); // Editor is in hiDPI mode, project is not, scale down. + } } else { - display_scale = 1; // Both editor and project runs in lowDPI mode, do not scale. + if (hidpi_proj) { + display_scale = (1.f / DisplayServer::get_singleton()->screen_get_max_scale()); // Editor is not in hiDPI mode, project is, scale up. + } else { + display_scale = 1; // Both editor and project runs in lowDPI mode, do not scale. + } } + screen_rect.position /= display_scale; + screen_rect.size /= display_scale; } - screen_rect.position /= display_scale; - screen_rect.size /= display_scale; - } - switch (window_placement) { - case 0: { // top left - args.push_back("--position"); - args.push_back(itos(screen_rect.position.x) + "," + itos(screen_rect.position.y)); - } break; - case 1: { // centered - Vector2 pos = (screen_rect.position) + ((screen_rect.size - window_size) / 2).floor(); - args.push_back("--position"); - args.push_back(itos(pos.x) + "," + itos(pos.y)); - } break; - case 2: { // custom pos - Vector2 pos = EditorSettings::get_singleton()->get("run/window_placement/rect_custom_position"); - pos += screen_rect.position; - args.push_back("--position"); - args.push_back(itos(pos.x) + "," + itos(pos.y)); - } break; - case 3: { // force maximized - Vector2 pos = screen_rect.position; - args.push_back("--position"); - args.push_back(itos(pos.x) + "," + itos(pos.y)); - args.push_back("--maximized"); - } break; - case 4: { // force fullscreen - Vector2 pos = screen_rect.position; - args.push_back("--position"); - args.push_back(itos(pos.x) + "," + itos(pos.y)); - args.push_back("--fullscreen"); - } break; + switch (window_placement) { + case 0: { // top left + args.push_back("--position"); + args.push_back(itos(screen_rect.position.x) + "," + itos(screen_rect.position.y)); + } break; + case 1: { // centered + Vector2 pos = (screen_rect.position) + ((screen_rect.size - window_size) / 2).floor(); + args.push_back("--position"); + args.push_back(itos(pos.x) + "," + itos(pos.y)); + } break; + case 2: { // custom pos + Vector2 pos = EditorSettings::get_singleton()->get("run/window_placement/rect_custom_position"); + pos += screen_rect.position; + args.push_back("--position"); + args.push_back(itos(pos.x) + "," + itos(pos.y)); + } break; + case 3: { // force maximized + Vector2 pos = screen_rect.position; + args.push_back("--position"); + args.push_back(itos(pos.x) + "," + itos(pos.y)); + args.push_back("--maximized"); + } break; + case 4: { // force fullscreen + Vector2 pos = screen_rect.position; + args.push_back("--position"); + args.push_back(itos(pos.x) + "," + itos(pos.y)); + args.push_back("--fullscreen"); + } break; + } + } else { + // Unable to get screen info, skip setting position. + switch (window_placement) { + case 3: { // force maximized + args.push_back("--maximized"); + } break; + case 4: { // force fullscreen + args.push_back("--fullscreen"); + } break; + } } List<String> breakpoints; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 48f04694aa..bdabff20f9 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1365,6 +1365,12 @@ float EditorSettings::get_auto_display_scale() const { return DisplayServer::get_singleton()->screen_get_max_scale(); #else const int screen = DisplayServer::get_singleton()->window_get_current_screen(); + + if (DisplayServer::get_singleton()->screen_get_size(screen) == Vector2i()) { + // Invalid screen size, skip. + return 1.0; + } + // Use the smallest dimension to use a correct display scale on portrait displays. const int smallest_dimension = MIN(DisplayServer::get_singleton()->screen_get_size(screen).x, DisplayServer::get_singleton()->screen_get_size(screen).y); if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && smallest_dimension >= 1400) { diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index b34b08b5de..3526b4ce4c 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -128,7 +128,7 @@ void ExportTemplateManager::_download_current() { } _download_template(mirror_url, true); - } else if (!mirrors_available && !is_refreshing_mirrors) { + } else if (!is_refreshing_mirrors) { _set_current_progress_status(TTR("Retrieving the mirror list...")); _refresh_mirrors(); } diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp index fe32399fc6..f8c99ff7d4 100644 --- a/editor/import/collada.cpp +++ b/editor/import/collada.cpp @@ -58,7 +58,7 @@ Transform3D Collada::get_root_transform() const { return unit_scale_transform; } -void Collada::Vertex::fix_unit_scale(Collada &state) { +void Collada::Vertex::fix_unit_scale(const Collada &state) { #ifdef COLLADA_IMPORT_SCALE_SCENE vertex *= state.state.unit_scale; #endif diff --git a/editor/import/collada.h b/editor/import/collada.h index b5e4cd9983..85735e93ac 100644 --- a/editor/import/collada.h +++ b/editor/import/collada.h @@ -266,7 +266,7 @@ public: } } - void fix_unit_scale(Collada &state); + void fix_unit_scale(const Collada &state); bool operator<(const Vertex &p_vert) const { if (uid == p_vert.uid) { diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index de51a28c5a..6770eef543 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -198,12 +198,12 @@ int ResourceImporterTexture::get_preset_count() const { String ResourceImporterTexture::get_preset_name(int p_idx) const { static const char *preset_names[] = { - "2D/3D (Auto-Detect)", - "2D", - "3D", + TTRC("2D/3D (Auto-Detect)"), + TTRC("2D"), + TTRC("3D"), }; - return preset_names[p_idx]; + return TTRGET(preset_names[p_idx]); } void ResourceImporterTexture::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { @@ -221,6 +221,7 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/premult_alpha"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/normal_map_invert_y"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/hdr_as_srgb"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/hdr_clamp_exposure"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "detect_3d/compress_to", PROPERTY_HINT_ENUM, "Disabled,VRAM Compressed,Basis Universal"), (p_preset == PRESET_DETECT) ? 1 : 0)); @@ -414,6 +415,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String const bool stream = false; const int size_limit = p_options["process/size_limit"]; const bool hdr_as_srgb = p_options["process/hdr_as_srgb"]; + const bool hdr_clamp_exposure = p_options["process/hdr_clamp_exposure"]; const int normal = p_options["compress/normal_map"]; const int hdr_compression = p_options["compress/hdr_compression"]; const int bptc_ldr = p_options["compress/bptc_ldr"]; @@ -485,6 +487,34 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String } } + if (hdr_clamp_exposure) { + // Clamp HDR exposure following Filament's tonemapping formula. + // This can be used to reduce fireflies in environment maps or reduce the influence + // of the sun from an HDRI panorama on environment lighting (when a DirectionalLight3D is used instead). + const int height = image->get_height(); + const int width = image->get_width(); + + // These values are chosen arbitrarily and seem to produce good results with 4,096 samples. + const float linear = 4096.0; + const float compressed = 16384.0; + + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + const Color color = image->get_pixel(i, j); + const float luma = color.get_luminance(); + + Color clamped_color; + if (luma <= linear) { + clamped_color = color; + } else { + clamped_color = (color / luma) * ((linear * linear - compressed * luma) / (2 * linear - compressed - luma)); + } + + image->set_pixel(i, j, clamped_color); + } + } + } + if (compress_mode == COMPRESS_BASIS_UNIVERSAL && image->get_format() >= Image::FORMAT_RF) { //basis universal does not support float formats, fall back compress_mode = COMPRESS_VRAM_COMPRESSED; diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 2415615a45..8397772bf8 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -530,25 +530,25 @@ void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, co state_machine_draw->draw_set_transform_matrix(Transform2D()); } -void AnimationNodeStateMachineEditor::_clip_src_line_to_rect(Vector2 &r_from, Vector2 &r_to, const Rect2 &p_rect) { - if (r_to == r_from) { +void AnimationNodeStateMachineEditor::_clip_src_line_to_rect(Vector2 &r_from, const Vector2 &p_to, const Rect2 &p_rect) { + if (p_to == r_from) { return; } //this could be optimized... - Vector2 n = (r_to - r_from).normalized(); + Vector2 n = (p_to - r_from).normalized(); while (p_rect.has_point(r_from)) { r_from += n; } } -void AnimationNodeStateMachineEditor::_clip_dst_line_to_rect(Vector2 &r_from, Vector2 &r_to, const Rect2 &p_rect) { - if (r_to == r_from) { +void AnimationNodeStateMachineEditor::_clip_dst_line_to_rect(const Vector2 &p_from, Vector2 &r_to, const Rect2 &p_rect) { + if (r_to == p_from) { return; } //this could be optimized... - Vector2 n = (r_to - r_from).normalized(); + Vector2 n = (r_to - p_from).normalized(); while (p_rect.has_point(r_to)) { r_to -= n; } diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index bf3f7e93cf..fe3f6f370c 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -147,8 +147,8 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { void _open_editor(const String &p_name); void _scroll_changed(double); - void _clip_src_line_to_rect(Vector2 &r_from, Vector2 &r_to, const Rect2 &p_rect); - void _clip_dst_line_to_rect(Vector2 &r_from, Vector2 &r_to, const Rect2 &p_rect); + void _clip_src_line_to_rect(Vector2 &r_from, const Vector2 &p_to, const Rect2 &p_rect); + void _clip_dst_line_to_rect(const Vector2 &p_from, Vector2 &r_to, const Rect2 &p_rect); void _erase_selected(); void _update_mode(); diff --git a/editor/plugins/bit_map_editor_plugin.cpp b/editor/plugins/bit_map_editor_plugin.cpp new file mode 100644 index 0000000000..9003c4480b --- /dev/null +++ b/editor/plugins/bit_map_editor_plugin.cpp @@ -0,0 +1,86 @@ +/*************************************************************************/ +/* bit_map_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "bit_map_editor_plugin.h" + +#include "editor/editor_scale.h" + +void BitMapEditor::setup(const Ref<BitMap> &p_bitmap) { + Ref<ImageTexture> texture; + texture.instantiate(); + texture->create_from_image(p_bitmap->convert_to_image()); + texture_rect->set_texture(texture); + + size_label->set_text(vformat(String::utf8("%s×%s"), p_bitmap->get_size().width, p_bitmap->get_size().height)); +} + +BitMapEditor::BitMapEditor() { + texture_rect = memnew(TextureRect); + texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); + texture_rect->set_texture_filter(TEXTURE_FILTER_NEAREST); + texture_rect->set_custom_minimum_size(Size2(0, 250) * EDSCALE); + add_child(texture_rect); + + size_label = memnew(Label); + size_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); + add_child(size_label); + + // Reduce extra padding on top and bottom of size label. + Ref<StyleBoxEmpty> stylebox; + stylebox.instantiate(); + stylebox->set_default_margin(SIDE_RIGHT, 4 * EDSCALE); + size_label->add_theme_style_override("normal", stylebox); +} + +/////////////////////// + +bool EditorInspectorPluginBitMap::can_handle(Object *p_object) { + return Object::cast_to<BitMap>(p_object) != nullptr; +} + +void EditorInspectorPluginBitMap::parse_begin(Object *p_object) { + BitMap *bitmap = Object::cast_to<BitMap>(p_object); + if (!bitmap) { + return; + } + Ref<BitMap> bm(bitmap); + + BitMapEditor *editor = memnew(BitMapEditor); + editor->setup(bm); + add_custom_control(editor); +} + +/////////////////////// + +BitMapEditorPlugin::BitMapEditorPlugin() { + Ref<EditorInspectorPluginBitMap> plugin; + plugin.instantiate(); + add_inspector_plugin(plugin); +} diff --git a/editor/plugins/bit_map_editor_plugin.h b/editor/plugins/bit_map_editor_plugin.h new file mode 100644 index 0000000000..c883e5542f --- /dev/null +++ b/editor/plugins/bit_map_editor_plugin.h @@ -0,0 +1,64 @@ +/*************************************************************************/ +/* bit_map_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BIT_MAP_PREVIEW_EDITOR_PLUGIN_H +#define BIT_MAP_PREVIEW_EDITOR_PLUGIN_H + +#include "editor/editor_plugin.h" +#include "scene/resources/bit_map.h" + +class BitMapEditor : public VBoxContainer { + GDCLASS(BitMapEditor, VBoxContainer); + + TextureRect *texture_rect = nullptr; + Label *size_label = nullptr; + +public: + void setup(const Ref<BitMap> &p_bitmap); + + BitMapEditor(); +}; + +class EditorInspectorPluginBitMap : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginBitMap, EditorInspectorPlugin); + +public: + virtual bool can_handle(Object *p_object) override; + virtual void parse_begin(Object *p_object) override; +}; + +class BitMapEditorPlugin : public EditorPlugin { + GDCLASS(BitMapEditorPlugin, EditorPlugin); + +public: + BitMapEditorPlugin(); +}; + +#endif // BIT_MAP_PREVIEW_EDITOR_PLUGIN_H diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 8d0db697e2..c840ce22ce 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -3372,7 +3372,7 @@ void CanvasItemEditor::_draw_selection() { // Draw the resize handles if (tool == TOOL_SELECT && canvas_item->_edit_use_rect() && _is_node_movable(canvas_item)) { Rect2 rect = canvas_item->_edit_get_rect(); - Vector2 endpoints[4] = { + const Vector2 endpoints[4] = { xform.xform(rect.position), xform.xform(rect.position + Vector2(rect.size.x, 0)), xform.xform(rect.position + rect.size), @@ -4575,7 +4575,7 @@ void CanvasItemEditor::_focus_selection(int p_op) { Rect2 rect; int count = 0; - Map<Node *, Object *> &selection = editor_selection->get_selection(); + const Map<Node *, Object *> &selection = editor_selection->get_selection(); for (const KeyValue<Node *, Object *> &E : selection) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E.key); if (!canvas_item) { diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index b8556220d2..a160ca463b 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -904,3 +904,34 @@ EditorFontPreviewPlugin::~EditorFontPreviewPlugin() { RS::get_singleton()->free(canvas); RS::get_singleton()->free(viewport); } + +//////////////////////////////////////////////////////////////////////////// + +static const real_t GRADIENT_PREVIEW_TEXTURE_SCALE_FACTOR = 4.0; + +bool EditorGradientPreviewPlugin::handles(const String &p_type) const { + return ClassDB::is_parent_class(p_type, "Gradient"); +} + +bool EditorGradientPreviewPlugin::generate_small_preview_automatically() const { + return true; +} + +Ref<Texture2D> EditorGradientPreviewPlugin::generate(const RES &p_from, const Size2 &p_size) const { + Ref<Gradient> gradient = p_from; + if (gradient.is_valid()) { + Ref<GradientTexture1D> ptex; + ptex.instantiate(); + ptex->set_width(p_size.width * GRADIENT_PREVIEW_TEXTURE_SCALE_FACTOR * EDSCALE); + ptex->set_gradient(gradient); + + Ref<ImageTexture> itex; + itex.instantiate(); + itex->create_from_image(ptex->get_image()); + return itex; + } + return Ref<Texture2D>(); +} + +EditorGradientPreviewPlugin::EditorGradientPreviewPlugin() { +} diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index 803f03f17e..73eb90dd86 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -182,4 +182,15 @@ public: EditorTileMapPatternPreviewPlugin(); ~EditorTileMapPatternPreviewPlugin(); }; + +class EditorGradientPreviewPlugin : public EditorResourcePreviewGenerator { + GDCLASS(EditorGradientPreviewPlugin, EditorResourcePreviewGenerator); + +public: + virtual bool handles(const String &p_type) const override; + virtual bool generate_small_preview_automatically() const override; + virtual Ref<Texture2D> generate(const RES &p_from, const Size2 &p_size) const override; + + EditorGradientPreviewPlugin(); +}; #endif // EDITORPREVIEWPLUGINS_H diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp index b15aec87d9..72caa15e9c 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp @@ -290,7 +290,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() { { uint8_t *tw = texdata.ptrw(); - float *twf = (float *)tw; + float *twf = reinterpret_cast<float *>(tw); for (int i = 0; i < vpc; i++) { twf[i * 2 + 0] = valid_positions[i].x; twf[i * 2 + 1] = valid_positions[i].y; @@ -334,7 +334,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() { { uint8_t *tw = normdata.ptrw(); - float *twf = (float *)tw; + float *twf = reinterpret_cast<float *>(tw); for (int i = 0; i < vpc; i++) { twf[i * 2 + 0] = valid_normals[i].x; twf[i * 2 + 1] = valid_normals[i].y; diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp index 35cbff53f4..4b1081ed92 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp @@ -354,7 +354,7 @@ void GPUParticles3DEditor::_generate_emission_points() { uint8_t *iw = point_img.ptrw(); memset(iw, 0, w * h * 3 * sizeof(float)); const Vector3 *r = points.ptr(); - float *wf = (float *)iw; + float *wf = reinterpret_cast<float *>(iw); for (int i = 0; i < point_count; i++) { wf[i * 3 + 0] = r[i].x; wf[i * 3 + 1] = r[i].y; @@ -383,7 +383,7 @@ void GPUParticles3DEditor::_generate_emission_points() { uint8_t *iw = point_img2.ptrw(); memset(iw, 0, w * h * 3 * sizeof(float)); const Vector3 *r = normals.ptr(); - float *wf = (float *)iw; + float *wf = reinterpret_cast<float *>(iw); for (int i = 0; i < point_count; i++) { wf[i * 3 + 0] = r[i].x; wf[i * 3 + 1] = r[i].y; diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.h b/editor/plugins/gpu_particles_3d_editor_plugin.h index 190fb9954b..6ba6d102ef 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.h +++ b/editor/plugins/gpu_particles_3d_editor_plugin.h @@ -55,7 +55,7 @@ protected: Vector<Face3> geometry; bool _generate(Vector<Vector3> &points, Vector<Vector3> &normals); - virtual void _generate_emission_points() = 0; + virtual void _generate_emission_points(){}; void _node_selected(const NodePath &p_path); static void _bind_methods(); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 6eed85e370..7e01593bda 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2087,9 +2087,8 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const const NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); real_t pan_speed = 1 / 150.0; - int pan_speed_modifier = 10; if (nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) { - pan_speed *= pan_speed_modifier; + pan_speed *= 10; } Transform3D camera_transform; @@ -2112,9 +2111,8 @@ void Node3DEditorViewport::_nav_zoom(Ref<InputEventWithModifiers> p_event, const const NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); real_t zoom_speed = 1 / 80.0; - int zoom_speed_modifier = 10; if (nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) { - zoom_speed *= zoom_speed_modifier; + zoom_speed *= 10; } NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/navigation/zoom_style").operator int(); @@ -2818,7 +2816,7 @@ void Node3DEditorViewport::_draw() { real_t scale_length = (max_speed - min_speed); if (!Math::is_zero_approx(scale_length)) { - real_t logscale_t = 1.0 - Math::log(1 + freelook_speed - min_speed) / Math::log(1 + scale_length); + real_t logscale_t = 1.0 - Math::log1p(freelook_speed - min_speed) / Math::log1p(scale_length); // Display the freelook speed to help the user get a better sense of scale. const int precision = freelook_speed < 1.0 ? 2 : 1; @@ -2841,7 +2839,7 @@ void Node3DEditorViewport::_draw() { real_t scale_length = (max_distance - min_distance); if (!Math::is_zero_approx(scale_length)) { - real_t logscale_t = 1.0 - Math::log(1 + cursor.distance - min_distance) / Math::log(1 + scale_length); + real_t logscale_t = 1.0 - Math::log1p(cursor.distance - min_distance) / Math::log1p(scale_length); // Display the zoom center distance to help the user get a better sense of scale. const int precision = cursor.distance < 1.0 ? 2 : 1; @@ -3644,7 +3642,7 @@ void Node3DEditorViewport::focus_selection() { Vector3 center; int count = 0; - List<Node *> &selection = editor_selection->get_selected_node_list(); + const List<Node *> &selection = editor_selection->get_selected_node_list(); for (Node *E : selection) { Node3D *sp = Object::cast_to<Node3D>(E); @@ -5515,7 +5513,7 @@ void Node3DEditor::_xform_dialog_action() { undo_redo->create_action(TTR("XForm Dialog")); - List<Node *> &selection = editor_selection->get_selected_node_list(); + const List<Node *> &selection = editor_selection->get_selected_node_list(); for (Node *E : selection) { Node3D *sp = Object::cast_to<Node3D>(E); @@ -6720,7 +6718,7 @@ Set<RID> _get_physics_bodies_rid(Node *node) { } void Node3DEditor::snap_selected_nodes_to_floor() { - List<Node *> &selection = editor_selection->get_selected_node_list(); + const List<Node *> &selection = editor_selection->get_selected_node_list(); Dictionary snap_data; for (Node *E : selection) { diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index e52b274908..3284af7bb5 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -320,14 +320,14 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_spatial_gui_input(Camera if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->is_ctrl_pressed()))) { //click into curve, break it down Vector<Vector3> v3a = c->tessellate(); - int idx = 0; int rc = v3a.size(); int closest_seg = -1; Vector3 closest_seg_point; - float closest_d = 1e20; if (rc >= 2) { + int idx = 0; const Vector3 *r = v3a.ptr(); + float closest_d = 1e20; if (p_camera->unproject_position(gt.xform(c->get_point_position(0))).distance_to(mbpos) < click_dist) { return EditorPlugin::AFTER_GUI_INPUT_PASS; //nope, existing diff --git a/editor/plugins/ray_cast_2d_editor_plugin.cpp b/editor/plugins/ray_cast_2d_editor_plugin.cpp new file mode 100644 index 0000000000..6f247a37ef --- /dev/null +++ b/editor/plugins/ray_cast_2d_editor_plugin.cpp @@ -0,0 +1,151 @@ +/*************************************************************************/ +/* ray_cast_2d_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "ray_cast_2d_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "editor/editor_node.h" + +void RayCast2DEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + get_tree()->connect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed)); + } break; + + case NOTIFICATION_EXIT_TREE: { + get_tree()->disconnect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed)); + } break; + } +} + +void RayCast2DEditor::_node_removed(Node *p_node) { + if (p_node == node) { + node = nullptr; + } +} + +bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { + if (!node || !node->is_visible_in_tree()) { + return false; + } + + Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { + if (mb->is_pressed()) { + if (xform.xform(node->get_target_position()).distance_to(mb->get_position()) < 8) { + pressed = true; + original_target_position = node->get_target_position(); + + return true; + } else { + pressed = false; + + return false; + } + } else if (pressed) { + undo_redo->create_action(TTR("Set target_position")); + undo_redo->add_do_method(node, "set_target_position", node->get_target_position()); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(node, "set_target_position", original_target_position); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); + undo_redo->commit_action(); + + pressed = false; + + return true; + } + } + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && pressed) { + Vector2 point = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position())); + point = node->get_global_transform().affine_inverse().xform(point); + + node->set_target_position(point); + canvas_item_editor->update_viewport(); + node->notify_property_list_changed(); + + return true; + } + + return false; +} + +void RayCast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { + if (!node || !node->is_visible_in_tree()) { + return; + } + + Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons")); + p_overlay->draw_texture(handle, gt.xform(node->get_target_position()) - handle->get_size() / 2); +} + +void RayCast2DEditor::edit(Node *p_node) { + if (!canvas_item_editor) { + canvas_item_editor = CanvasItemEditor::get_singleton(); + } + + if (p_node) { + node = Object::cast_to<RayCast2D>(p_node); + } else { + node = nullptr; + } + + canvas_item_editor->update_viewport(); +} + +RayCast2DEditor::RayCast2DEditor() { + undo_redo = EditorNode::get_singleton()->get_undo_redo(); +} + +/////////////////////// + +void RayCast2DEditorPlugin::edit(Object *p_object) { + ray_cast_2d_editor->edit(Object::cast_to<RayCast2D>(p_object)); +} + +bool RayCast2DEditorPlugin::handles(Object *p_object) const { + return Object::cast_to<RayCast2D>(p_object) != nullptr; +} + +void RayCast2DEditorPlugin::make_visible(bool p_visible) { + if (!p_visible) { + edit(nullptr); + } +} + +RayCast2DEditorPlugin::RayCast2DEditorPlugin() { + ray_cast_2d_editor = memnew(RayCast2DEditor); + EditorNode::get_singleton()->get_gui_base()->add_child(ray_cast_2d_editor); +} diff --git a/editor/plugins/ray_cast_2d_editor_plugin.h b/editor/plugins/ray_cast_2d_editor_plugin.h new file mode 100644 index 0000000000..74628da0e4 --- /dev/null +++ b/editor/plugins/ray_cast_2d_editor_plugin.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* ray_cast_2d_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RAY_CAST_2D_EDITOR_PLUGIN_H +#define RAY_CAST_2D_EDITOR_PLUGIN_H + +#include "editor/editor_plugin.h" +#include "scene/2d/ray_cast_2d.h" + +class CanvasItemEditor; + +class RayCast2DEditor : public Control { + GDCLASS(RayCast2DEditor, Control); + + UndoRedo *undo_redo = nullptr; + CanvasItemEditor *canvas_item_editor = nullptr; + RayCast2D *node; + + bool pressed = false; + Point2 original_target_position; + +protected: + void _notification(int p_what); + void _node_removed(Node *p_node); + +public: + bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); + void forward_canvas_draw_over_viewport(Control *p_overlay); + void edit(Node *p_node); + + RayCast2DEditor(); +}; + +class RayCast2DEditorPlugin : public EditorPlugin { + GDCLASS(RayCast2DEditorPlugin, EditorPlugin); + + RayCast2DEditor *ray_cast_2d_editor = nullptr; + +public: + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return ray_cast_2d_editor->forward_canvas_gui_input(p_event); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { ray_cast_2d_editor->forward_canvas_draw_over_viewport(p_overlay); } + + virtual String get_name() const override { return "RayCast2D"; } + bool has_main_screen() const override { return false; } + virtual void edit(Object *p_object) override; + virtual bool handles(Object *p_object) const override; + virtual void make_visible(bool visible) override; + + RayCast2DEditorPlugin(); +}; + +#endif // RAY_CAST_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 065683d632..1b703a097c 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -1209,8 +1209,7 @@ void Skeleton3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gi t.basis = to_local * p_transform.get_basis(); // Origin. - Vector3 orig = Vector3(); - orig = skeleton->get_bone_pose(p_id).origin; + Vector3 orig = skeleton->get_bone_pose(p_id).origin; Vector3 sub = p_transform.origin - skeleton->get_bone_global_pose(p_id).origin; t.origin = orig + to_local.xform(sub); @@ -1283,9 +1282,6 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->set_material(unselected_mat); } - Vector<Transform3D> grests; - grests.resize(skeleton->get_bone_count()); - LocalVector<int> bones; LocalVector<float> weights; bones.resize(4); @@ -1309,11 +1305,6 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { child_bones_vector = skeleton->get_bone_children(current_bone_idx); int child_bones_size = child_bones_vector.size(); - // You have children but no parent, then you must be a root/parentless bone. - if (skeleton->get_bone_parent(current_bone_idx) < 0) { - grests.write[current_bone_idx] = skeleton->get_bone_rest(current_bone_idx); - } - for (int i = 0; i < child_bones_size; i++) { // Something wrong. if (child_bones_vector[i] < 0) { @@ -1322,10 +1313,8 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { int child_bone_idx = child_bones_vector[i]; - grests.write[child_bone_idx] = grests[current_bone_idx] * skeleton->get_bone_rest(child_bone_idx); - - Vector3 v0 = grests[current_bone_idx].origin; - Vector3 v1 = grests[child_bone_idx].origin; + Vector3 v0 = skeleton->get_bone_global_rest(current_bone_idx).origin; + Vector3 v1 = skeleton->get_bone_global_rest(child_bone_idx).origin; Vector3 d = (v1 - v0).normalized(); real_t dist = v0.distance_to(v1); @@ -1333,7 +1322,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { int closest = -1; real_t closest_d = 0.0; for (int j = 0; j < 3; j++) { - real_t dp = Math::abs(grests[current_bone_idx].basis[j].normalized().dot(d)); + real_t dp = Math::abs(skeleton->get_bone_global_rest(current_bone_idx).basis[j].normalized().dot(d)); if (j == 0 || dp > closest_d) { closest = j; } @@ -1360,7 +1349,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { for (int j = 0; j < 3; j++) { Vector3 axis; if (first == Vector3()) { - axis = d.cross(d.cross(grests[current_bone_idx].basis[j])).normalized(); + axis = d.cross(d.cross(skeleton->get_bone_global_rest(current_bone_idx).basis[j])).normalized(); first = axis; } else { axis = d.cross(first).normalized(); @@ -1415,7 +1404,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->add_vertex(v0); surface_tool->set_bones(bones); surface_tool->set_weights(weights); - surface_tool->add_vertex(v0 + (grests[current_bone_idx].basis.inverse())[j].normalized() * dist * bone_axis_length); + surface_tool->add_vertex(v0 + (skeleton->get_bone_global_rest(current_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); if (j == closest) { continue; @@ -1432,7 +1421,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->add_vertex(v1); surface_tool->set_bones(bones); surface_tool->set_weights(weights); - surface_tool->add_vertex(v1 + (grests[child_bone_idx].basis.inverse())[j].normalized() * dist * bone_axis_length); + surface_tool->add_vertex(v1 + (skeleton->get_bone_global_rest(child_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); if (j == closest) { continue; diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index adb8590246..3fa12233a8 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -145,7 +145,7 @@ void TextureRegionEditor::_region_draw() { } } else if (snap_mode == SNAP_AUTOSLICE) { for (const Rect2 &r : autoslice_cache) { - Vector2 endpoints[4] = { + const Vector2 endpoints[4] = { mtx.basis_xform(r.position), mtx.basis_xform(r.position + Vector2(r.size.x, 0)), mtx.basis_xform(r.position + r.size), diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 71947ae185..4de2f42fe0 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -350,7 +350,7 @@ void TileAtlasView::_draw_alternatives() { bool transposed = tile_data->get_transpose(); // Update the y to max value. - Vector2i offset_pos = current_pos; + Vector2i offset_pos; if (transposed) { offset_pos = (current_pos + Vector2(texture_region_size.y, texture_region_size.x) / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, alternative_id)); y_increment = MAX(y_increment, texture_region_size.x); diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 6c12573cc4..70bcd7e39a 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -2057,7 +2057,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t } drag_last_pos = mb->get_position(); } - } else if (tile_data && tile_data->get_terrain_set() == terrain_set) { + } else if (tile_data->get_terrain_set() == terrain_set) { if (mb->is_ctrl_pressed()) { // Paint terrain set with rect. drag_type = DRAG_TYPE_PAINT_TERRAIN_BITS_RECT; @@ -2387,7 +2387,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi tile_data->set_terrain_set(drag_painted_value); } drag_last_pos = mb->get_position(); - } else if (tile_data && tile_data->get_terrain_set() == terrain_set) { + } else if (tile_data->get_terrain_set() == terrain_set) { // Paint terrain bits. drag_type = DRAG_TYPE_PAINT_TERRAIN_BITS; drag_modified.clear(); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 144697698c..44b18f48fc 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -1695,8 +1695,8 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom(); Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile); Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0); - Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) }; - Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) }; + const Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) }; + const Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) }; bool can_grow[4]; for (int i = 0; i < 4; i++) { can_grow[i] = tile_set_atlas_source->has_room_for_tile(selected.tile + directions[i], tile_set_atlas_source->get_tile_size_in_atlas(selected.tile), tile_set_atlas_source->get_tile_animation_columns(selected.tile), tile_set_atlas_source->get_tile_animation_separation(selected.tile), tile_set_atlas_source->get_tile_animation_frames_count(selected.tile), selected.tile); diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index 21ebcbd655..9a4b14616f 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -394,13 +394,12 @@ void TileSetScenesCollectionSourceEditor::_drop_data_fw(const Point2 &p_point, c if (p_from == scene_tiles_list) { // Handle dropping a texture in the list of atlas resources. - int scene_id = -1; Dictionary d = p_data; Vector<String> files = d["files"]; for (int i = 0; i < files.size(); i++) { Ref<PackedScene> resource = ResourceLoader::load(files[i]); if (resource.is_valid()) { - scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id(); + int scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id(); undo_redo->create_action(TTR("Add a Scene Tile")); undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", resource, scene_id); undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index c4a5ec7a87..dc07ac7c39 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -119,7 +119,7 @@ void VisualShaderGraphPlugin::register_shader(VisualShader *p_shader) { visual_shader = Ref<VisualShader>(p_shader); } -void VisualShaderGraphPlugin::set_connections(List<VisualShader::Connection> &p_connections) { +void VisualShaderGraphPlugin::set_connections(const List<VisualShader::Connection> &p_connections) { connections = p_connections; } @@ -2765,9 +2765,9 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri } if (vsnode->get_output_port_count() > 0 || created_expression_port) { int _from_node = id_to_use; - int _from_slot = 0; if (created_expression_port) { + int _from_slot = 0; undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot); undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot); @@ -2805,9 +2805,9 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri if (vsnode->get_input_port_count() > 0 || created_expression_port) { int _to_node = id_to_use; - int _to_slot = 0; if (created_expression_port) { + int _to_slot = 0; undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot); undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 9f82b2ed7f..8db2cf07f9 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -92,7 +92,7 @@ protected: public: void register_shader(VisualShader *p_visual_shader); - void set_connections(List<VisualShader::Connection> &p_connections); + void set_connections(const List<VisualShader::Connection> &p_connections); void register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node); void register_output_port(int p_id, int p_port, TextureButton *p_button); void register_uniform_name(int p_id, LineEdit *p_uniform_name); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 81df7ee30a..9c745e6a41 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -575,16 +575,16 @@ private: unzClose(pkg); if (failed_files.size()) { - String msg = TTR("The following files failed extraction from package:") + "\n\n"; + String err_msg = TTR("The following files failed extraction from package:") + "\n\n"; for (int i = 0; i < failed_files.size(); i++) { if (i > 15) { - msg += "\nAnd " + itos(failed_files.size() - i) + " more files."; + err_msg += "\nAnd " + itos(failed_files.size() - i) + " more files."; break; } - msg += failed_files[i] + "\n"; + err_msg += failed_files[i] + "\n"; } - dialog_error->set_text(msg); + dialog_error->set_text(err_msg); dialog_error->popup_centered(); } else if (!project_path->get_text().ends_with(".zip")) { @@ -2877,17 +2877,15 @@ ProjectManager::ProjectManager() { Vector2i screen_size = DisplayServer::get_singleton()->screen_get_size(); Vector2i screen_position = DisplayServer::get_singleton()->screen_get_position(); - // Consider the editor display scale. - window_size.x = round((float)window_size.x * scale_factor); - window_size.y = round((float)window_size.y * scale_factor); - - // Make the window centered on the screen. - Vector2i window_position; - window_position.x = screen_position.x + (screen_size.x - window_size.x) / 2; - window_position.y = screen_position.y + (screen_size.y - window_size.y) / 2; + window_size *= scale_factor; DisplayServer::get_singleton()->window_set_size(window_size); - DisplayServer::get_singleton()->window_set_position(window_position); + if (screen_size != Vector2i()) { + Vector2i window_position; + window_position.x = screen_position.x + (screen_size.x - window_size.x) / 2; + window_position.y = screen_position.y + (screen_size.y - window_size.y) / 2; + DisplayServer::get_singleton()->window_set_position(window_position); + } } OS::get_singleton()->set_low_processor_usage_mode(true); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index c63471720b..3e8eb6b4ee 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2999,7 +2999,7 @@ void SceneTreeDock::attach_shader_to_selected(int p_preferred_mode) { shader_create_dialog->popup_centered(); } -void SceneTreeDock::open_shader_dialog(Ref<ShaderMaterial> &p_for_material, int p_preferred_mode) { +void SceneTreeDock::open_shader_dialog(const Ref<ShaderMaterial> &p_for_material, int p_preferred_mode) { selected_shader_material = p_for_material; attach_shader_to_selected(p_preferred_mode); } diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 842995dfe3..77e727b2c8 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -309,7 +309,7 @@ public: void open_script_dialog(Node *p_for_node, bool p_extend); void attach_shader_to_selected(int p_preferred_mode = -1); - void open_shader_dialog(Ref<ShaderMaterial> &p_for_material, int p_preferred_mode = -1); + void open_shader_dialog(const Ref<ShaderMaterial> &p_for_material, int p_preferred_mode = -1); void open_add_child_dialog(); void open_instance_child_dialog(); diff --git a/main/main.cpp b/main/main.cpp index f20ec94fa5..755924929c 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -120,10 +120,10 @@ static RenderingServer *rendering_server = nullptr; static CameraServer *camera_server = nullptr; static XRServer *xr_server = nullptr; static TextServerManager *tsman = nullptr; -static PhysicsServer3D *physics_server = nullptr; -static PhysicsServer2D *physics_2d_server = nullptr; -static NavigationServer3D *navigation_server = nullptr; -static NavigationServer2D *navigation_2d_server = nullptr; +static PhysicsServer3D *physics_server_3d = nullptr; +static PhysicsServer2D *physics_server_2d = nullptr; +static NavigationServer3D *navigation_server_3d = nullptr; +static NavigationServer2D *navigation_server_2d = nullptr; // We error out if setup2() doesn't turn this true static bool _start_success = false; @@ -204,32 +204,32 @@ static String get_full_version_string() { // to have less code in main.cpp. void initialize_physics() { /// 3D Physics Server - physics_server = PhysicsServer3DManager::new_server( + physics_server_3d = PhysicsServer3DManager::new_server( ProjectSettings::get_singleton()->get(PhysicsServer3DManager::setting_property_name)); - if (!physics_server) { + if (!physics_server_3d) { // Physics server not found, Use the default physics - physics_server = PhysicsServer3DManager::new_default_server(); + physics_server_3d = PhysicsServer3DManager::new_default_server(); } - ERR_FAIL_COND(!physics_server); - physics_server->init(); + ERR_FAIL_COND(!physics_server_3d); + physics_server_3d->init(); /// 2D Physics server - physics_2d_server = PhysicsServer2DManager::new_server( + physics_server_2d = PhysicsServer2DManager::new_server( ProjectSettings::get_singleton()->get(PhysicsServer2DManager::setting_property_name)); - if (!physics_2d_server) { + if (!physics_server_2d) { // Physics server not found, Use the default physics - physics_2d_server = PhysicsServer2DManager::new_default_server(); + physics_server_2d = PhysicsServer2DManager::new_default_server(); } - ERR_FAIL_COND(!physics_2d_server); - physics_2d_server->init(); + ERR_FAIL_COND(!physics_server_2d); + physics_server_2d->init(); } void finalize_physics() { - physics_server->finish(); - memdelete(physics_server); + physics_server_3d->finish(); + memdelete(physics_server_3d); - physics_2d_server->finish(); - memdelete(physics_2d_server); + physics_server_2d->finish(); + memdelete(physics_server_2d); } void finalize_display() { @@ -240,18 +240,18 @@ void finalize_display() { } void initialize_navigation_server() { - ERR_FAIL_COND(navigation_server != nullptr); + ERR_FAIL_COND(navigation_server_3d != nullptr); - navigation_server = NavigationServer3DManager::new_default_server(); - navigation_2d_server = memnew(NavigationServer2D); + navigation_server_3d = NavigationServer3DManager::new_default_server(); + navigation_server_2d = memnew(NavigationServer2D); } void finalize_navigation_server() { - memdelete(navigation_server); - navigation_server = nullptr; + memdelete(navigation_server_3d); + navigation_server_3d = nullptr; - memdelete(navigation_2d_server); - navigation_2d_server = nullptr; + memdelete(navigation_server_2d); + navigation_server_2d = nullptr; } //#define DEBUG_INIT diff --git a/modules/csg/editor/csg_gizmos.cpp b/modules/csg/editor/csg_gizmos.cpp index be29810252..4d972e46c6 100644 --- a/modules/csg/editor/csg_gizmos.cpp +++ b/modules/csg/editor/csg_gizmos.cpp @@ -347,14 +347,12 @@ void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_lines(lines, material); p_gizmo->add_collision_segments(lines); - Array csg_meshes = cs->get_meshes(); - if (csg_meshes.size() != 2) { - return; - } - - Ref<Mesh> csg_mesh = csg_meshes[1]; - if (csg_mesh.is_valid()) { - p_gizmo->add_collision_triangles(csg_mesh->generate_triangle_mesh()); + if (cs->is_root_shape()) { + Array csg_meshes = cs->get_meshes(); + Ref<Mesh> csg_mesh = csg_meshes[1]; + if (csg_mesh.is_valid()) { + p_gizmo->add_collision_triangles(csg_mesh->generate_triangle_mesh()); + } } if (p_gizmo->is_selected()) { diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 59254fc3ad..55c7ace938 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1032,7 +1032,13 @@ Error GDScript::load_source_code(const String &p_path) { Error err; Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); if (err) { - ERR_FAIL_COND_V(err, err); + const char *err_name; + if (err < 0 || err >= ERR_MAX) { + err_name = "(invalid error code)"; + } else { + err_name = error_names[err]; + } + ERR_FAIL_COND_V_MSG(err, err, "Attempt to open script '" + p_path + "' resulted in error '" + err_name + "'."); } uint64_t len = f->get_length(); diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 79171cac73..caca7d8ca5 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -262,6 +262,7 @@ class GDScriptInstance : public ScriptInstance { friend class GDScript; friend class GDScriptFunction; friend class GDScriptLambdaCallable; + friend class GDScriptLambdaSelfCallable; friend class GDScriptCompiler; friend struct GDScriptUtilityFunctionsDefinitions; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 01118a6b4f..d346264933 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -2498,12 +2498,17 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a } if (is_self && parser->current_function != nullptr && parser->current_function->is_static && !is_static) { - push_error(vformat(R"*(Cannot call non-static function "%s()" from static function "%s()".)*", p_call->function_name, parser->current_function->identifier->name), p_call); + // Get the parent function above any lambda. + GDScriptParser::FunctionNode *parent_function = parser->current_function; + while (parent_function->source_lambda) { + parent_function = parent_function->source_lambda->parent_function; + } + push_error(vformat(R"*(Cannot call non-static function "%s()" from static function "%s()".)*", p_call->function_name, parent_function->identifier->name), p_call); } else if (!is_self && base_type.is_meta_type && !is_static) { base_type.is_meta_type = false; // For `to_string()`. push_error(vformat(R"*(Cannot call non-static function "%s()" on the class "%s" directly. Make an instance instead.)*", p_call->function_name, base_type.to_string()), p_call); - } else if (is_self && !is_static && !lambda_stack.is_empty()) { - push_error(vformat(R"*(Cannot call non-static function "%s()" from a lambda function.)*", p_call->function_name), p_call); + } else if (is_self && !is_static) { + mark_lambda_use_self(); } call_type = return_type; @@ -2636,10 +2641,10 @@ void GDScriptAnalyzer::reduce_get_node(GDScriptParser::GetNodeNode *p_get_node) if (!ClassDB::is_parent_class(parser->current_class->base_type.native_type, result.native_type)) { push_error(R"*(Cannot use shorthand "get_node()" notation ("$") on a class that isn't a node.)*", p_get_node); - } else if (!lambda_stack.is_empty()) { - push_error(R"*(Cannot use shorthand "get_node()" notation ("$") inside a lambda. Use a captured variable instead.)*", p_get_node); } + mark_lambda_use_self(); + p_get_node->set_datatype(result); } @@ -2854,21 +2859,25 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod MethodBind *getter = ClassDB::get_method(native, getter_name); if (getter != nullptr) { p_identifier->set_datatype(type_from_property(getter->get_return_info())); + p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE; } return; } if (ClassDB::get_method_info(native, name, &method_info)) { // Method is callable. p_identifier->set_datatype(make_callable_type(method_info)); + p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE; return; } if (ClassDB::get_signal(native, name, &method_info)) { // Signal is a type too. p_identifier->set_datatype(make_signal_type(method_info)); + p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE; return; } if (ClassDB::has_enum(native, name)) { p_identifier->set_datatype(make_native_enum_type(native, name)); + p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT; return; } bool valid = false; @@ -2877,6 +2886,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod p_identifier->is_constant = true; p_identifier->reduced_value = int_constant; p_identifier->set_datatype(type_from_variant(int_constant, p_identifier)); + p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT; return; } } @@ -2927,7 +2937,11 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident p_identifier->reduced_value = p_identifier->constant_source->initializer->reduced_value; found_source = true; break; + case GDScriptParser::IdentifierNode::INHERITED_VARIABLE: + mark_lambda_use_self(); + break; case GDScriptParser::IdentifierNode::MEMBER_VARIABLE: + mark_lambda_use_self(); p_identifier->variable_source->usages++; [[fallthrough]]; case GDScriptParser::IdentifierNode::LOCAL_VARIABLE: @@ -2958,18 +2972,37 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident } if (found_source) { - // If the identifier is local, check if it's any kind of capture by comparing their source function. - // Only capture locals and members and enum values. Constants are still accessible from the lambda using the script reference. - if (p_identifier->source == GDScriptParser::IdentifierNode::UNDEFINED_SOURCE || p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_CONSTANT || lambda_stack.is_empty()) { - return; + if ((p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_VARIABLE || p_identifier->source == GDScriptParser::IdentifierNode::INHERITED_VARIABLE) && parser->current_function && parser->current_function->is_static) { + // Get the parent function above any lambda. + GDScriptParser::FunctionNode *parent_function = parser->current_function; + while (parent_function->source_lambda) { + parent_function = parent_function->source_lambda->parent_function; + } + push_error(vformat(R"*(Cannot access instance variable "%s" from the static function "%s()".)*", p_identifier->name, parent_function->identifier->name), p_identifier); } - GDScriptParser::FunctionNode *function_test = lambda_stack.back()->get()->function; - while (function_test != nullptr && function_test != p_identifier->source_function && function_test->source_lambda != nullptr && !function_test->source_lambda->captures_indices.has(p_identifier->name)) { - function_test->source_lambda->captures_indices[p_identifier->name] = function_test->source_lambda->captures.size(); - function_test->source_lambda->captures.push_back(p_identifier); - function_test = function_test->source_lambda->parent_function; + if (!lambda_stack.is_empty()) { + // If the identifier is a member variable (including the native class properties), we consider the lambda to be using `self`, so we keep a reference to the current instance. + if (p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_VARIABLE || p_identifier->source == GDScriptParser::IdentifierNode::INHERITED_VARIABLE) { + mark_lambda_use_self(); + return; // No need to capture. + } + // If the identifier is local, check if it's any kind of capture by comparing their source function. + // Only capture locals and enum values. Constants are still accessible from the lambda using the script reference. If not, this method is done. + if (p_identifier->source == GDScriptParser::IdentifierNode::UNDEFINED_SOURCE || p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_CONSTANT) { + return; + } + + GDScriptParser::FunctionNode *function_test = lambda_stack.back()->get()->function; + // Make sure we aren't capturing variable in the same lambda. + // This also add captures for nested lambdas. + while (function_test != nullptr && function_test != p_identifier->source_function && function_test->source_lambda != nullptr && !function_test->source_lambda->captures_indices.has(p_identifier->name)) { + function_test->source_lambda->captures_indices[p_identifier->name] = function_test->source_lambda->captures.size(); + function_test->source_lambda->captures.push_back(p_identifier); + function_test = function_test->source_lambda->parent_function; + } } + return; } @@ -3149,6 +3182,7 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) { void GDScriptAnalyzer::reduce_self(GDScriptParser::SelfNode *p_self) { p_self->is_constant = false; p_self->set_datatype(type_from_metatype(parser->current_class->get_datatype())); + mark_lambda_use_self(); } void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscript) { @@ -3159,6 +3193,12 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri reduce_identifier(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base), true); } else { reduce_expression(p_subscript->base); + + if (p_subscript->base->type == GDScriptParser::Node::ARRAY) { + const_fold_array(static_cast<GDScriptParser::ArrayNode *>(p_subscript->base)); + } else if (p_subscript->base->type == GDScriptParser::Node::DICTIONARY) { + const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(p_subscript->base)); + } } GDScriptParser::DataType result_type; @@ -3476,6 +3516,13 @@ void GDScriptAnalyzer::const_fold_array(GDScriptParser::ArrayNode *p_array) { for (int i = 0; i < p_array->elements.size(); i++) { GDScriptParser::ExpressionNode *element = p_array->elements[i]; + + if (element->type == GDScriptParser::Node::ARRAY) { + const_fold_array(static_cast<GDScriptParser::ArrayNode *>(element)); + } else if (element->type == GDScriptParser::Node::DICTIONARY) { + const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element)); + } + all_is_constant = all_is_constant && element->is_constant; if (!all_is_constant) { return; @@ -3496,6 +3543,13 @@ void GDScriptAnalyzer::const_fold_dictionary(GDScriptParser::DictionaryNode *p_d for (int i = 0; i < p_dictionary->elements.size(); i++) { const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i]; + + if (element.value->type == GDScriptParser::Node::ARRAY) { + const_fold_array(static_cast<GDScriptParser::ArrayNode *>(element.value)); + } else if (element.value->type == GDScriptParser::Node::DICTIONARY) { + const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element.value)); + } + all_is_constant = all_is_constant && element.key->is_constant && element.value->is_constant; if (!all_is_constant) { return; @@ -4121,6 +4175,12 @@ void GDScriptAnalyzer::mark_node_unsafe(const GDScriptParser::Node *p_node) { #endif } +void GDScriptAnalyzer::mark_lambda_use_self() { + for (GDScriptParser::LambdaNode *lambda : lambda_stack) { + lambda->use_self = true; + } +} + bool GDScriptAnalyzer::class_exists(const StringName &p_class) const { return ClassDB::class_exists(p_class) && ClassDB::is_class_exposed(p_class); } diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 7b8883e1d3..519e1975c4 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -42,7 +42,7 @@ class GDScriptAnalyzer { HashMap<String, Ref<GDScriptParserRef>> depended_parsers; const GDScriptParser::EnumNode *current_enum = nullptr; - List<const GDScriptParser::LambdaNode *> lambda_stack; + List<GDScriptParser::LambdaNode *> lambda_stack; // Tests for detecting invalid overloading of script members static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node); @@ -115,6 +115,7 @@ class GDScriptAnalyzer { bool is_type_compatible(const GDScriptParser::DataType &p_target, const GDScriptParser::DataType &p_source, bool p_allow_implicit_conversion = false, const GDScriptParser::Node *p_source_node = nullptr); void push_error(const String &p_message, const GDScriptParser::Node *p_origin); void mark_node_unsafe(const GDScriptParser::Node *p_node); + void mark_lambda_use_self(); bool class_exists(const StringName &p_class) const; Ref<GDScriptParserRef> get_parser_for(const String &p_path); #ifdef DEBUG_ENABLED diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index a7e25f5aab..e72069bcd5 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -1211,8 +1211,8 @@ void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_targ append(p_function_name); } -void GDScriptByteCodeGenerator::write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures) { - append(GDScriptFunction::OPCODE_CREATE_LAMBDA, 1 + p_captures.size()); +void GDScriptByteCodeGenerator::write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures, bool p_use_self) { + append(p_use_self ? GDScriptFunction::OPCODE_CREATE_SELF_LAMBDA : GDScriptFunction::OPCODE_CREATE_LAMBDA, 1 + p_captures.size()); for (int i = 0; i < p_captures.size(); i++) { append(p_captures[i]); } diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index 222ae13390..0503f66161 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -470,7 +470,7 @@ public: virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override; virtual void write_call_self_async(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override; virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override; - virtual void write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures) override; + virtual void write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures, bool p_use_self) override; virtual void write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) override; virtual void write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) override; virtual void write_construct_typed_array(const Address &p_target, const GDScriptDataType &p_element_type, const Vector<Address> &p_arguments) override; diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h index 3d42ce06c0..326b66a295 100644 --- a/modules/gdscript/gdscript_codegen.h +++ b/modules/gdscript/gdscript_codegen.h @@ -131,7 +131,7 @@ public: virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0; virtual void write_call_self_async(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0; virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0; - virtual void write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures) = 0; + virtual void write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures, bool p_use_self) = 0; virtual void write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) = 0; virtual void write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) = 0; virtual void write_construct_typed_array(const Address &p_target, const GDScriptDataType &p_element_type, const Vector<Address> &p_arguments) = 0; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 0138147fcc..225c2d0d45 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1197,7 +1197,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code return GDScriptCodeGenerator::Address(); } - gen->write_lambda(result, function, captures); + gen->write_lambda(result, function, captures, lambda->use_self); for (int i = 0; i < captures.size(); i++) { if (captures[i].mode == GDScriptCodeGenerator::Address::TEMPORARY) { diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index 74090d0aa9..dc114f2eff 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -792,6 +792,25 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { incr = 3 + captures_count; } break; + case OPCODE_CREATE_SELF_LAMBDA: { + int captures_count = _code_ptr[ip + 1 + instr_var_args]; + GDScriptFunction *lambda = _lambdas_ptr[_code_ptr[ip + 2 + instr_var_args]]; + + text += DADDR(1 + captures_count); + text += "create self lambda from "; + text += lambda->name.operator String(); + text += "function, captures ("; + + for (int i = 0; i < captures_count; i++) { + if (i > 0) { + text += ", "; + } + text += DADDR(1 + i); + } + text += ")"; + + incr = 3 + captures_count; + } break; case OPCODE_JUMP: { text += "jump "; text += itos(_code_ptr[ip + 1]); diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index d07a167ca2..ba0d51c5cc 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -299,6 +299,7 @@ public: OPCODE_AWAIT, OPCODE_AWAIT_RESUME, OPCODE_CREATE_LAMBDA, + OPCODE_CREATE_SELF_LAMBDA, OPCODE_JUMP, OPCODE_JUMP_IF, OPCODE_JUMP_IF_NOT, diff --git a/modules/gdscript/gdscript_lambda_callable.cpp b/modules/gdscript/gdscript_lambda_callable.cpp index baf93e1098..c43fa12c8c 100644 --- a/modules/gdscript/gdscript_lambda_callable.cpp +++ b/modules/gdscript/gdscript_lambda_callable.cpp @@ -93,3 +93,81 @@ GDScriptLambdaCallable::GDScriptLambdaCallable(Ref<GDScript> p_script, GDScriptF h = (uint32_t)hash_djb2_one_64((uint64_t)this); } + +bool GDScriptLambdaSelfCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) { + // Lambda callables are only compared by reference. + return p_a == p_b; +} + +bool GDScriptLambdaSelfCallable::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) { + // Lambda callables are only compared by reference. + return p_a < p_b; +} + +uint32_t GDScriptLambdaSelfCallable::hash() const { + return h; +} + +String GDScriptLambdaSelfCallable::get_as_text() const { + if (function->get_name() != StringName()) { + return function->get_name().operator String() + "(lambda)"; + } + return "(anonymous lambda)"; +} + +CallableCustom::CompareEqualFunc GDScriptLambdaSelfCallable::get_compare_equal_func() const { + return compare_equal; +} + +CallableCustom::CompareLessFunc GDScriptLambdaSelfCallable::get_compare_less_func() const { + return compare_less; +} + +ObjectID GDScriptLambdaSelfCallable::get_object() const { + return object->get_instance_id(); +} + +void GDScriptLambdaSelfCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { +#ifdef DEBUG_ENABLED + if (object->get_script_instance() == nullptr || object->get_script_instance()->get_language() != GDScriptLanguage::get_singleton()) { + ERR_PRINT("Trying to call a lambda with an invalid instance."); + r_call_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; + return; + } +#endif + + int captures_amount = captures.size(); + + if (captures_amount > 0) { + Vector<const Variant *> args; + args.resize(p_argcount + captures_amount); + for (int i = 0; i < captures_amount; i++) { + args.write[i] = &captures[i]; + } + for (int i = 0; i < p_argcount; i++) { + args.write[i + captures_amount] = p_arguments[i]; + } + + r_return_value = function->call(static_cast<GDScriptInstance *>(object->get_script_instance()), args.ptrw(), args.size(), r_call_error); + r_call_error.argument -= captures_amount; + } else { + r_return_value = function->call(static_cast<GDScriptInstance *>(object->get_script_instance()), p_arguments, p_argcount, r_call_error); + } +} + +GDScriptLambdaSelfCallable::GDScriptLambdaSelfCallable(Ref<RefCounted> p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures) { + reference = p_self; + object = p_self.ptr(); + function = p_function; + captures = p_captures; + + h = (uint32_t)hash_djb2_one_64((uint64_t)this); +} + +GDScriptLambdaSelfCallable::GDScriptLambdaSelfCallable(Object *p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures) { + object = p_self; + function = p_function; + captures = p_captures; + + h = (uint32_t)hash_djb2_one_64((uint64_t)this); +} diff --git a/modules/gdscript/gdscript_lambda_callable.h b/modules/gdscript/gdscript_lambda_callable.h index f6a54a1a2f..248176e32c 100644 --- a/modules/gdscript/gdscript_lambda_callable.h +++ b/modules/gdscript/gdscript_lambda_callable.h @@ -62,4 +62,29 @@ public: virtual ~GDScriptLambdaCallable() = default; }; +// Lambda callable that references a particular object, so it can use `self` in the body. +class GDScriptLambdaSelfCallable : public CallableCustom { + GDScriptFunction *function = nullptr; + Ref<RefCounted> reference; // For objects that are RefCounted, keep a reference. + Object *object = nullptr; // For non RefCounted objects, use a direct pointer. + uint32_t h; + + Vector<Variant> captures; + + static bool compare_equal(const CallableCustom *p_a, const CallableCustom *p_b); + static bool compare_less(const CallableCustom *p_a, const CallableCustom *p_b); + +public: + uint32_t hash() const override; + String get_as_text() const override; + CompareEqualFunc get_compare_equal_func() const override; + CompareLessFunc get_compare_less_func() const override; + ObjectID get_object() const override; + void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; + + GDScriptLambdaSelfCallable(Ref<RefCounted> p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures); + GDScriptLambdaSelfCallable(Object *p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures); + virtual ~GDScriptLambdaSelfCallable() = default; +}; + #endif // GDSCRIPT_LAMBDA_CALLABLE diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 67d778f932..67f6b61f14 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2200,9 +2200,6 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_self(ExpressionNode *p_pre if (current_function && current_function->is_static) { push_error(R"(Cannot use "self" inside a static function.)"); } - if (in_lambda) { - push_error(R"(Cannot use "self" inside a lambda.)"); - } SelfNode *self = alloc_node<SelfNode>(); self->current_class = current_class; return self; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 487b7d0449..10474db02f 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -767,6 +767,7 @@ public: LOCAL_BIND, // Pattern bind. MEMBER_VARIABLE, MEMBER_CONSTANT, + INHERITED_VARIABLE, }; Source source = UNDEFINED_SOURCE; @@ -800,6 +801,7 @@ public: FunctionNode *parent_function = nullptr; Vector<IdentifierNode *> captures; Map<StringName, int> captures_indices; + bool use_self = false; bool has_name() const { return function && function->identifier; diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 2afb850c32..e28dd26c28 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -306,6 +306,7 @@ void (*type_init_function_table[])(Variant *) = { &&OPCODE_AWAIT, \ &&OPCODE_AWAIT_RESUME, \ &&OPCODE_CREATE_LAMBDA, \ + &&OPCODE_CREATE_SELF_LAMBDA, \ &&OPCODE_JUMP, \ &&OPCODE_JUMP_IF, \ &&OPCODE_JUMP_IF_NOT, \ @@ -2277,6 +2278,41 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } DISPATCH_OPCODE; + OPCODE(OPCODE_CREATE_SELF_LAMBDA) { + CHECK_SPACE(2 + instr_arg_count); + + GD_ERR_BREAK(p_instance == nullptr); + + ip += instr_arg_count; + + int captures_count = _code_ptr[ip + 1]; + GD_ERR_BREAK(captures_count < 0); + + int lambda_index = _code_ptr[ip + 2]; + GD_ERR_BREAK(lambda_index < 0 || lambda_index >= _lambdas_count); + GDScriptFunction *lambda = _lambdas_ptr[lambda_index]; + + Vector<Variant> captures; + captures.resize(captures_count); + for (int i = 0; i < captures_count; i++) { + GET_INSTRUCTION_ARG(arg, i); + captures.write[i] = *arg; + } + + GDScriptLambdaSelfCallable *callable; + if (Object::cast_to<RefCounted>(p_instance->owner)) { + callable = memnew(GDScriptLambdaSelfCallable(Ref<RefCounted>(Object::cast_to<RefCounted>(p_instance->owner)), lambda, captures)); + } else { + callable = memnew(GDScriptLambdaSelfCallable(p_instance->owner, lambda, captures)); + } + + GET_INSTRUCTION_ARG(result, captures_count); + *result = Callable(callable); + + ip += 3; + } + DISPATCH_OPCODE; + OPCODE(OPCODE_JUMP) { CHECK_SPACE(2); int to = _code_ptr[ip + 1]; diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out index 015ad756f8..6f7f0783f0 100644 --- a/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out @@ -1,2 +1,2 @@ GDTEST_ANALYZER_ERROR -Invalid index type "bool" for a base of type "Array". +Cannot get index "true" from "[0, 1]". diff --git a/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.gd b/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.gd new file mode 100644 index 0000000000..cc78309ae4 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.gd @@ -0,0 +1,58 @@ +# https://github.com/godotengine/godot/issues/50285 + +@warning_ignore(unused_local_constant) +func test(): + const CONST_INNER_DICTIONARY = { "key": true } + const CONST_NESTED_DICTIONARY_OLD_WORKAROUND = { + "key1": "value1", + "key2": CONST_INNER_DICTIONARY + } + # All of these should be valid + const CONST_NESTED_DICTIONARY = { + "key1": "value1", + "key2": { "key": true } + } + + + const CONST_DICTIONARY_WITH_ARRAY = { + "key1": [1,2,3,4] + } + + const CONST_NESTED_ARRAY = [[],[2],[1,2,3]] + const CONST_ARRAY_WITH_DICT = [{"key1": 3}, {"key2": 5}] + + const THREE_DIMENSIONAL_ARRAY = [[[],[],[]],[[],[],[]],[[],[],[]]] + const MANY_NESTED_DICT = { + "key1": { + "key11": { + "key111": {}, + "key112": {}, + }, + "key12": { + "key121": {}, + "key122": {}, + }, + }, + "key2": { + "key21": { + "key211": {}, + "key212": {}, + }, + "key22": { + "key221": {}, + "key222": {}, + }, + } + } + + + const CONST_ARRAY_ACCESS = [1,2,3][0] + const CONST_DICT_ACCESS = {"key1": 5}["key1"] + + const CONST_ARRAY_NESTED_ACCESS = [[1,2,3],[4,5,6],[8,9,10]][0][1] + const CONST_DICT_NESTED_ACCESS = {"key1": {"key2": 1}}["key1"]["key2"] + + print(CONST_ARRAY_ACCESS) + print(CONST_DICT_ACCESS) + print(CONST_ARRAY_NESTED_ACCESS) + print(CONST_DICT_NESTED_ACCESS) diff --git a/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.out b/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.out new file mode 100644 index 0000000000..5883fc5c18 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.out @@ -0,0 +1,5 @@ +GDTEST_OK +1 +5 +2 +1 diff --git a/modules/gdscript/tests/scripts/runtime/features/lambda_use_self.gd b/modules/gdscript/tests/scripts/runtime/features/lambda_use_self.gd new file mode 100644 index 0000000000..3d063869ab --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/lambda_use_self.gd @@ -0,0 +1,23 @@ +var member = "foo" + +func bar(): + print("bar") + +func test(): + var lambda1 = func(): + print(member) + lambda1.call() + + var lambda2 = func(): + var nested = func(): + print(member) + nested.call() + lambda2.call() + + var lambda3 = func(): + bar() + lambda3.call() + + var lambda4 = func(): + return self + print(lambda4.call() == self) diff --git a/modules/gdscript/tests/scripts/runtime/features/lambda_use_self.out b/modules/gdscript/tests/scripts/runtime/features/lambda_use_self.out new file mode 100644 index 0000000000..53d602b234 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/lambda_use_self.out @@ -0,0 +1,5 @@ +GDTEST_OK +foo +foo +bar +true diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp index 23a7b7fed6..95db1c0965 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp +++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp @@ -64,9 +64,12 @@ SceneExporterGLTFPlugin::SceneExporterGLTFPlugin() { file_export_lib->clear_filters(); file_export_lib->add_filter("*.glb"); file_export_lib->add_filter("*.gltf"); - file_export_lib->set_title(TTR("Export Mesh GLTF2")); - String gltf_scene_name = TTR("Export GLTF..."); - add_tool_menu_item(gltf_scene_name, callable_mp(this, &SceneExporterGLTFPlugin::convert_scene_to_gltf2)); + file_export_lib->set_title(TTR("Export Scene to glTF 2.0 File")); + + PopupMenu *menu = get_export_as_menu(); + int idx = menu->get_item_count(); + menu->add_item(TTR("glTF 2.0 Scene...")); + menu->set_item_metadata(idx, callable_mp(this, &SceneExporterGLTFPlugin::convert_scene_to_gltf2)); } void SceneExporterGLTFPlugin::_gltf2_dialog_action(String p_file) { diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 784733aba2..281f62c4ad 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -65,6 +65,7 @@ #include "scene/3d/node_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/importer_mesh.h" +#include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/multimesh.h" #include "scene/resources/surface_tool.h" @@ -80,6 +81,7 @@ // FIXME: Hardcoded to avoid editor dependency. #define GLTF_IMPORT_USE_NAMED_SKIN_BINDS 16 +#define GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS 32 #include <stdio.h> #include <stdlib.h> @@ -2918,30 +2920,32 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { } } - //just add it - Ref<BaseMaterial3D> mat; - if (p.has("material")) { - const int material = p["material"]; - ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT); - Ref<BaseMaterial3D> mat3d = state->materials[material]; - ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT); - if (has_vertex_color) { - mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - } - mat = mat3d; + String mat_name; + if (!state->discard_meshes_and_materials) { + if (p.has("material")) { + const int material = p["material"]; + ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT); + Ref<BaseMaterial3D> mat3d = state->materials[material]; + ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT); + if (has_vertex_color) { + mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + } + mat = mat3d; - } else { - Ref<StandardMaterial3D> mat3d; - mat3d.instantiate(); - if (has_vertex_color) { - mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + } else { + Ref<StandardMaterial3D> mat3d; + mat3d.instantiate(); + if (has_vertex_color) { + mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + } + mat = mat3d; } - mat = mat3d; + ERR_FAIL_NULL_V(mat, ERR_FILE_CORRUPT); + mat_name = mat->get_name(); } - ERR_FAIL_NULL_V(mat, ERR_FILE_CORRUPT); import_mesh->add_surface(primitive, array, morphs, - Dictionary(), mat, mat->get_name(), flags); + Dictionary(), mat, mat_name, flags); } Vector<float> blend_weights; @@ -6908,8 +6912,8 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) { Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32_t p_flags, int32_t p_bake_fps) { ERR_FAIL_COND_V(state.is_null(), FAILED); - state->use_named_skin_binds = - p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; + state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; + state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; _convert_scene_node(state, p_node, -1, -1); if (!state->buffers.size()) { @@ -6929,6 +6933,7 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire Error err = FAILED; state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; + state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; Ref<FileAccessMemory> file_access; file_access.instantiate(); @@ -6968,20 +6973,22 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_sear ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - /* PARSE IMAGES */ - err = _parse_images(state, p_search_path); + if (!state->discard_meshes_and_materials) { + /* PARSE IMAGES */ + err = _parse_images(state, p_search_path); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - /* PARSE TEXTURES */ - err = _parse_textures(state); + /* PARSE TEXTURES */ + err = _parse_textures(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - /* PARSE TEXTURES */ - err = _parse_materials(state); + /* PARSE TEXTURES */ + err = _parse_materials(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + } /* PARSE SKINS */ err = _parse_skins(state); @@ -7033,6 +7040,7 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint } r_state->filename = p_path.get_file().get_basename(); r_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; + r_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; Error err; Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN); diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 3f638bbca5..6ead2f69c3 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -305,3 +305,11 @@ AnimationPlayer *GLTFState::get_animation_player(int idx) { ERR_FAIL_INDEX_V(idx, animation_players.size(), nullptr); return animation_players[idx]; } + +void GLTFState::set_discard_meshes_and_materials(bool p_discard_meshes_and_materials) { + discard_meshes_and_materials = p_discard_meshes_and_materials; +} + +bool GLTFState::get_discard_meshes_and_materials() { + return discard_meshes_and_materials; +} diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index d03434d2f1..42ca079f1c 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -62,6 +62,7 @@ class GLTFState : public Resource { Vector<uint8_t> glb_data; bool use_named_skin_binds = false; + bool discard_meshes_and_materials = false; Vector<Ref<GLTFNode>> nodes; Vector<Vector<uint8_t>> buffers; @@ -112,6 +113,9 @@ public: bool get_use_named_skin_binds(); void set_use_named_skin_binds(bool p_use_named_skin_binds); + bool get_discard_meshes_and_materials(); + void set_discard_meshes_and_materials(bool p_discard_meshes_and_materials); + Array get_nodes(); void set_nodes(Array p_nodes); diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp index ddc2e945a7..1296a4587c 100644 --- a/modules/mbedtls/packet_peer_mbed_dtls.cpp +++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp @@ -115,7 +115,7 @@ Error PacketPeerMbedDTLS::_do_handshake() { } Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_validate_certs, const String &p_for_hostname, Ref<X509Certificate> p_ca_certs) { - ERR_FAIL_COND_V(!p_base.is_valid() || !p_base->is_connected_to_host(), ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!p_base.is_valid() || !p_base->is_socket_connected(), ERR_INVALID_PARAMETER); base = p_base; int ret = 0; diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index ca4fc4f628..d16d41b438 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -40,43 +40,43 @@ /// an instance of that struct with the submitted parameters. /// Then, that struct is stored in an array; the `sync` function consume that array. -#define COMMAND_1(F_NAME, T_0, D_0) \ - struct MERGE(F_NAME, _command) : public SetCommand { \ - T_0 d_0; \ - MERGE(F_NAME, _command) \ - (T_0 p_d_0) : \ - d_0(p_d_0) {} \ - virtual void exec(GodotNavigationServer *server) { \ - server->MERGE(_cmd_, F_NAME)(d_0); \ - } \ - }; \ - void GodotNavigationServer::F_NAME(T_0 D_0) const { \ - auto cmd = memnew(MERGE(F_NAME, _command)( \ - D_0)); \ - add_command(cmd); \ - } \ +#define COMMAND_1(F_NAME, T_0, D_0) \ + struct MERGE(F_NAME, _command) : public SetCommand { \ + T_0 d_0; \ + MERGE(F_NAME, _command) \ + (T_0 p_d_0) : \ + d_0(p_d_0) {} \ + virtual void exec(GodotNavigationServer *server) override { \ + server->MERGE(_cmd_, F_NAME)(d_0); \ + } \ + }; \ + void GodotNavigationServer::F_NAME(T_0 D_0) const { \ + auto cmd = memnew(MERGE(F_NAME, _command)( \ + D_0)); \ + add_command(cmd); \ + } \ void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0) -#define COMMAND_2(F_NAME, T_0, D_0, T_1, D_1) \ - struct MERGE(F_NAME, _command) : public SetCommand { \ - T_0 d_0; \ - T_1 d_1; \ - MERGE(F_NAME, _command) \ - ( \ - T_0 p_d_0, \ - T_1 p_d_1) : \ - d_0(p_d_0), \ - d_1(p_d_1) {} \ - virtual void exec(GodotNavigationServer *server) { \ - server->MERGE(_cmd_, F_NAME)(d_0, d_1); \ - } \ - }; \ - void GodotNavigationServer::F_NAME(T_0 D_0, T_1 D_1) const { \ - auto cmd = memnew(MERGE(F_NAME, _command)( \ - D_0, \ - D_1)); \ - add_command(cmd); \ - } \ +#define COMMAND_2(F_NAME, T_0, D_0, T_1, D_1) \ + struct MERGE(F_NAME, _command) : public SetCommand { \ + T_0 d_0; \ + T_1 d_1; \ + MERGE(F_NAME, _command) \ + ( \ + T_0 p_d_0, \ + T_1 p_d_1) : \ + d_0(p_d_0), \ + d_1(p_d_1) {} \ + virtual void exec(GodotNavigationServer *server) override { \ + server->MERGE(_cmd_, F_NAME)(d_0, d_1); \ + } \ + }; \ + void GodotNavigationServer::F_NAME(T_0 D_0, T_1 D_1) const { \ + auto cmd = memnew(MERGE(F_NAME, _command)( \ + D_0, \ + D_1)); \ + add_command(cmd); \ + } \ void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1) #define COMMAND_4(F_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3) \ @@ -95,7 +95,7 @@ d_1(p_d_1), \ d_2(p_d_2), \ d_3(p_d_3) {} \ - virtual void exec(GodotNavigationServer *server) { \ + virtual void exec(GodotNavigationServer *server) override { \ server->MERGE(_cmd_, F_NAME)(d_0, d_1, d_2, d_3); \ } \ }; \ diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index a6df6bb72c..cbc0adc574 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -30,7 +30,6 @@ #include "nav_map.h" -#include "core/os/threaded_array_processor.h" #include "nav_region.h" #include "rvo_agent.h" @@ -674,7 +673,10 @@ void NavMap::compute_single_step(uint32_t index, RvoAgent **agent) { void NavMap::step(real_t p_deltatime) { deltatime = p_deltatime; if (controlled_agents.size() > 0) { - thread_process_array( + if (step_work_pool.get_thread_count() == 0) { + step_work_pool.init(); + } + step_work_pool.do_work( controlled_agents.size(), this, &NavMap::compute_single_step, @@ -719,3 +721,10 @@ void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys } } } + +NavMap::NavMap() { +} + +NavMap::~NavMap() { + step_work_pool.finish(); +} diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index f46297a7ce..5232e42bed 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -35,6 +35,7 @@ #include "core/math/math_defs.h" #include "core/templates/map.h" +#include "core/templates/thread_work_pool.h" #include "nav_utils.h" #include <KdTree.h> @@ -80,8 +81,12 @@ class NavMap : public NavRid { /// Change the id each time the map is updated. uint32_t map_update_id = 0; + /// Pooled threads for computing steps + ThreadWorkPool step_work_pool; + public: - NavMap() {} + NavMap(); + ~NavMap(); void set_up(Vector3 p_up); Vector3 get_up() const { diff --git a/modules/noise/SCsub b/modules/noise/SCsub index 3e8395b9b1..1430aa0c4e 100644 --- a/modules/noise/SCsub +++ b/modules/noise/SCsub @@ -27,6 +27,7 @@ env.modules_sources += thirdparty_obj module_obj = [] env_noise.add_source_files(module_obj, "*.cpp") +env_noise.add_source_files(module_obj, "editor/*.cpp") env.modules_sources += module_obj # Needed to force rebuilding the module files when the thirdparty library is updated. diff --git a/modules/noise/doc_classes/FastNoiseLite.xml b/modules/noise/doc_classes/FastNoiseLite.xml index b6d91850c4..6ca4ba2d46 100644 --- a/modules/noise/doc_classes/FastNoiseLite.xml +++ b/modules/noise/doc_classes/FastNoiseLite.xml @@ -16,12 +16,9 @@ <member name="cellular_jitter" type="float" setter="set_cellular_jitter" getter="get_cellular_jitter" default="0.45"> Maximum distance a point can move off of its grid position. Set to [code]0[/code] for an even grid. </member> - <member name="cellular_return_type" type="int" setter="set_cellular_return_type" getter="get_cellular_return_type" enum="FastNoiseLite.CellularReturnType" default="0"> + <member name="cellular_return_type" type="int" setter="set_cellular_return_type" getter="get_cellular_return_type" enum="FastNoiseLite.CellularReturnType" default="1"> Return type from cellular noise calculations. See [enum CellularReturnType]. </member> - <member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp"> - A [Gradient] which is used to map the luminance of each pixel to a color value. - </member> <member name="domain_warp_amplitude" type="float" setter="set_domain_warp_amplitude" getter="get_domain_warp_amplitude" default="30.0"> Sets the maximum warp distance from the origin. </member> @@ -69,9 +66,6 @@ <member name="frequency" type="float" setter="set_frequency" getter="get_frequency" default="0.01"> The frequency for all noise types. Low frequency results in smooth noise while high frequency results in rougher, more granular noise. </member> - <member name="in_3d_space" type="bool" setter="set_in_3d_space" getter="is_in_3d_space" default="false"> - Determines whether the noise image returned by [method Noise.get_image] is calculated in 3d space. May result in reduced contrast. - </member> <member name="noise_type" type="int" setter="set_noise_type" getter="get_noise_type" enum="FastNoiseLite.NoiseType" default="1"> The noise algorithm used. See [enum NoiseType]. </member> diff --git a/modules/noise/doc_classes/Noise.xml b/modules/noise/doc_classes/Noise.xml index db0dec18d2..5af204575c 100644 --- a/modules/noise/doc_classes/Noise.xml +++ b/modules/noise/doc_classes/Noise.xml @@ -11,23 +11,24 @@ <tutorials> </tutorials> <methods> - <method name="get_image"> + <method name="get_image" qualifiers="const"> <return type="Image" /> <argument index="0" name="width" type="int" /> <argument index="1" name="height" type="int" /> <argument index="2" name="invert" type="bool" default="false" /> + <argument index="3" name="in_3d_space" type="bool" default="false" /> <description> Returns a 2D [Image] noise image. </description> </method> - <method name="get_noise_1d"> + <method name="get_noise_1d" qualifiers="const"> <return type="float" /> <argument index="0" name="x" type="float" /> <description> Returns the 1D noise value at the given (x) coordinate. </description> </method> - <method name="get_noise_2d"> + <method name="get_noise_2d" qualifiers="const"> <return type="float" /> <argument index="0" name="x" type="float" /> <argument index="1" name="y" type="float" /> @@ -35,14 +36,14 @@ Returns the 2D noise value at the given position. </description> </method> - <method name="get_noise_2dv"> + <method name="get_noise_2dv" qualifiers="const"> <return type="float" /> <argument index="0" name="v" type="Vector2" /> <description> Returns the 2D noise value at the given position. </description> </method> - <method name="get_noise_3d"> + <method name="get_noise_3d" qualifiers="const"> <return type="float" /> <argument index="0" name="x" type="float" /> <argument index="1" name="y" type="float" /> @@ -51,19 +52,20 @@ Returns the 3D noise value at the given position. </description> </method> - <method name="get_noise_3dv"> + <method name="get_noise_3dv" qualifiers="const"> <return type="float" /> <argument index="0" name="v" type="Vector3" /> <description> Returns the 3D noise value at the given position. </description> </method> - <method name="get_seamless_image"> + <method name="get_seamless_image" qualifiers="const"> <return type="Image" /> <argument index="0" name="width" type="int" /> <argument index="1" name="height" type="int" /> <argument index="2" name="invert" type="bool" default="false" /> - <argument index="3" name="skirt" type="float" default="0.1" /> + <argument index="3" name="in_3d_space" type="bool" default="false" /> + <argument index="4" name="skirt" type="float" default="0.1" /> <description> Returns a seamless 2D [Image] noise image. </description> diff --git a/modules/noise/doc_classes/NoiseTexture.xml b/modules/noise/doc_classes/NoiseTexture.xml index 63630eccde..62a223b387 100644 --- a/modules/noise/doc_classes/NoiseTexture.xml +++ b/modules/noise/doc_classes/NoiseTexture.xml @@ -24,9 +24,20 @@ <member name="bump_strength" type="float" setter="set_bump_strength" getter="get_bump_strength" default="8.0"> Strength of the bump maps used in this texture. A higher value will make the bump maps appear larger while a lower value will make them appear softer. </member> + <member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp"> + A [Gradient] which is used to map the luminance of each pixel to a color value. + </member> + <member name="generate_mipmaps" type="bool" setter="set_generate_mipmaps" getter="is_generating_mipmaps" default="true"> + Determines whether mipmaps are generated for this texture. + Enabling this results in less texture aliasing, but the noise texture generation may take longer. + Requires (anisotropic) mipmap filtering to be enabled for a material to have an effect. + </member> <member name="height" type="int" setter="set_height" getter="get_height" default="512"> Height of the generated texture. </member> + <member name="in_3d_space" type="bool" setter="set_in_3d_space" getter="is_in_3d_space" default="false"> + Determines whether the noise image is calculated in 3D space. May result in reduced contrast. + </member> <member name="invert" type="bool" setter="set_invert" getter="get_invert" default="false"> If [code]true[/code], inverts the noise texture. White becomes black, black becomes white. </member> diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp new file mode 100644 index 0000000000..32c3f0aad4 --- /dev/null +++ b/modules/noise/editor/noise_editor_plugin.cpp @@ -0,0 +1,149 @@ +/*************************************************************************/ +/* noise_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "noise_editor_plugin.h" + +#ifdef TOOLS_ENABLED + +#include "editor/editor_scale.h" + +#include "modules/noise/noise.h" +#include "modules/noise/noise_texture.h" + +class NoisePreview : public Control { + GDCLASS(NoisePreview, Control) + + static const int PREVIEW_HEIGHT = 150; + static const int PADDING_3D_SPACE_SWITCH = 2; + + Ref<Noise> _noise; + Size2i _preview_texture_size; + + TextureRect *_texture_rect = nullptr; + Button *_3d_space_switch = nullptr; + +public: + NoisePreview() { + set_custom_minimum_size(Size2(0, EDSCALE * PREVIEW_HEIGHT)); + + _texture_rect = memnew(TextureRect); + _texture_rect->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + _texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_COVERED); + add_child(_texture_rect); + + _3d_space_switch = memnew(Button); + _3d_space_switch->set_text(TTR("3D")); + _3d_space_switch->set_tooltip(TTR("Toggles whether the noise preview is computed in 3D space.")); + _3d_space_switch->set_toggle_mode(true); + _3d_space_switch->set_offset(SIDE_LEFT, PADDING_3D_SPACE_SWITCH); + _3d_space_switch->set_offset(SIDE_TOP, PADDING_3D_SPACE_SWITCH); + _3d_space_switch->connect("pressed", callable_mp(this, &NoisePreview::_on_3d_button_pressed)); + add_child(_3d_space_switch); + } + + void set_noise(Ref<Noise> noise) { + if (_noise == noise) { + return; + } + _noise = noise; + if (_noise.is_valid()) { + if (_noise->has_meta("_preview_in_3d_space_")) { + _3d_space_switch->set_pressed(true); + } + + update_preview(); + } + } + +private: + void _on_3d_button_pressed() { + if (_3d_space_switch->is_pressed()) { + _noise->set_meta("_preview_in_3d_space_", true); + } else { + _noise->remove_meta("_preview_in_3d_space_"); + } + } + + void _notification(int p_what) { + switch (p_what) { + case NOTIFICATION_RESIZED: { + _preview_texture_size = get_size(); + update_preview(); + } break; + } + } + + void update_preview() { + if (MIN(_preview_texture_size.width, _preview_texture_size.height) > 0) { + Ref<NoiseTexture> tex; + tex.instantiate(); + tex->set_width(_preview_texture_size.width); + tex->set_height(_preview_texture_size.height); + tex->set_in_3d_space(_3d_space_switch->is_pressed()); + tex->set_noise(_noise); + _texture_rect->set_texture(tex); + } + } +}; + +///////////////////////////////////////////////////////////////////////////////// + +class NoiseEditorInspectorPlugin : public EditorInspectorPlugin { + GDCLASS(NoiseEditorInspectorPlugin, EditorInspectorPlugin) +public: + bool can_handle(Object *p_object) override { + return Object::cast_to<Noise>(p_object) != nullptr; + } + + void parse_begin(Object *p_object) override { + Noise *noise_ptr = Object::cast_to<Noise>(p_object); + if (noise_ptr) { + Ref<Noise> noise(noise_ptr); + + NoisePreview *viewer = memnew(NoisePreview); + viewer->set_noise(noise); + add_custom_control(viewer); + } + } +}; + +///////////////////////////////////////////////////////////////////////////////// + +String NoiseEditorPlugin::get_name() const { + return Noise::get_class_static(); +} + +NoiseEditorPlugin::NoiseEditorPlugin() { + Ref<NoiseEditorInspectorPlugin> plugin; + plugin.instantiate(); + add_inspector_plugin(plugin); +} + +#endif // TOOLS_ENABLED diff --git a/modules/noise/editor/noise_editor_plugin.h b/modules/noise/editor/noise_editor_plugin.h new file mode 100644 index 0000000000..55a01deb2d --- /dev/null +++ b/modules/noise/editor/noise_editor_plugin.h @@ -0,0 +1,49 @@ +/*************************************************************************/ +/* noise_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NOISE_EDITOR_PLUGIN_H +#define NOISE_EDITOR_PLUGIN_H + +#ifdef TOOLS_ENABLED + +#include "editor/editor_plugin.h" + +class NoiseEditorPlugin : public EditorPlugin { + GDCLASS(NoiseEditorPlugin, EditorPlugin) + +public: + String get_name() const override; + + NoiseEditorPlugin(); +}; + +#endif // TOOLS_ENABLED + +#endif // NOISE_EDITOR_PLUGIN_H diff --git a/modules/noise/fastnoise_lite.cpp b/modules/noise/fastnoise_lite.cpp index 9497fe6a7e..a8d38dee62 100644 --- a/modules/noise/fastnoise_lite.cpp +++ b/modules/noise/fastnoise_lite.cpp @@ -31,31 +31,29 @@ #include "fastnoise_lite.h" FastNoiseLite::FastNoiseLite() { - // Most defaults copied from the library. - set_noise_type(TYPE_SIMPLEX_SMOOTH); - set_seed(0); - set_frequency(0.01); - set_in_3d_space(false); - - set_fractal_type(FRACTAL_FBM); - set_fractal_octaves(5); - set_fractal_lacunarity(2.0); - set_fractal_gain(0.5); - set_fractal_weighted_strength(0.0); - set_fractal_ping_pong_strength(2.0); - - set_cellular_distance_function(DISTANCE_EUCLIDEAN); - set_cellular_return_type(RETURN_CELL_VALUE); - set_cellular_jitter(0.45); - - set_domain_warp_enabled(false); - set_domain_warp_type(DOMAIN_WARP_SIMPLEX); - set_domain_warp_amplitude(30.0); - set_domain_warp_frequency(0.05); - set_domain_warp_fractal_type(DOMAIN_WARP_FRACTAL_PROGRESSIVE); - set_domain_warp_fractal_octaves(5); - set_domain_warp_fractal_lacunarity(6); - set_domain_warp_fractal_gain(0.5); + _noise.SetNoiseType((_FastNoiseLite::NoiseType)noise_type); + _noise.SetSeed(seed); + _noise.SetFrequency(frequency); + + _noise.SetFractalType((_FastNoiseLite::FractalType)fractal_type); + _noise.SetFractalOctaves(fractal_octaves); + _noise.SetFractalLacunarity(fractal_lacunarity); + _noise.SetFractalGain(fractal_gain); + _noise.SetFractalWeightedStrength(fractal_weighted_strength); + _noise.SetFractalPingPongStrength(fractal_ping_pong_strength); + + _noise.SetCellularDistanceFunction((_FastNoiseLite::CellularDistanceFunction)cellular_distance_function); + _noise.SetCellularReturnType((_FastNoiseLite::CellularReturnType)cellular_return_type); + _noise.SetCellularJitter(cellular_jitter); + + _domain_warp_noise.SetDomainWarpType((_FastNoiseLite::DomainWarpType)domain_warp_type); + _domain_warp_noise.SetSeed(seed); + _domain_warp_noise.SetDomainWarpAmp(domain_warp_amplitude); + _domain_warp_noise.SetFrequency(domain_warp_frequency); + _domain_warp_noise.SetFractalType(_FastNoiseLite::FractalType_None); + _domain_warp_noise.SetFractalOctaves(domain_warp_fractal_octaves); + _domain_warp_noise.SetFractalLacunarity(domain_warp_fractal_lacunarity); + _domain_warp_noise.SetFractalGain(domain_warp_fractal_gain); } FastNoiseLite::~FastNoiseLite() { @@ -77,6 +75,7 @@ FastNoiseLite::NoiseType FastNoiseLite::get_noise_type() const { void FastNoiseLite::set_seed(int p_seed) { seed = p_seed; _noise.SetSeed(p_seed); + _domain_warp_noise.SetSeed(p_seed); emit_changed(); } @@ -94,14 +93,6 @@ real_t FastNoiseLite::get_frequency() const { return frequency; } -void FastNoiseLite::set_in_3d_space(bool p_enable) { - in_3d_space = p_enable; - emit_changed(); -} -bool FastNoiseLite::is_in_3d_space() const { - return in_3d_space; -} - void FastNoiseLite::set_offset(Vector3 p_offset) { offset = p_offset; emit_changed(); @@ -111,46 +102,6 @@ Vector3 FastNoiseLite::get_offset() const { return offset; } -void FastNoiseLite::set_color_ramp(const Ref<Gradient> &p_gradient) { - color_ramp = p_gradient; - if (color_ramp.is_valid()) { - color_ramp->connect(SNAME("changed"), callable_mp(this, &FastNoiseLite::_changed)); - emit_changed(); - } -} - -Ref<Gradient> FastNoiseLite::get_color_ramp() const { - return color_ramp; -} - -// Noise functions. - -real_t FastNoiseLite::get_noise_1d(real_t p_x) { - return get_noise_2d(p_x, 0.0); -} - -real_t FastNoiseLite::get_noise_2dv(Vector2 p_v) { - return get_noise_2d(p_v.x, p_v.y); -} - -real_t FastNoiseLite::get_noise_2d(real_t p_x, real_t p_y) { - if (domain_warp_enabled) { - _domain_warp_noise.DomainWarp(p_x, p_y); - } - return _noise.GetNoise(p_x + offset.x, p_y + offset.y); -} - -real_t FastNoiseLite::get_noise_3dv(Vector3 p_v) { - return get_noise_3d(p_v.x, p_v.y, p_v.z); -} - -real_t FastNoiseLite::get_noise_3d(real_t p_x, real_t p_y, real_t p_z) { - if (domain_warp_enabled) { - _domain_warp_noise.DomainWarp(p_x, p_y, p_z); - } - return _noise.GetNoise(p_x + offset.x, p_y + offset.y, p_z + offset.z); -} - // Fractal. void FastNoiseLite::set_fractal_type(FractalType p_type) { @@ -204,12 +155,12 @@ real_t FastNoiseLite::get_fractal_weighted_strength() const { } void FastNoiseLite::set_fractal_ping_pong_strength(real_t p_ping_pong_strength) { - fractal_pinp_pong_strength = p_ping_pong_strength; + fractal_ping_pong_strength = p_ping_pong_strength; _noise.SetFractalPingPongStrength(p_ping_pong_strength); emit_changed(); } real_t FastNoiseLite::get_fractal_ping_pong_strength() const { - return fractal_pinp_pong_strength; + return fractal_ping_pong_strength; } // Cellular. @@ -237,7 +188,6 @@ real_t FastNoiseLite::get_cellular_jitter() const { void FastNoiseLite::set_cellular_return_type(CellularReturnType p_ret) { cellular_return_type = p_ret; _noise.SetCellularReturnType((_FastNoiseLite::CellularReturnType)p_ret); - emit_changed(); } @@ -345,68 +295,32 @@ real_t FastNoiseLite::get_domain_warp_fractal_gain() const { return domain_warp_fractal_gain; } -// Textures. +// Noise interface functions. -Ref<Image> FastNoiseLite::get_image(int p_width, int p_height, bool p_invert) { - bool grayscale = color_ramp.is_null(); - - Vector<uint8_t> data; - data.resize(p_width * p_height * (grayscale ? 1 : 4)); - - uint8_t *wd8 = data.ptrw(); +real_t FastNoiseLite::get_noise_1d(real_t p_x) const { + return get_noise_2d(p_x, 0.0); +} - // Get all values and identify min/max values. - Vector<real_t> values; - values.resize(p_width * p_height); - real_t min_val = 100; - real_t max_val = -100; +real_t FastNoiseLite::get_noise_2dv(Vector2 p_v) const { + return get_noise_2d(p_v.x, p_v.y); +} - for (int y = 0, i = 0; y < p_height; y++) { - for (int x = 0; x < p_width; x++, i++) { - values.set(i, is_in_3d_space() ? get_noise_3d(x, y, 0.0) : get_noise_2d(x, y)); - if (values[i] > max_val) { - max_val = values[i]; - } - if (values[i] < min_val) { - min_val = values[i]; - } - } +real_t FastNoiseLite::get_noise_2d(real_t p_x, real_t p_y) const { + if (domain_warp_enabled) { + _domain_warp_noise.DomainWarp(p_x, p_y); } + return _noise.GetNoise(p_x + offset.x, p_y + offset.y); +} - // Normalize values and write to texture. - uint8_t value; - for (int i = 0, x = 0; i < p_height; i++) { - for (int j = 0; j < p_width; j++, x++) { - if (max_val == min_val) { - value = 0; - } else { - value = uint8_t(CLAMP((values[x] - min_val) / (max_val - min_val) * 255.f, 0, 255)); - } - if (p_invert) { - value = 255 - value; - } - if (grayscale) { - wd8[x] = value; - } else { - float luminance = value / 255.0; - Color ramp_color = color_ramp->get_color_at_offset(luminance); - wd8[x * 4 + 0] = uint8_t(CLAMP(ramp_color.r * 255, 0, 255)); - wd8[x * 4 + 1] = uint8_t(CLAMP(ramp_color.g * 255, 0, 255)); - wd8[x * 4 + 2] = uint8_t(CLAMP(ramp_color.b * 255, 0, 255)); - wd8[x * 4 + 3] = uint8_t(CLAMP(ramp_color.a * 255, 0, 255)); - } - } - } - if (grayscale) { - return memnew(Image(p_width, p_height, false, Image::FORMAT_L8, data)); - } else { - return memnew(Image(p_width, p_height, false, Image::FORMAT_RGBA8, data)); - } +real_t FastNoiseLite::get_noise_3dv(Vector3 p_v) const { + return get_noise_3d(p_v.x, p_v.y, p_v.z); } -Ref<Image> FastNoiseLite::get_seamless_image(int p_width, int p_height, bool p_invert, real_t p_blend_skirt) { - // Just return parent function. This is here only so Godot will properly document this function. - return Noise::get_seamless_image(p_width, p_height, p_invert, p_blend_skirt); +real_t FastNoiseLite::get_noise_3d(real_t p_x, real_t p_y, real_t p_z) const { + if (domain_warp_enabled) { + _domain_warp_noise.DomainWarp(p_x, p_y, p_z); + } + return _noise.GetNoise(p_x + offset.x, p_y + offset.y, p_z + offset.z); } void FastNoiseLite::_changed() { @@ -418,108 +332,103 @@ void FastNoiseLite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_noise_type", "type"), &FastNoiseLite::set_noise_type); ClassDB::bind_method(D_METHOD("get_noise_type"), &FastNoiseLite::get_noise_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "noise_type", PROPERTY_HINT_ENUM, "Simplex,Simplex Smooth,Cellular,Perlin,Value Cubic,Value"), "set_noise_type", "get_noise_type"); ClassDB::bind_method(D_METHOD("set_seed", "seed"), &FastNoiseLite::set_seed); ClassDB::bind_method(D_METHOD("get_seed"), &FastNoiseLite::get_seed); - ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed"); ClassDB::bind_method(D_METHOD("set_frequency", "freq"), &FastNoiseLite::set_frequency); ClassDB::bind_method(D_METHOD("get_frequency"), &FastNoiseLite::get_frequency); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frequency", PROPERTY_HINT_RANGE, ".001,1"), "set_frequency", "get_frequency"); - - ClassDB::bind_method(D_METHOD("set_in_3d_space", "enable"), &FastNoiseLite::set_in_3d_space); - ClassDB::bind_method(D_METHOD("is_in_3d_space"), &FastNoiseLite::is_in_3d_space); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "in_3d_space"), "set_in_3d_space", "is_in_3d_space"); ClassDB::bind_method(D_METHOD("set_offset", "offset"), &FastNoiseLite::set_offset); ClassDB::bind_method(D_METHOD("get_offset"), &FastNoiseLite::get_offset); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "offset", PROPERTY_HINT_RANGE, "-999999999,999999999,1"), "set_offset", "get_offset"); - - ClassDB::bind_method(D_METHOD("set_color_ramp", "gradient"), &FastNoiseLite::set_color_ramp); - ClassDB::bind_method(D_METHOD("get_color_ramp"), &FastNoiseLite::get_color_ramp); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp"); // Fractal. - ADD_GROUP("Fractal", "fractal_"); ClassDB::bind_method(D_METHOD("set_fractal_type", "type"), &FastNoiseLite::set_fractal_type); ClassDB::bind_method(D_METHOD("get_fractal_type"), &FastNoiseLite::get_fractal_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_type", PROPERTY_HINT_ENUM, "None,FBM,Ridged,Ping-Pong"), "set_fractal_type", "get_fractal_type"); ClassDB::bind_method(D_METHOD("set_fractal_octaves", "octave_count"), &FastNoiseLite::set_fractal_octaves); ClassDB::bind_method(D_METHOD("get_fractal_octaves"), &FastNoiseLite::get_fractal_octaves); - ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_octaves", PROPERTY_HINT_RANGE, "1,10,1"), "set_fractal_octaves", "get_fractal_octaves"); ClassDB::bind_method(D_METHOD("set_fractal_lacunarity", "lacunarity"), &FastNoiseLite::set_fractal_lacunarity); ClassDB::bind_method(D_METHOD("get_fractal_lacunarity"), &FastNoiseLite::get_fractal_lacunarity); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_lacunarity"), "set_fractal_lacunarity", "get_fractal_lacunarity"); ClassDB::bind_method(D_METHOD("set_fractal_gain", "gain"), &FastNoiseLite::set_fractal_gain); ClassDB::bind_method(D_METHOD("get_fractal_gain"), &FastNoiseLite::get_fractal_gain); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_gain"), "set_fractal_gain", "get_fractal_gain"); ClassDB::bind_method(D_METHOD("set_fractal_weighted_strength", "weighted_strength"), &FastNoiseLite::set_fractal_weighted_strength); ClassDB::bind_method(D_METHOD("get_fractal_weighted_strength"), &FastNoiseLite::get_fractal_weighted_strength); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_weighted_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_fractal_weighted_strength", "get_fractal_weighted_strength"); ClassDB::bind_method(D_METHOD("set_fractal_ping_pong_strength", "ping_pong_strength"), &FastNoiseLite::set_fractal_ping_pong_strength); ClassDB::bind_method(D_METHOD("get_fractal_ping_pong_strength"), &FastNoiseLite::get_fractal_ping_pong_strength); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_ping_pong_strength"), "set_fractal_ping_pong_strength", "get_fractal_ping_pong_strength"); // Cellular. - ADD_GROUP("Cellular", "cellular_"); ClassDB::bind_method(D_METHOD("set_cellular_distance_function", "func"), &FastNoiseLite::set_cellular_distance_function); ClassDB::bind_method(D_METHOD("get_cellular_distance_function"), &FastNoiseLite::get_cellular_distance_function); - ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_distance_function", PROPERTY_HINT_ENUM, "Euclidean,Euclidean Squared,Manhattan,Hybrid"), "set_cellular_distance_function", "get_cellular_distance_function"); ClassDB::bind_method(D_METHOD("set_cellular_jitter", "jitter"), &FastNoiseLite::set_cellular_jitter); ClassDB::bind_method(D_METHOD("get_cellular_jitter"), &FastNoiseLite::get_cellular_jitter); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cellular_jitter"), "set_cellular_jitter", "get_cellular_jitter"); ClassDB::bind_method(D_METHOD("set_cellular_return_type", "ret"), &FastNoiseLite::set_cellular_return_type); ClassDB::bind_method(D_METHOD("get_cellular_return_type"), &FastNoiseLite::get_cellular_return_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_return_type", PROPERTY_HINT_ENUM, "Cell Value,Distance,Distance2,Distance2Add,Distance2Sub,Distance2Mul,Distance2Div"), "set_cellular_return_type", "get_cellular_return_type"); // Domain warp. - ADD_GROUP("Domain Warp", "domain_warp_"); - ClassDB::bind_method(D_METHOD("set_domain_warp_enabled", "domain_warp_enabled"), &FastNoiseLite::set_domain_warp_enabled); ClassDB::bind_method(D_METHOD("is_domain_warp_enabled"), &FastNoiseLite::is_domain_warp_enabled); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "domain_warp_enabled"), "set_domain_warp_enabled", "is_domain_warp_enabled"); ClassDB::bind_method(D_METHOD("set_domain_warp_type", "domain_warp_type"), &FastNoiseLite::set_domain_warp_type); ClassDB::bind_method(D_METHOD("get_domain_warp_type"), &FastNoiseLite::get_domain_warp_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_type", PROPERTY_HINT_ENUM, "Simplex,Simplex Reduced,Basic Grid"), "set_domain_warp_type", "get_domain_warp_type"); ClassDB::bind_method(D_METHOD("set_domain_warp_amplitude", "domain_warp_amplitude"), &FastNoiseLite::set_domain_warp_amplitude); ClassDB::bind_method(D_METHOD("get_domain_warp_amplitude"), &FastNoiseLite::get_domain_warp_amplitude); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_amplitude"), "set_domain_warp_amplitude", "get_domain_warp_amplitude"); ClassDB::bind_method(D_METHOD("set_domain_warp_frequency", "domain_warp_frequency"), &FastNoiseLite::set_domain_warp_frequency); ClassDB::bind_method(D_METHOD("get_domain_warp_frequency"), &FastNoiseLite::get_domain_warp_frequency); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_frequency"), "set_domain_warp_frequency", "get_domain_warp_frequency"); ClassDB::bind_method(D_METHOD("set_domain_warp_fractal_type", "domain_warp_fractal_type"), &FastNoiseLite::set_domain_warp_fractal_type); ClassDB::bind_method(D_METHOD("get_domain_warp_fractal_type"), &FastNoiseLite::get_domain_warp_fractal_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_fractal_type", PROPERTY_HINT_ENUM, "None,Progressive,Independent"), "set_domain_warp_fractal_type", "get_domain_warp_fractal_type"); ClassDB::bind_method(D_METHOD("set_domain_warp_fractal_octaves", "domain_warp_octave_count"), &FastNoiseLite::set_domain_warp_fractal_octaves); ClassDB::bind_method(D_METHOD("get_domain_warp_fractal_octaves"), &FastNoiseLite::get_domain_warp_fractal_octaves); - ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_fractal_octaves", PROPERTY_HINT_RANGE, "1,10,1"), "set_domain_warp_fractal_octaves", "get_domain_warp_fractal_octaves"); ClassDB::bind_method(D_METHOD("set_domain_warp_fractal_lacunarity", "domain_warp_lacunarity"), &FastNoiseLite::set_domain_warp_fractal_lacunarity); ClassDB::bind_method(D_METHOD("get_domain_warp_fractal_lacunarity"), &FastNoiseLite::get_domain_warp_fractal_lacunarity); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_fractal_lacunarity"), "set_domain_warp_fractal_lacunarity", "get_domain_warp_fractal_lacunarity"); ClassDB::bind_method(D_METHOD("set_domain_warp_fractal_gain", "domain_warp_gain"), &FastNoiseLite::set_domain_warp_fractal_gain); ClassDB::bind_method(D_METHOD("get_domain_warp_fractal_gain"), &FastNoiseLite::get_domain_warp_fractal_gain); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_fractal_gain"), "set_domain_warp_fractal_gain", "get_domain_warp_fractal_gain"); ClassDB::bind_method(D_METHOD("_changed"), &FastNoiseLite::_changed); + ADD_PROPERTY(PropertyInfo(Variant::INT, "noise_type", PROPERTY_HINT_ENUM, "Simplex,Simplex Smooth,Cellular,Perlin,Value Cubic,Value"), "set_noise_type", "get_noise_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frequency", PROPERTY_HINT_RANGE, ".001,1"), "set_frequency", "get_frequency"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "offset", PROPERTY_HINT_RANGE, "-999999999,999999999,0.01"), "set_offset", "get_offset"); + + ADD_GROUP("Fractal", "fractal_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_type", PROPERTY_HINT_ENUM, "None,FBM,Ridged,Ping-Pong"), "set_fractal_type", "get_fractal_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_octaves", PROPERTY_HINT_RANGE, "1,10,1"), "set_fractal_octaves", "get_fractal_octaves"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_lacunarity"), "set_fractal_lacunarity", "get_fractal_lacunarity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_gain"), "set_fractal_gain", "get_fractal_gain"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_weighted_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_fractal_weighted_strength", "get_fractal_weighted_strength"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fractal_ping_pong_strength"), "set_fractal_ping_pong_strength", "get_fractal_ping_pong_strength"); + + ADD_GROUP("Cellular", "cellular_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_distance_function", PROPERTY_HINT_ENUM, "Euclidean,Euclidean Squared,Manhattan,Hybrid"), "set_cellular_distance_function", "get_cellular_distance_function"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cellular_jitter"), "set_cellular_jitter", "get_cellular_jitter"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_return_type", PROPERTY_HINT_ENUM, "Cell Value,Distance,Distance2,Distance2Add,Distance2Sub,Distance2Mul,Distance2Div"), "set_cellular_return_type", "get_cellular_return_type"); + + ADD_GROUP("Domain Warp", "domain_warp_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "domain_warp_enabled"), "set_domain_warp_enabled", "is_domain_warp_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_type", PROPERTY_HINT_ENUM, "Simplex,Simplex Reduced,Basic Grid"), "set_domain_warp_type", "get_domain_warp_type"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_amplitude"), "set_domain_warp_amplitude", "get_domain_warp_amplitude"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_frequency"), "set_domain_warp_frequency", "get_domain_warp_frequency"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_fractal_type", PROPERTY_HINT_ENUM, "None,Progressive,Independent"), "set_domain_warp_fractal_type", "get_domain_warp_fractal_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_fractal_octaves", PROPERTY_HINT_RANGE, "1,10,1"), "set_domain_warp_fractal_octaves", "get_domain_warp_fractal_octaves"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_fractal_lacunarity"), "set_domain_warp_fractal_lacunarity", "get_domain_warp_fractal_lacunarity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "domain_warp_fractal_gain"), "set_domain_warp_fractal_gain", "get_domain_warp_fractal_gain"); + BIND_ENUM_CONSTANT(TYPE_VALUE); BIND_ENUM_CONSTANT(TYPE_VALUE_CUBIC); BIND_ENUM_CONSTANT(TYPE_PERLIN); diff --git a/modules/noise/fastnoise_lite.h b/modules/noise/fastnoise_lite.h index 4635e26d28..0a4251868b 100644 --- a/modules/noise/fastnoise_lite.h +++ b/modules/noise/fastnoise_lite.h @@ -99,36 +99,33 @@ private: _FastNoiseLite _domain_warp_noise; Vector3 offset; - NoiseType noise_type; - Ref<Gradient> color_ramp; + NoiseType noise_type = TYPE_SIMPLEX_SMOOTH; - int seed; - real_t frequency; - bool in_3d_space; + int seed = 0; + real_t frequency = 0.01; // Fractal specific. - FractalType fractal_type; - int fractal_octaves; - real_t fractal_lacunarity; - real_t fractal_gain; - real_t fractal_weighted_strength; - real_t fractal_pinp_pong_strength; + FractalType fractal_type = FRACTAL_FBM; + int fractal_octaves = 5; + real_t fractal_lacunarity = 2; + real_t fractal_gain = 0.5; + real_t fractal_weighted_strength = 0; + real_t fractal_ping_pong_strength = 2; // Cellular specific. - CellularDistanceFunction cellular_distance_function; - CellularReturnType cellular_return_type; - real_t cellular_jitter; + CellularDistanceFunction cellular_distance_function = DISTANCE_EUCLIDEAN; + CellularReturnType cellular_return_type = RETURN_DISTANCE; + real_t cellular_jitter = 0.45; // Domain warp specific. - bool domain_warp_enabled; - DomainWarpType domain_warp_type; - real_t domain_warp_frequency; - real_t domain_warp_amplitude; - - DomainWarpFractalType domain_warp_fractal_type; - int domain_warp_fractal_octaves; - real_t domain_warp_fractal_lacunarity; - real_t domain_warp_fractal_gain; + bool domain_warp_enabled = false; + DomainWarpType domain_warp_type = DOMAIN_WARP_SIMPLEX; + real_t domain_warp_amplitude = 30.0; + real_t domain_warp_frequency = 0.05; + DomainWarpFractalType domain_warp_fractal_type = DOMAIN_WARP_FRACTAL_PROGRESSIVE; + int domain_warp_fractal_octaves = 5; + real_t domain_warp_fractal_lacunarity = 6; + real_t domain_warp_fractal_gain = 0.5; public: FastNoiseLite(); @@ -145,15 +142,9 @@ public: void set_frequency(real_t p_freq); real_t get_frequency() const; - void set_in_3d_space(bool p_enable); - bool is_in_3d_space() const; - void set_offset(Vector3 p_offset); Vector3 get_offset() const; - void set_color_ramp(const Ref<Gradient> &p_gradient); - Ref<Gradient> get_color_ramp() const; - // Fractal specific. void set_fractal_type(FractalType p_type); @@ -212,17 +203,13 @@ public: real_t get_domain_warp_fractal_gain() const; // Interface methods. + real_t get_noise_1d(real_t p_x) const override; - Ref<Image> get_image(int p_width, int p_height, bool p_invert = false) override; - Ref<Image> get_seamless_image(int p_width, int p_height, bool p_invert = false, real_t p_blend_skirt = 0.1) override; - - real_t get_noise_1d(real_t p_x) override; - - real_t get_noise_2dv(Vector2 p_v) override; - real_t get_noise_2d(real_t p_x, real_t p_y) override; + real_t get_noise_2dv(Vector2 p_v) const override; + real_t get_noise_2d(real_t p_x, real_t p_y) const override; - real_t get_noise_3dv(Vector3 p_v) override; - real_t get_noise_3d(real_t p_x, real_t p_y, real_t p_z) override; + real_t get_noise_3dv(Vector3 p_v) const override; + real_t get_noise_3d(real_t p_x, real_t p_y, real_t p_z) const override; void _changed(); }; diff --git a/modules/noise/noise.cpp b/modules/noise/noise.cpp index 430e8c87cf..ad3df0a016 100644 --- a/modules/noise/noise.cpp +++ b/modules/noise/noise.cpp @@ -30,13 +30,13 @@ #include "noise.h" -Ref<Image> Noise::get_seamless_image(int p_width, int p_height, bool p_invert, real_t p_blend_skirt) { +Ref<Image> Noise::get_seamless_image(int p_width, int p_height, bool p_invert, bool p_in_3d_space, real_t p_blend_skirt) const { int skirt_width = p_width * p_blend_skirt; int skirt_height = p_height * p_blend_skirt; int src_width = p_width + skirt_width; int src_height = p_height + skirt_height; - Ref<Image> src = get_image(src_width, src_height, p_invert); + Ref<Image> src = get_image(src_width, src_height, p_invert, p_in_3d_space); bool grayscale = (src->get_format() == Image::FORMAT_L8); if (grayscale) { return _generate_seamless_image<uint8_t>(src, p_width, p_height, p_invert, p_blend_skirt); @@ -54,6 +54,50 @@ uint8_t Noise::_alpha_blend<uint8_t>(uint8_t p_bg, uint8_t p_fg, int p_alpha) co return (uint8_t)((alpha * p_fg + inv_alpha * p_bg) >> 8); } +Ref<Image> Noise::get_image(int p_width, int p_height, bool p_invert, bool p_in_3d_space) const { + Vector<uint8_t> data; + data.resize(p_width * p_height); + + uint8_t *wd8 = data.ptrw(); + + // Get all values and identify min/max values. + Vector<real_t> values; + values.resize(p_width * p_height); + real_t min_val = 1000; + real_t max_val = -1000; + + for (int y = 0, i = 0; y < p_height; y++) { + for (int x = 0; x < p_width; x++, i++) { + values.set(i, p_in_3d_space ? get_noise_3d(x, y, 0.0) : get_noise_2d(x, y)); + if (values[i] > max_val) { + max_val = values[i]; + } + if (values[i] < min_val) { + min_val = values[i]; + } + } + } + + // Normalize values and write to texture. + uint8_t value; + for (int i = 0, x = 0; i < p_height; i++) { + for (int j = 0; j < p_width; j++, x++) { + if (max_val == min_val) { + value = 0; + } else { + value = uint8_t(CLAMP((values[x] - min_val) / (max_val - min_val) * 255.f, 0, 255)); + } + if (p_invert) { + value = 255 - value; + } + + wd8[x] = value; + } + } + + return memnew(Image(p_width, p_height, false, Image::FORMAT_L8, data)); +} + void Noise::_bind_methods() { // Noise functions. ClassDB::bind_method(D_METHOD("get_noise_1d", "x"), &Noise::get_noise_1d); @@ -63,6 +107,6 @@ void Noise::_bind_methods() { ClassDB::bind_method(D_METHOD("get_noise_3dv", "v"), &Noise::get_noise_3dv); // Textures. - ClassDB::bind_method(D_METHOD("get_image", "width", "height", "invert"), &Noise::get_image, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("get_seamless_image", "width", "height", "invert", "skirt"), &Noise::get_seamless_image, DEFVAL(false), DEFVAL(0.1)); + ClassDB::bind_method(D_METHOD("get_image", "width", "height", "invert", "in_3d_space"), &Noise::get_image, DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_seamless_image", "width", "height", "invert", "in_3d_space", "skirt"), &Noise::get_seamless_image, DEFVAL(false), DEFVAL(false), DEFVAL(0.1)); } diff --git a/modules/noise/noise.h b/modules/noise/noise.h index 853c24b485..8083334388 100644 --- a/modules/noise/noise.h +++ b/modules/noise/noise.h @@ -81,7 +81,7 @@ class Noise : public Resource { }; template <typename T> - Ref<Image> _generate_seamless_image(Ref<Image> p_src, int p_width, int p_height, bool p_invert, real_t p_blend_skirt) { + Ref<Image> _generate_seamless_image(Ref<Image> p_src, int p_width, int p_height, bool p_invert, real_t p_blend_skirt) const { /* To make a seamless image, we swap the quadrants so the edges are perfect matches. We initially get a 10% larger image so we have an overlap we can use to blend over the seams. @@ -225,16 +225,16 @@ public: // Virtual destructor so we can delete any Noise derived object when referenced as a Noise*. virtual ~Noise() {} - virtual real_t get_noise_1d(real_t p_x) = 0; + virtual real_t get_noise_1d(real_t p_x) const = 0; - virtual real_t get_noise_2dv(Vector2 p_v) = 0; - virtual real_t get_noise_2d(real_t p_x, real_t p_y) = 0; + virtual real_t get_noise_2dv(Vector2 p_v) const = 0; + virtual real_t get_noise_2d(real_t p_x, real_t p_y) const = 0; - virtual real_t get_noise_3dv(Vector3 p_v) = 0; - virtual real_t get_noise_3d(real_t p_x, real_t p_y, real_t p_z) = 0; + virtual real_t get_noise_3dv(Vector3 p_v) const = 0; + virtual real_t get_noise_3d(real_t p_x, real_t p_y, real_t p_z) const = 0; - virtual Ref<Image> get_image(int p_width, int p_height, bool p_invert = false) = 0; - virtual Ref<Image> get_seamless_image(int p_width, int p_height, bool p_invert = false, real_t p_blend_skirt = 0.1); + virtual Ref<Image> get_image(int p_width, int p_height, bool p_invert = false, bool p_in_3d_space = false) const; + virtual Ref<Image> get_seamless_image(int p_width, int p_height, bool p_invert = false, bool p_in_3d_space = false, real_t p_blend_skirt = 0.1) const; }; #endif // NOISE_H diff --git a/modules/noise/noise_texture.cpp b/modules/noise/noise_texture.cpp index 276335797a..e9d16e548c 100644 --- a/modules/noise/noise_texture.cpp +++ b/modules/noise/noise_texture.cpp @@ -47,15 +47,22 @@ NoiseTexture::~NoiseTexture() { } void NoiseTexture::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture); + ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture); + ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done); + ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture::set_width); ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture::set_height); - ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise); - ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise); - ClassDB::bind_method(D_METHOD("set_invert", "invert"), &NoiseTexture::set_invert); ClassDB::bind_method(D_METHOD("get_invert"), &NoiseTexture::get_invert); + ClassDB::bind_method(D_METHOD("set_in_3d_space", "enable"), &NoiseTexture::set_in_3d_space); + ClassDB::bind_method(D_METHOD("is_in_3d_space"), &NoiseTexture::is_in_3d_space); + + ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "invert"), &NoiseTexture::set_generate_mipmaps); + ClassDB::bind_method(D_METHOD("is_generating_mipmaps"), &NoiseTexture::is_generating_mipmaps); + ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless); ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless); @@ -68,17 +75,22 @@ void NoiseTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture::set_bump_strength); ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture::get_bump_strength); - ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture); - ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture); - ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done); + ClassDB::bind_method(D_METHOD("set_color_ramp", "gradient"), &NoiseTexture::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp"), &NoiseTexture::get_color_ramp); + + ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise); + ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise); ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert"), "set_invert", "get_invert"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "in_3d_space"), "set_in_3d_space", "is_in_3d_space"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "is_generating_mipmaps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "seamless"), "set_seamless", "get_seamless"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "seamless_blend_skirt", PROPERTY_HINT_RANGE, "0.05,1,0.001"), "set_seamless_blend_skirt", "get_seamless_blend_skirt"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normal_map"), "set_as_normal_map", "is_normal_map"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "Noise"), "set_noise", "get_noise"); } @@ -143,18 +155,42 @@ Ref<Image> NoiseTexture::_generate_texture() { Ref<Image> image; if (seamless) { - image = ref_noise->get_seamless_image(size.x, size.y, invert, seamless_blend_skirt); + image = ref_noise->get_seamless_image(size.x, size.y, invert, in_3d_space, seamless_blend_skirt); } else { - image = ref_noise->get_image(size.x, size.y, invert); + image = ref_noise->get_image(size.x, size.y, invert, in_3d_space); + } + if (color_ramp.is_valid()) { + image = _modulate_with_gradient(image, color_ramp); } - if (as_normal_map) { image->bump_map_to_normal_map(bump_strength); } + if (generate_mipmaps) { + image->generate_mipmaps(); + } return image; } +Ref<Image> NoiseTexture::_modulate_with_gradient(Ref<Image> p_image, Ref<Gradient> p_gradient) { + int width = p_image->get_width(); + int height = p_image->get_height(); + + Ref<Image> new_image; + new_image.instantiate(); + new_image->create(width, height, false, Image::FORMAT_RGBA8); + + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + Color pixel_color = p_image->get_pixel(col, row); + Color ramp_color = color_ramp->get_color_at_offset(pixel_color.get_luminance()); + new_image->set_pixel(col, row, ramp_color); + } + } + + return new_image; +} + void NoiseTexture::_update_texture() { bool use_thread = true; if (first_time) { @@ -227,6 +263,29 @@ bool NoiseTexture::get_invert() const { return invert; } +void NoiseTexture::set_in_3d_space(bool p_enable) { + if (p_enable == in_3d_space) { + return; + } + in_3d_space = p_enable; + _queue_update(); +} +bool NoiseTexture::is_in_3d_space() const { + return in_3d_space; +} + +void NoiseTexture::set_generate_mipmaps(bool p_enable) { + if (p_enable == generate_mipmaps) { + return; + } + generate_mipmaps = p_enable; + _queue_update(); +} + +bool NoiseTexture::is_generating_mipmaps() const { + return generate_mipmaps; +} + void NoiseTexture::set_seamless(bool p_seamless) { if (p_seamless == seamless) { return; @@ -241,6 +300,8 @@ bool NoiseTexture::get_seamless() { } void NoiseTexture::set_seamless_blend_skirt(real_t p_blend_skirt) { + ERR_FAIL_COND(p_blend_skirt < 0.05 || p_blend_skirt > 1); + if (p_blend_skirt == seamless_blend_skirt) { return; } @@ -278,6 +339,24 @@ float NoiseTexture::get_bump_strength() { return bump_strength; } +void NoiseTexture::set_color_ramp(const Ref<Gradient> &p_gradient) { + if (p_gradient == color_ramp) { + return; + } + if (color_ramp.is_valid()) { + color_ramp->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + } + color_ramp = p_gradient; + if (color_ramp.is_valid()) { + color_ramp->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + } + _queue_update(); +} + +Ref<Gradient> NoiseTexture::get_color_ramp() const { + return color_ramp; +} + int NoiseTexture::get_width() const { return size.x; } diff --git a/modules/noise/noise_texture.h b/modules/noise/noise_texture.h index 2a94df39d4..6c088562a1 100644 --- a/modules/noise/noise_texture.h +++ b/modules/noise/noise_texture.h @@ -51,15 +51,18 @@ private: mutable RID texture; uint32_t flags = 0; - Ref<Noise> noise; + Size2i size = Size2i(512, 512); bool invert = false; - Vector2i size = Vector2i(512, 512); - Vector2 noise_offset; + bool in_3d_space = false; + bool generate_mipmaps = true; bool seamless = false; real_t seamless_blend_skirt = 0.1; bool as_normal_map = false; float bump_strength = 8.0; + Ref<Gradient> color_ramp; + Ref<Noise> noise; + void _thread_done(const Ref<Image> &p_image); static void _thread_function(void *p_ud); @@ -68,6 +71,8 @@ private: void _update_texture(); void _set_texture_image(const Ref<Image> &p_image); + Ref<Image> _modulate_with_gradient(Ref<Image> p_image, Ref<Gradient> p_gradient); + protected: static void _bind_methods(); virtual void _validate_property(PropertyInfo &property) const override; @@ -82,6 +87,12 @@ public: void set_invert(bool p_invert); bool get_invert() const; + void set_in_3d_space(bool p_enable); + bool is_in_3d_space() const; + + void set_generate_mipmaps(bool p_enable); + bool is_generating_mipmaps() const; + void set_seamless(bool p_seamless); bool get_seamless(); @@ -94,6 +105,9 @@ public: void set_bump_strength(float p_bump_strength); float get_bump_strength(); + void set_color_ramp(const Ref<Gradient> &p_gradient); + Ref<Gradient> get_color_ramp() const; + int get_width() const override; int get_height() const override; diff --git a/modules/noise/register_types.cpp b/modules/noise/register_types.cpp index 81bb0317c1..3623da3bb9 100644 --- a/modules/noise/register_types.cpp +++ b/modules/noise/register_types.cpp @@ -34,10 +34,19 @@ #include "noise.h" #include "noise_texture.h" +#ifdef TOOLS_ENABLED +#include "editor/editor_plugin.h" +#include "editor/noise_editor_plugin.h" +#endif + void register_noise_types() { GDREGISTER_CLASS(NoiseTexture); GDREGISTER_ABSTRACT_CLASS(Noise); GDREGISTER_CLASS(FastNoiseLite); + +#ifdef TOOLS_ENABLED + EditorPlugins::add_by_type<NoiseEditorPlugin>(); +#endif } void unregister_noise_types() { diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp index 2ba33419d7..366e131369 100644 --- a/modules/openxr/action_map/openxr_action_map.cpp +++ b/modules/openxr/action_map/openxr_action_map.cpp @@ -55,7 +55,14 @@ void OpenXRActionMap::_bind_methods() { } void OpenXRActionMap::set_action_sets(Array p_action_sets) { - action_sets = p_action_sets; + action_sets.clear(); + + for (int i = 0; i < p_action_sets.size(); i++) { + Ref<OpenXRActionSet> action_set = p_action_sets[i]; + if (action_set.is_valid() && action_sets.find(action_set) == -1) { + action_sets.push_back(action_set); + } + } } Array OpenXRActionMap::get_action_sets() const { @@ -99,7 +106,14 @@ void OpenXRActionMap::remove_action_set(Ref<OpenXRActionSet> p_action_set) { } void OpenXRActionMap::set_interaction_profiles(Array p_interaction_profiles) { - interaction_profiles = p_interaction_profiles; + interaction_profiles.clear(); + + for (int i = 0; i < p_interaction_profiles.size(); i++) { + Ref<OpenXRInteractionProfile> interaction_profile = p_interaction_profiles[i]; + if (interaction_profile.is_valid() && interaction_profiles.find(interaction_profile) == -1) { + interaction_profiles.push_back(interaction_profile); + } + } } Array OpenXRActionMap::get_interaction_profiles() const { diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp index 1ef571b6ee..58c329f043 100644 --- a/modules/websocket/wsl_client.cpp +++ b/modules/websocket/wsl_client.cpp @@ -273,6 +273,7 @@ void WSLClient::poll() { return; // Not connected. } + _tcp->poll(); switch (_tcp->get_status()) { case StreamPeerTCP::STATUS_NONE: // Clean close @@ -336,7 +337,7 @@ MultiplayerPeer::ConnectionStatus WSLClient::get_connection_status() const { return CONNECTION_CONNECTED; } - if (_tcp->is_connected_to_host() || _resolver_id != IP::RESOLVER_INVALID_ID) { + if (_tcp->get_status() == StreamPeerTCP::STATUS_CONNECTING || _resolver_id != IP::RESOLVER_INVALID_ID) { return CONNECTION_CONNECTING; } diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp index 06b0e31801..debfe8e950 100644 --- a/modules/webxr/webxr_interface_js.cpp +++ b/modules/webxr/webxr_interface_js.cpp @@ -59,7 +59,7 @@ void _emwebxr_on_session_started(char *p_reference_space_type) { ERR_FAIL_COND(interface.is_null()); String reference_space_type = String(p_reference_space_type); - ((WebXRInterfaceJS *)interface.ptr())->_set_reference_space_type(reference_space_type); + static_cast<WebXRInterfaceJS *>(interface.ptr())->_set_reference_space_type(reference_space_type); interface->emit_signal(SNAME("session_started")); } @@ -94,7 +94,7 @@ void _emwebxr_on_controller_changed() { Ref<XRInterface> interface = xr_server->find_interface("WebXR"); ERR_FAIL_COND(interface.is_null()); - ((WebXRInterfaceJS *)interface.ptr())->_on_controller_changed(); + static_cast<WebXRInterfaceJS *>(interface.ptr())->_on_controller_changed(); } extern "C" EMSCRIPTEN_KEEPALIVE void _emwebxr_on_input_event(char *p_signal_name, int p_input_source) { diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 54124c22d0..fc46005b41 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -139,7 +139,7 @@ void OS_Android::finalize() { } OS_Android *OS_Android::get_singleton() { - return (OS_Android *)OS::get_singleton(); + return static_cast<OS_Android *>(OS::get_singleton()); } GodotJavaWrapper *OS_Android::get_godot_java() { diff --git a/platform/iphone/ios.h b/platform/iphone/ios.h index 03e663b05c..0607d7b395 100644 --- a/platform/iphone/ios.h +++ b/platform/iphone/ios.h @@ -32,15 +32,26 @@ #define IOS_H #include "core/object/class_db.h" +#import <CoreHaptics/CoreHaptics.h> class iOS : public Object { GDCLASS(iOS, Object); static void _bind_methods(); +private: + CHHapticEngine *haptic_engine API_AVAILABLE(ios(13)) = nullptr; + + CHHapticEngine *get_haptic_engine_instance() API_AVAILABLE(ios(13)); + void start_haptic_engine(); + void stop_haptic_engine(); + public: static void alert(const char *p_alert, const char *p_title); + bool supports_haptic_engine(); + void vibrate_haptic_engine(float p_duration_seconds); + String get_model() const; String get_rate_url(int p_app_id) const; diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm index ad1ea70c10..cca28cc055 100644 --- a/platform/iphone/ios.mm +++ b/platform/iphone/ios.mm @@ -32,11 +32,110 @@ #import "app_delegate.h" #import "view_controller.h" + +#import <CoreHaptics/CoreHaptics.h> #import <UIKit/UIKit.h> #include <sys/sysctl.h> void iOS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rate_url", "app_id"), &iOS::get_rate_url); + ClassDB::bind_method(D_METHOD("supports_haptic_engine"), &iOS::supports_haptic_engine); + ClassDB::bind_method(D_METHOD("start_haptic_engine"), &iOS::start_haptic_engine); + ClassDB::bind_method(D_METHOD("stop_haptic_engine"), &iOS::stop_haptic_engine); +}; + +bool iOS::supports_haptic_engine() { + if (@available(iOS 13, *)) { + id<CHHapticDeviceCapability> capabilities = [CHHapticEngine capabilitiesForHardware]; + return capabilities.supportsHaptics; + } + + return false; +} + +CHHapticEngine *iOS::get_haptic_engine_instance() API_AVAILABLE(ios(13)) { + if (haptic_engine == nullptr) { + NSError *error = nullptr; + haptic_engine = [[CHHapticEngine alloc] initAndReturnError:&error]; + + if (!error) { + [haptic_engine setAutoShutdownEnabled:true]; + } else { + haptic_engine = nullptr; + NSLog(@"Could not initialize haptic engine: %@", error); + } + } + + return haptic_engine; +} + +void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13)) { + if (@available(iOS 13, *)) { // We need the @available check every time to make the compiler happy... + if (supports_haptic_engine()) { + CHHapticEngine *haptic_engine = get_haptic_engine_instance(); + if (haptic_engine) { + NSDictionary *hapticDict = @{ + CHHapticPatternKeyPattern : @[ + @{CHHapticPatternKeyEvent : @{ + CHHapticPatternKeyEventType : CHHapticEventTypeHapticTransient, + CHHapticPatternKeyTime : @(CHHapticTimeImmediate), + CHHapticPatternKeyEventDuration : @(p_duration_seconds) + }, + }, + ], + }; + + NSError *error; + CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithDictionary:hapticDict error:&error]; + + [[haptic_engine createPlayerWithPattern:pattern error:&error] startAtTime:0 error:&error]; + + NSLog(@"Could not vibrate using haptic engine: %@", error); + } + + return; + } + } + + NSLog(@"Haptic engine is not supported in this version of iOS"); +} + +void iOS::start_haptic_engine() { + if (@available(iOS 13, *)) { + if (supports_haptic_engine()) { + CHHapticEngine *haptic_engine = get_haptic_engine_instance(); + if (haptic_engine) { + [haptic_engine startWithCompletionHandler:^(NSError *returnedError) { + if (returnedError) { + NSLog(@"Could not start haptic engine: %@", returnedError); + } + }]; + } + + return; + } + } + + NSLog(@"Haptic engine is not supported in this version of iOS"); +} + +void iOS::stop_haptic_engine() { + if (@available(iOS 13, *)) { + if (supports_haptic_engine()) { + CHHapticEngine *haptic_engine = get_haptic_engine_instance(); + if (haptic_engine) { + [haptic_engine stopWithCompletionHandler:^(NSError *returnedError) { + if (returnedError) { + NSLog(@"Could not stop haptic engine: %@", returnedError); + } + }]; + } + + return; + } + } + + NSLog(@"Haptic engine is not supported in this version of iOS"); } void iOS::alert(const char *p_alert, const char *p_title) { diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm index ea1bc0ef64..f7974c4b3d 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -298,8 +298,12 @@ String OSIPhone::get_processor_name() const { } void OSIPhone::vibrate_handheld(int p_duration_ms) { - // iOS does not support duration for vibration - AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); + if (ios->supports_haptic_engine()) { + ios->vibrate_haptic_engine((float)p_duration_ms / 1000.f); + } else { + // iOS <13 does not support duration for vibration + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); + } } bool OSIPhone::_check_internal_feature_support(const String &p_feature) { diff --git a/platform/javascript/javascript_singleton.cpp b/platform/javascript/javascript_singleton.cpp index c9c4d6e1b9..8dc7aba5f8 100644 --- a/platform/javascript/javascript_singleton.cpp +++ b/platform/javascript/javascript_singleton.cpp @@ -207,7 +207,7 @@ int JavaScriptObjectImpl::_variant2js(const void **p_args, int p_pos, godot_js_w break; case Variant::INT: { const int64_t tmp = v->operator int64_t(); - if (tmp >= 1 << 31) { + if (tmp >= 1LL << 31) { r_val->r = (double)tmp; return Variant::FLOAT; } diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 39f9b99108..2fba58fc53 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -319,20 +319,21 @@ def configure(env): if os.system("pkg-config --exists alsa") == 0: # 0 means found env["alsa"] = True env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) + env.ParseConfig("pkg-config alsa --cflags") # Only cflags, we dlopen the library. else: print("Warning: ALSA libraries not found. Disabling the ALSA audio driver.") if env["pulseaudio"]: if os.system("pkg-config --exists libpulse") == 0: # 0 means found env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"]) - env.ParseConfig("pkg-config --cflags libpulse") + env.ParseConfig("pkg-config libpulse --cflags") # Only cflags, we dlopen the library. else: print("Warning: PulseAudio development libraries not found. Disabling the PulseAudio audio driver.") if env["dbus"]: if os.system("pkg-config --exists dbus-1") == 0: # 0 means found env.Append(CPPDEFINES=["DBUS_ENABLED"]) - env.ParseConfig("pkg-config --cflags --libs dbus-1") + env.ParseConfig("pkg-config dbus-1 --cflags --libs") else: print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.") @@ -341,6 +342,7 @@ def configure(env): if env["udev"]: if os.system("pkg-config --exists libudev") == 0: # 0 means found env.Append(CPPDEFINES=["UDEV_ENABLED"]) + env.ParseConfig("pkg-config libudev --cflags") # Only cflags, we dlopen the library. else: print("Warning: libudev development libraries not found. Disabling controller hotplugging support.") else: @@ -366,11 +368,11 @@ def configure(env): if not env["use_volk"]: env.ParseConfig("pkg-config vulkan --cflags --libs") if not env["builtin_glslang"]: - # No pkgconfig file for glslang so far + # No pkgconfig file so far, hardcode expected lib name. env.Append(LIBS=["glslang", "SPIRV"]) env.Append(CPPDEFINES=["GLES3_ENABLED"]) - env.Append(LIBS=["GL"]) + env.ParseConfig("pkg-config gl --cflags --libs") env.Append(LIBS=["pthread"]) diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 7da30ac363..a36fcabd91 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -670,17 +670,17 @@ void DisplayServerX11::_clipboard_transfer_ownership(Atom p_source, Window x11_w int DisplayServerX11::get_screen_count() const { _THREAD_SAFE_METHOD_ + int count = 0; // Using Xinerama Extension int event_base, error_base; - const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); - if (!ext_okay) { - return 0; + if (XineramaQueryExtension(x11_display, &event_base, &error_base)) { + XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); + XFree(xsi); + } else { + count = XScreenCount(x11_display); } - int count; - XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); - XFree(xsi); return count; } @@ -712,6 +712,19 @@ Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const { if (xsi) { XFree(xsi); } + } else { + int count = XScreenCount(x11_display); + if (p_screen < count) { + Window root = XRootWindow(x11_display, p_screen); + XWindowAttributes xwa; + XGetWindowAttributes(x11_display, root, &xwa); + rect.position.x = xwa.x; + rect.position.y = xwa.y; + rect.size.width = xwa.width; + rect.size.height = xwa.height; + } else { + ERR_PRINT("Invalid screen index: " + itos(p_screen) + "(count: " + itos(count) + ")."); + } } return rect; @@ -2130,7 +2143,7 @@ bool DisplayServerX11::window_get_flag(WindowFlags p_flag, WindowID p_window) co unsigned char *data = nullptr; if (XGetWindowProperty(x11_display, wd.x11_window, prop, 0, sizeof(Hints), False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) { if (data && (format == 32) && (len >= 5)) { - borderless = !((Hints *)data)->decorations; + borderless = !(reinterpret_cast<Hints *>(data)->decorations); } if (data) { XFree(data); @@ -2162,7 +2175,7 @@ void DisplayServerX11::window_request_attention(WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); - WindowData &wd = windows[p_window]; + const WindowData &wd = windows[p_window]; // Using EWMH -- Extended Window Manager Hints // // Sets the _NET_WM_STATE_DEMANDS_ATTENTION atom for WM_STATE @@ -2188,7 +2201,7 @@ void DisplayServerX11::window_move_to_foreground(WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); - WindowData &wd = windows[p_window]; + const WindowData &wd = windows[p_window]; XEvent xev; Atom net_active_window = XInternAtom(x11_display, "_NET_ACTIVE_WINDOW", False); @@ -2534,10 +2547,9 @@ DisplayServerX11::Property DisplayServerX11::_read_property(Display *p_display, unsigned long bytes_after = 0; unsigned char *ret = nullptr; - int read_bytes = 1024; - // Keep trying to read the property until there are no bytes unread. if (p_property != None) { + int read_bytes = 1024; do { if (ret != nullptr) { XFree(ret); @@ -2557,7 +2569,7 @@ DisplayServerX11::Property DisplayServerX11::_read_property(Display *p_display, return p; } -static Atom pick_target_from_list(Display *p_display, Atom *p_list, int p_count) { +static Atom pick_target_from_list(Display *p_display, const Atom *p_list, int p_count) { static const char *target_type = "text/uri-list"; for (int i = 0; i < p_count; i++) { diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index bf142f8804..b73d4dc626 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -242,6 +242,91 @@ bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) { return p_feature == "pc"; } +uint64_t OS_LinuxBSD::get_embedded_pck_offset() const { + Ref<FileAccess> f = FileAccess::open(get_executable_path(), FileAccess::READ); + if (f.is_null()) { + return 0; + } + + // Read and check ELF magic number. + { + uint32_t magic = f->get_32(); + if (magic != 0x464c457f) { // 0x7F + "ELF" + return 0; + } + } + + // Read program architecture bits from class field. + int bits = f->get_8() * 32; + + // Get info about the section header table. + int64_t section_table_pos; + int64_t section_header_size; + if (bits == 32) { + section_header_size = 40; + f->seek(0x20); + section_table_pos = f->get_32(); + f->seek(0x30); + } else { // 64 + section_header_size = 64; + f->seek(0x28); + section_table_pos = f->get_64(); + f->seek(0x3c); + } + int num_sections = f->get_16(); + int string_section_idx = f->get_16(); + + // Load the strings table. + uint8_t *strings; + { + // Jump to the strings section header. + f->seek(section_table_pos + string_section_idx * section_header_size); + + // Read strings data size and offset. + int64_t string_data_pos; + int64_t string_data_size; + if (bits == 32) { + f->seek(f->get_position() + 0x10); + string_data_pos = f->get_32(); + string_data_size = f->get_32(); + } else { // 64 + f->seek(f->get_position() + 0x18); + string_data_pos = f->get_64(); + string_data_size = f->get_64(); + } + + // Read strings data. + f->seek(string_data_pos); + strings = (uint8_t *)memalloc(string_data_size); + if (!strings) { + return 0; + } + f->get_buffer(strings, string_data_size); + } + + // Search for the "pck" section. + int64_t off = 0; + for (int i = 0; i < num_sections; ++i) { + int64_t section_header_pos = section_table_pos + i * section_header_size; + f->seek(section_header_pos); + + uint32_t name_offset = f->get_32(); + if (strcmp((char *)strings + name_offset, "pck") == 0) { + if (bits == 32) { + f->seek(section_header_pos + 0x10); + off = f->get_32(); + } else { // 64 + f->seek(section_header_pos + 0x18); + off = f->get_64(); + } + break; + } + } + memfree(strings); + + return off; +} + String OS_LinuxBSD::get_config_path() const { if (has_environment("XDG_CONFIG_HOME")) { if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) { diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h index 7b912ddee3..3f97b86eae 100644 --- a/platform/linuxbsd/os_linuxbsd.h +++ b/platform/linuxbsd/os_linuxbsd.h @@ -78,6 +78,8 @@ public: virtual MainLoop *get_main_loop() const override; + virtual uint64_t get_embedded_pck_offset() const override; + virtual String get_config_path() const override; virtual String get_data_path() const override; virtual String get_cache_path() const override; diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 917a0af90b..4c91163d2b 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -54,16 +54,23 @@ Error EditorExportPlatformWindows::_export_debug_script(const Ref<EditorExportPr } Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { - Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, p_path, p_flags); - - if (err != OK) { - return err; + String pck_path = p_path; + if (p_preset->get("binary_format/embed_pck")) { + pck_path = p_path.get_basename() + ".tmp"; + } + Error err = EditorExportPlatformPC::prepare_template(p_preset, p_debug, pck_path, p_flags); + if (p_preset->get("application/modify_resources") && err == OK) { + err = _rcedit_add_data(p_preset, pck_path); + } + if (err == OK) { + err = EditorExportPlatformPC::export_project_data(p_preset, p_debug, pck_path, p_flags); } - - _rcedit_add_data(p_preset, p_path); - if (p_preset->get("codesign/enable") && err == OK) { - err = _code_sign(p_preset, p_path); + err = _code_sign(p_preset, pck_path); + } + if (p_preset->get("binary_format/embed_pck") && err == OK) { + Ref<DirAccess> tmp_dir = DirAccess::create_for_path(p_path.get_base_dir()); + err = tmp_dir->rename(pck_path, p_path); } String app_name; @@ -117,6 +124,7 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/description"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray())); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/modify_resources"), true)); 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.0"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), "")); @@ -127,17 +135,20 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), "")); } -void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path) { +Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path) { 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; + return ERR_FILE_NOT_FOUND; } if (!FileAccess::exists(rcedit_path)) { ERR_PRINT("Could not find rcedit executable at " + rcedit_path + ", no icon or app information data will be included."); - return; + return ERR_FILE_NOT_FOUND; + } + if (rcedit_path.is_empty()) { + rcedit_path = "rcedit"; // try to run signtool from PATH } #ifndef WINDOWS_ENABLED @@ -146,7 +157,7 @@ void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> if (!wine_path.is_empty() && !FileAccess::exists(wine_path)) { ERR_PRINT("Could not find wine executable at " + wine_path + ", no icon or app information data will be included."); - return; + return ERR_FILE_NOT_FOUND; } if (wine_path.is_empty()) { @@ -204,13 +215,22 @@ void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> args.push_back(trademarks); } -#ifdef WINDOWS_ENABLED - OS::get_singleton()->execute(rcedit_path, args); -#else +#ifndef WINDOWS_ENABLED // On non-Windows we need WINE to run rcedit args.push_front(rcedit_path); - OS::get_singleton()->execute(wine_path, args); + rcedit_path = wine_path; #endif + + String str; + Error err = OS::get_singleton()->execute(rcedit_path, args, &str, nullptr, true); + ERR_FAIL_COND_V(err != OK, err); + print_line("rcedit (" + p_path + "): " + str); + + if (str.find("Fatal error") != -1) { + return FAILED; + } + + return OK; } Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) { @@ -417,6 +437,10 @@ bool EditorExportPlatformWindows::can_export(const Ref<EditorExportPreset> &p_pr Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) const { // Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data + if (p_embedded_size + p_embedded_start >= 0x100000000) { // Check for total executable size + ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Windows executables cannot be >= 4 GiB."); + } + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ_WRITE); if (f.is_null()) { return ERR_CANT_OPEN; diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 39d1cf4c77..c33c7f1f63 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -38,7 +38,7 @@ #include "platform/windows/logo.gen.h" class EditorExportPlatformWindows : public EditorExportPlatformPC { - void _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path); + Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path); Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path); Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path); diff --git a/platform/windows/godot_windows.cpp b/platform/windows/godot_windows.cpp index ad4e3ae77c..8de3ef294a 100644 --- a/platform/windows/godot_windows.cpp +++ b/platform/windows/godot_windows.cpp @@ -39,7 +39,18 @@ #ifndef TOOLS_ENABLED #if defined _MSC_VER #pragma section("pck", read) -__declspec(allocate("pck")) static const char dummy[8] = { 0 }; +__declspec(allocate("pck")) static char dummy[8] = { 0 }; + +// Dummy function to prevent LTO from discarding "pck" section. +extern "C" char *__cdecl pck_section_dummy_call() { + return &dummy[0]; +}; +#if defined _AMD64_ +#pragma comment(linker, "/include:pck_section_dummy_call") +#elif defined _X86_ +#pragma comment(linker, "/include:_pck_section_dummy_call") +#endif + #elif defined __GNUC__ static const char dummy[8] __attribute__((section("pck"), used)) = { 0 }; #endif @@ -140,11 +151,6 @@ int widechar_main(int argc, wchar_t **argv) { setlocale(LC_CTYPE, ""); -#ifndef TOOLS_ENABLED - // Workaround to prevent LTCG (MSVC LTO) from removing "pck" section - const char *dummy_guard = dummy; -#endif - char **argv_utf8 = new char *[argc]; for (int i = 0; i < argc; ++i) { diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index b4669e452a..8755bc65dc 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -686,6 +686,58 @@ MainLoop *OS_Windows::get_main_loop() const { return main_loop; } +uint64_t OS_Windows::get_embedded_pck_offset() const { + Ref<FileAccess> f = FileAccess::open(get_executable_path(), FileAccess::READ); + if (f.is_null()) { + return 0; + } + + // Process header. + { + f->seek(0x3c); + uint32_t pe_pos = f->get_32(); + + f->seek(pe_pos); + uint32_t magic = f->get_32(); + if (magic != 0x00004550) { + return 0; + } + } + + int num_sections; + { + int64_t header_pos = f->get_position(); + + f->seek(header_pos + 2); + num_sections = f->get_16(); + f->seek(header_pos + 16); + uint16_t opt_header_size = f->get_16(); + + // Skip rest of header + optional header to go to the section headers. + f->seek(f->get_position() + 2 + opt_header_size); + } + int64_t section_table_pos = f->get_position(); + + // Search for the "pck" section. + int64_t off = 0; + for (int i = 0; i < num_sections; ++i) { + int64_t section_header_pos = section_table_pos + i * 40; + f->seek(section_header_pos); + + uint8_t section_name[9]; + f->get_buffer(section_name, 8); + section_name[8] = '\0'; + + if (strcmp((char *)section_name, "pck") == 0) { + f->seek(section_header_pos + 20); + off = f->get_32(); + break; + } + } + + return off; +} + String OS_Windows::get_config_path() const { // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. if (has_environment("XDG_CONFIG_HOME")) { diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index adeecf37c5..370cb77fde 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -144,6 +144,8 @@ public: virtual int get_processor_count() const override; virtual String get_processor_name() const override; + virtual uint64_t get_embedded_pck_offset() const override; + virtual String get_config_path() const override; virtual String get_data_path() const override; virtual String get_cache_path() const override; diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index c69eeb52a8..04518dff97 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -287,6 +287,15 @@ bool GPUParticles2D::get_fractional_delta() const { return fractional_delta; } +void GPUParticles2D::set_interpolate(bool p_enable) { + interpolate = p_enable; + RS::get_singleton()->particles_set_interpolate(particles, p_enable); +} + +bool GPUParticles2D::get_interpolate() const { + return interpolate; +} + TypedArray<String> GPUParticles2D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); @@ -543,6 +552,7 @@ void GPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &GPUParticles2D::set_use_local_coordinates); ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &GPUParticles2D::set_fixed_fps); ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &GPUParticles2D::set_fractional_delta); + ClassDB::bind_method(D_METHOD("set_interpolate", "enable"), &GPUParticles2D::set_interpolate); ClassDB::bind_method(D_METHOD("set_process_material", "material"), &GPUParticles2D::set_process_material); ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &GPUParticles2D::set_speed_scale); ClassDB::bind_method(D_METHOD("set_collision_base_size", "size"), &GPUParticles2D::set_collision_base_size); @@ -558,6 +568,7 @@ void GPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &GPUParticles2D::get_use_local_coordinates); ClassDB::bind_method(D_METHOD("get_fixed_fps"), &GPUParticles2D::get_fixed_fps); ClassDB::bind_method(D_METHOD("get_fractional_delta"), &GPUParticles2D::get_fractional_delta); + ClassDB::bind_method(D_METHOD("get_interpolate"), &GPUParticles2D::get_interpolate); ClassDB::bind_method(D_METHOD("get_process_material"), &GPUParticles2D::get_process_material); ClassDB::bind_method(D_METHOD("get_speed_scale"), &GPUParticles2D::get_speed_scale); ClassDB::bind_method(D_METHOD("get_collision_base_size"), &GPUParticles2D::get_collision_base_size); @@ -601,6 +612,7 @@ void GPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interpolate"), "set_interpolate", "get_interpolate"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_collision_base_size", "get_collision_base_size"); @@ -644,6 +656,7 @@ GPUParticles2D::GPUParticles2D() { set_lifetime(1); set_fixed_fps(0); set_fractional_delta(true); + set_interpolate(true); set_pre_process_time(0); set_explosiveness_ratio(0); set_randomness_ratio(0); diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index fc95ae27b2..852270dd3c 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -58,6 +58,7 @@ private: bool local_coords; int fixed_fps; bool fractional_delta; + bool interpolate = true; #ifdef TOOLS_ENABLED bool show_visibility_rect; #endif @@ -133,6 +134,9 @@ public: void set_fractional_delta(bool p_enable); bool get_fractional_delta() const; + void set_interpolate(bool p_enable); + bool get_interpolate() const; + void set_draw_order(DrawOrder p_order); DrawOrder get_draw_order() const; diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index aa68349329..a21cb7db62 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -311,7 +311,7 @@ void PathFollow2D::set_offset(real_t p_offset) { if (path->get_curve().is_valid()) { real_t path_length = path->get_curve()->get_baked_length(); - if (loop) { + if (loop && path_length) { offset = Math::fposmod(offset, path_length); if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) { offset = path_length; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index cbbadf1178..cab57146b1 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -2143,7 +2143,7 @@ void TileMap::set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPat TypedArray<Vector2i> used_cells = p_pattern->get_used_cells(); for (int i = 0; i < used_cells.size(); i++) { Vector2i coords = map_pattern(p_position, used_cells[i], p_pattern); - set_cell(p_layer, coords, p_pattern->get_cell_source_id(coords), p_pattern->get_cell_atlas_coords(coords), p_pattern->get_cell_alternative_tile(coords)); + set_cell(p_layer, coords, p_pattern->get_cell_source_id(used_cells[i]), p_pattern->get_cell_atlas_coords(used_cells[i]), p_pattern->get_cell_alternative_tile(used_cells[i])); } } @@ -2512,10 +2512,10 @@ void TileMap::_set_tile_data(int p_layer, const Vector<int> &p_data) { uint32_t v = decode_uint32(&local[4]); // Extract the transform flags that used to be in the tilemap. - bool flip_h = v & (1 << 29); - bool flip_v = v & (1 << 30); - bool transpose = v & (1 << 31); - v &= (1 << 29) - 1; + bool flip_h = v & (1UL << 29); + bool flip_v = v & (1UL << 30); + bool transpose = v & (1UL << 31); + v &= (1UL << 29) - 1; // Extract autotile/atlas coords. int16_t coord_x = 0; diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp index 7a5cb26a29..4981125057 100644 --- a/scene/3d/path_3d.cpp +++ b/scene/3d/path_3d.cpp @@ -310,7 +310,7 @@ void PathFollow3D::set_offset(real_t p_offset) { if (path->get_curve().is_valid()) { real_t path_length = path->get_curve()->get_baked_length(); - if (loop) { + if (loop && path_length) { offset = Math::fposmod(offset, path_length); if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) { offset = path_length; diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 783edf7fc6..9e403a6ecd 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -509,6 +509,7 @@ void Skeleton3D::add_bone(const String &p_name) { bones.push_back(b); process_order_dirty = true; version++; + rest_dirty = true; _make_dirty(); update_gizmos(); } @@ -567,6 +568,7 @@ void Skeleton3D::set_bone_parent(int p_bone, int p_parent) { bones.write[p_bone].parent = p_parent; process_order_dirty = true; + rest_dirty = true; _make_dirty(); } @@ -585,6 +587,7 @@ void Skeleton3D::unparent_bone_and_rest(int p_bone) { bones.write[p_bone].parent = -1; process_order_dirty = true; + rest_dirty = true; _make_dirty(); } @@ -607,6 +610,7 @@ void Skeleton3D::set_bone_children(int p_bone, Vector<int> p_children) { bones.write[p_bone].child_bones = p_children; process_order_dirty = true; + rest_dirty = true; _make_dirty(); } @@ -616,6 +620,7 @@ void Skeleton3D::add_bone_child(int p_bone, int p_child) { bones.write[p_bone].child_bones.push_back(p_child); process_order_dirty = true; + rest_dirty = true; _make_dirty(); } @@ -631,6 +636,7 @@ void Skeleton3D::remove_bone_child(int p_bone, int p_child) { } process_order_dirty = true; + rest_dirty = true; _make_dirty(); } @@ -643,6 +649,7 @@ void Skeleton3D::set_bone_rest(int p_bone, const Transform3D &p_rest) { ERR_FAIL_INDEX(p_bone, bone_size); bones.write[p_bone].rest = p_rest; + rest_dirty = true; _make_dirty(); } Transform3D Skeleton3D::get_bone_rest(int p_bone) const { @@ -651,6 +658,14 @@ Transform3D Skeleton3D::get_bone_rest(int p_bone) const { return bones[p_bone].rest; } +Transform3D Skeleton3D::get_bone_global_rest(int p_bone) const { + const int bone_size = bones.size(); + ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); + if (rest_dirty) { + const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); + } + return bones[p_bone].global_rest; +} void Skeleton3D::set_bone_enabled(int p_bone, bool p_enabled) { const int bone_size = bones.size(); @@ -1058,6 +1073,9 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { b.pose_global_no_override = b.pose_global; } } + if (rest_dirty) { + b.global_rest = b.parent >= 0 ? bonesptr[b.parent].global_rest * b.rest : b.rest; + } if (b.local_pose_override_amount >= CMP_EPSILON) { Transform3D override_local_pose; @@ -1088,6 +1106,7 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { emit_signal(SceneStringNames::get_singleton()->bone_pose_changed, current_bone_idx); } + rest_dirty = false; } // Helper functions @@ -1206,6 +1225,7 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_rest", "bone_idx"), &Skeleton3D::get_bone_rest); ClassDB::bind_method(D_METHOD("set_bone_rest", "bone_idx", "rest"), &Skeleton3D::set_bone_rest); + ClassDB::bind_method(D_METHOD("get_bone_global_rest", "bone_idx"), &Skeleton3D::get_bone_global_rest); ClassDB::bind_method(D_METHOD("create_skin_from_rest_transforms"), &Skeleton3D::create_skin_from_rest_transforms); ClassDB::bind_method(D_METHOD("register_skin", "skin"), &Skeleton3D::register_skin); diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index 279c3e49a2..f8c9fa2c96 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -77,6 +77,7 @@ private: int parent; Transform3D rest; + Transform3D global_rest; _FORCE_INLINE_ void update_pose_cache() { if (pose_cache_dirty) { @@ -142,6 +143,7 @@ private: void _make_dirty(); bool dirty = false; + bool rest_dirty = false; bool show_rest_only = false; @@ -198,6 +200,7 @@ public: void set_bone_rest(int p_bone, const Transform3D &p_rest); Transform3D get_bone_rest(int p_bone) const; + Transform3D get_bone_global_rest(int p_bone) const; Transform3D get_bone_global_pose(int p_bone) const; Transform3D get_bone_global_pose_no_override(int p_bone) const; diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index d541dd5f37..6a8fa9327c 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -563,7 +563,7 @@ void Sprite3D::_draw() { value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; if (t.d > 0) { - value |= 3 << 30; + value |= 3UL << 30; } v_tangent = value; } @@ -926,7 +926,7 @@ void AnimatedSprite3D::_draw() { value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; if (t.d > 0) { - value |= 3 << 30; + value |= 3UL << 30; } v_tangent = value; } diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index bda3868fbb..d6ac5ccf30 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -777,8 +777,8 @@ Vector<int> Voxelizer::get_voxel_gi_level_cell_count() const { /* dt of 1d function using squared distance */ static void edt(float *f, int stride, int n) { float *d = (float *)alloca(sizeof(float) * n + sizeof(int) * n + sizeof(float) * (n + 1)); - int *v = (int *)&(d[n]); - float *z = (float *)&v[n]; + int *v = reinterpret_cast<int *>(&(d[n])); + float *z = reinterpret_cast<float *>(&v[n]); int k = 0; v[0] = 0; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index f5236adbad..424716e002 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -541,9 +541,9 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { player->get_animation_list(&sname); Ref<Animation> reset_anim; - bool has_reset_anim = player->has_animation("RESET"); + bool has_reset_anim = player->has_animation(SceneStringNames::get_singleton()->RESET); if (has_reset_anim) { - reset_anim = player->get_animation("RESET"); + reset_anim = player->get_animation(SceneStringNames::get_singleton()->RESET); } for (const StringName &E : sname) { Ref<Animation> anim = player->get_animation(E); diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index 42adc1ea02..3192f5f7cd 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -114,9 +114,8 @@ void RootMotionView::_notification(int p_what) { first = false; transform.orthonormalize(); //don't want scale, too imprecise - transform.affine_invert(); - accumulated = transform * accumulated; + accumulated = accumulated * transform; accumulated.origin.x = Math::fposmod(accumulated.origin.x, cell_size); if (zero_y) { accumulated.origin.y = 0; @@ -134,9 +133,9 @@ void RootMotionView::_notification(int p_what) { Vector3 from(i * cell_size, 0, j * cell_size); Vector3 from_i((i + 1) * cell_size, 0, j * cell_size); Vector3 from_j(i * cell_size, 0, (j + 1) * cell_size); - from = accumulated.xform(from); - from_i = accumulated.xform(from_i); - from_j = accumulated.xform(from_j); + from = accumulated.xform_inv(from); + from_i = accumulated.xform_inv(from_i); + from_j = accumulated.xform_inv(from_j); Color c = color, c_i = color, c_j = color; c.a *= MAX(0, 1.0 - from.length() / radius); diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index ccc878a6ec..97229ea89b 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -152,10 +152,6 @@ bool Tween::is_running() { return running; } -void Tween::set_valid(bool p_valid) { - valid = p_valid; -} - bool Tween::is_valid() { return valid; } @@ -648,7 +644,7 @@ void Tween::_bind_methods() { ClassDB::bind_method(D_METHOD("parallel"), &Tween::parallel); ClassDB::bind_method(D_METHOD("chain"), &Tween::chain); - ClassDB::bind_method(D_METHOD("interpolate_value", "initial_value", "delta_value", "elapsed_time", "duration", "trans_type", "ease_type"), &Tween::interpolate_variant); + ClassDB::bind_static_method("Tween", D_METHOD("interpolate_value", "initial_value", "delta_value", "elapsed_time", "duration", "trans_type", "ease_type"), &Tween::interpolate_variant); ADD_SIGNAL(MethodInfo("step_finished", PropertyInfo(Variant::INT, "idx"))); ADD_SIGNAL(MethodInfo("loop_finished", PropertyInfo(Variant::INT, "loop_count"))); @@ -679,6 +675,14 @@ void Tween::_bind_methods() { BIND_ENUM_CONSTANT(EASE_OUT_IN); } +Tween::Tween() { + ERR_FAIL_MSG("Tween can't be created directly. Use create_tween() method."); +} + +Tween::Tween(bool p_valid) { + valid = p_valid; +} + Ref<PropertyTweener> PropertyTweener::from(Variant p_value) { initial_val = p_value; do_continue = false; diff --git a/scene/animation/tween.h b/scene/animation/tween.h index e28a499259..5c1567d510 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -139,7 +139,6 @@ public: void kill(); bool is_running(); - void set_valid(bool p_valid); bool is_valid(); void clear(); @@ -160,8 +159,8 @@ public: Ref<Tween> parallel(); Ref<Tween> chain(); - real_t run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d); - Variant interpolate_variant(Variant p_initial_val, Variant p_delta_val, float p_time, float p_duration, Tween::TransitionType p_trans, Tween::EaseType p_ease); + static real_t run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d); + static Variant interpolate_variant(Variant p_initial_val, Variant p_delta_val, float p_time, float p_duration, Tween::TransitionType p_trans, Tween::EaseType p_ease); Variant calculate_delta_value(Variant p_intial_val, Variant p_final_val); bool step(float p_delta); @@ -169,7 +168,8 @@ public: Node *get_bound_node() const; float get_total_time() const; - Tween() {} + Tween(); + Tween(bool p_valid); }; VARIANT_ENUM_CAST(Tween::TweenPauseMode); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 25e266c38e..f1c0260dd5 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -653,21 +653,10 @@ void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg } Ref<MultiplayerAPI> Node::get_multiplayer() const { - if (multiplayer.is_valid()) { - return multiplayer; - } if (!is_inside_tree()) { return Ref<MultiplayerAPI>(); } - return get_tree()->get_multiplayer(); -} - -Ref<MultiplayerAPI> Node::get_custom_multiplayer() const { - return multiplayer; -} - -void Node::set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { - multiplayer = p_multiplayer; + return get_tree()->get_multiplayer(get_path()); } Vector<Multiplayer::RPCConfig> Node::get_node_rpc_methods() const { @@ -2892,8 +2881,6 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("is_multiplayer_authority"), &Node::is_multiplayer_authority); ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer); - ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer); - ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer); ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "call_local", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(false), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description); @@ -2999,7 +2986,6 @@ void Node::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "scene_file_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_scene_file_path", "get_scene_file_path"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_owner", "get_owner"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "", "get_multiplayer"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_custom_multiplayer", "get_custom_multiplayer"); ADD_GROUP("Process", "process_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,When Paused,Always,Disabled"), "set_process_mode", "get_process_mode"); diff --git a/scene/main/node.h b/scene/main/node.h index 923d03dcfe..fb84aabb62 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -515,8 +515,6 @@ public: void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); Ref<MultiplayerAPI> get_multiplayer() const; - Ref<MultiplayerAPI> get_custom_multiplayer() const; - void set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer); Node(); ~Node(); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 151239c9e7..82f18d1a42 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -438,6 +438,10 @@ bool SceneTree::process(double p_time) { if (multiplayer_poll) { multiplayer->poll(); + const NodePath *rpath = nullptr; + while ((rpath = custom_multiplayers.next(rpath))) { + custom_multiplayers[*rpath]->poll(); + } } emit_signal(SNAME("process_frame")); @@ -1113,9 +1117,7 @@ Ref<SceneTreeTimer> SceneTree::create_timer(double p_delay_sec, bool p_process_a } Ref<Tween> SceneTree::create_tween() { - Ref<Tween> tween; - tween.instantiate(); - tween->set_valid(true); + Ref<Tween> tween = memnew(Tween(true)); tweens.push_back(tween); return tween; } @@ -1133,8 +1135,51 @@ Array SceneTree::get_processed_tweens() { return ret; } -Ref<MultiplayerAPI> SceneTree::get_multiplayer() const { - return multiplayer; +Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const { + Ref<MultiplayerAPI> out = multiplayer; + const NodePath *spath = nullptr; + while ((spath = custom_multiplayers.next(spath))) { + const Vector<StringName> snames = (*spath).get_names(); + const Vector<StringName> tnames = p_for_path.get_names(); + if (tnames.size() < snames.size()) { + continue; + } + const StringName *sptr = snames.ptr(); + const StringName *nptr = tnames.ptr(); + bool valid = true; + for (int i = 0; i < snames.size(); i++) { + if (sptr[i] != nptr[i]) { + valid = false; + break; + } + } + if (valid) { + out = custom_multiplayers[*spath]; + break; + } + } + return out; +} + +void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path) { + if (p_root_path.is_empty()) { + ERR_FAIL_COND(!p_multiplayer.is_valid()); + if (multiplayer.is_valid()) { + multiplayer->set_root_path(NodePath()); + } + multiplayer = p_multiplayer; + multiplayer->set_root_path("/" + root->get_name()); + } else { + if (p_multiplayer.is_valid()) { + custom_multiplayers[p_root_path] = p_multiplayer; + p_multiplayer->set_root_path(p_root_path); + } else { + if (custom_multiplayers.has(p_root_path)) { + custom_multiplayers[p_root_path]->set_root_path(NodePath()); + custom_multiplayers.erase(p_root_path); + } + } + } } void SceneTree::set_multiplayer_poll_enabled(bool p_enabled) { @@ -1145,13 +1190,6 @@ bool SceneTree::is_multiplayer_poll_enabled() const { return multiplayer_poll; } -void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { - ERR_FAIL_COND(!p_multiplayer.is_valid()); - - multiplayer = p_multiplayer; - multiplayer->set_root_path("/" + root->get_name()); -} - void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("get_root"), &SceneTree::get_root); ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group); @@ -1214,8 +1252,8 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("_change_scene"), &SceneTree::_change_scene); - ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer"), &SceneTree::set_multiplayer); - ClassDB::bind_method(D_METHOD("get_multiplayer"), &SceneTree::get_multiplayer); + ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer", "root_path"), &SceneTree::set_multiplayer, DEFVAL(NodePath())); + ClassDB::bind_method(D_METHOD("get_multiplayer", "for_path"), &SceneTree::get_multiplayer, DEFVAL(NodePath())); ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled); ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled); @@ -1225,7 +1263,6 @@ void SceneTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_edited_scene_root", "get_edited_scene_root"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_current_scene", "get_current_scene"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_root"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_multiplayer", "get_multiplayer"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled"); ADD_SIGNAL(MethodInfo("tree_changed")); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 705ca6ebd3..9d7757e0a3 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -159,6 +159,7 @@ private: ///network/// Ref<MultiplayerAPI> multiplayer; + HashMap<NodePath, Ref<MultiplayerAPI>> custom_multiplayers; bool multiplayer_poll = true; static SceneTree *singleton; @@ -351,10 +352,10 @@ public: //network API - Ref<MultiplayerAPI> get_multiplayer() const; + Ref<MultiplayerAPI> get_multiplayer(const NodePath &p_for_path = NodePath()) const; + void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path = NodePath()); void set_multiplayer_poll_enabled(bool p_enabled); bool is_multiplayer_poll_enabled() const; - void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer); static void add_idle_callback(IdleCallback p_callback); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 8b1a4680d2..6feccb7eec 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1045,7 +1045,9 @@ void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio Rect2i popup_rect; popup_rect.size = Vector2i(MIN(size_ratio.x, p_size.x), MIN(size_ratio.y, p_size.y)); - popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + if (parent_rect != Rect2()) { + popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + } popup(popup_rect); } @@ -1069,7 +1071,10 @@ void Window::popup_centered(const Size2i &p_minsize) { Size2 contents_minsize = _get_contents_minimum_size(); popup_rect.size.x = MAX(p_minsize.x, contents_minsize.x); popup_rect.size.y = MAX(p_minsize.y, contents_minsize.y); - popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + + if (parent_rect != Rect2()) { + popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + } popup(popup_rect); } @@ -1091,8 +1096,10 @@ void Window::popup_centered_ratio(float p_ratio) { } Rect2i popup_rect; - popup_rect.size = parent_rect.size * p_ratio; - popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + if (parent_rect != Rect2()) { + popup_rect.size = parent_rect.size * p_ratio; + popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; + } popup(popup_rect); } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index e421cdc1f8..6c0192cf44 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -1109,6 +1109,9 @@ void initialize_theme() { TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)GLOBAL_DEF_RST("gui/theme/default_font_subpixel_positioning", TextServer::SUBPIXEL_POSITIONING_AUTO); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_subpixel_positioning", PropertyInfo(Variant::INT, "gui/theme/default_font_subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + const bool font_msdf = GLOBAL_DEF_RST("gui/theme/default_font_multichannel_signed_distance_field", false); + const bool font_generate_mipmaps = GLOBAL_DEF_RST("gui/theme/default_font_generate_mipmaps", false); + Ref<Font> font; if (!font_path.is_empty()) { font = ResourceLoader::load(font_path); @@ -1119,7 +1122,7 @@ void initialize_theme() { // Always make the default theme to avoid invalid default font/icon/style in the given theme. if (RenderingServer::get_singleton()) { - make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiased); + make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiased, font_msdf, font_generate_mipmaps); } if (!theme_path.is_empty()) { diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index f059ec2cf6..271cf61171 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -1026,7 +1026,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const default_style = make_flat_stylebox(Color(1, 0.365, 0.365), 4, 4, 4, 4, 0, false, 2); } -void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa) { +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel, TextServer::Hinting p_font_hinting, bool p_font_antialiased, bool p_font_msdf, bool p_font_generate_mipmaps) { Ref<Theme> t; t.instantiate(); @@ -1051,9 +1051,12 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos Ref<FontData> dynamic_font_data; dynamic_font_data.instantiate(); dynamic_font_data->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size); - dynamic_font_data->set_subpixel_positioning(p_subpixel); - dynamic_font_data->set_hinting(p_hinting); - dynamic_font_data->set_antialiased(p_aa); + dynamic_font_data->set_subpixel_positioning(p_font_subpixel); + dynamic_font_data->set_hinting(p_font_hinting); + dynamic_font_data->set_antialiased(p_font_antialiased); + dynamic_font_data->set_multichannel_signed_distance_field(p_font_msdf); + dynamic_font_data->set_generate_mipmaps(p_font_generate_mipmaps); + dynamic_font->add_data(dynamic_font_data); default_font = dynamic_font; diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index a9e21dda3f..f777330a07 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -36,7 +36,7 @@ const int default_font_size = 16; void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); -void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa); +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, bool p_font_antialiased = true, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); void clear_default_theme(); #endif diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp index 28afef8638..044477e744 100644 --- a/scene/resources/immediate_mesh.cpp +++ b/scene/resources/immediate_mesh.cpp @@ -211,7 +211,7 @@ void ImmediateMesh::surface_end() { value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; if (t.d > 0) { - value |= 3 << 30; + value |= 3UL << 30; } *tangent = value; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 4c20e07976..14abe13afa 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -2278,6 +2278,8 @@ Ref<Image> GradientTexture1D::get_image() const { return RenderingServer::get_singleton()->texture_2d_get(texture); } +////////////////// + GradientTexture2D::GradientTexture2D() { _queue_update(); } @@ -2299,7 +2301,8 @@ void GradientTexture2D::set_gradient(Ref<Gradient> p_gradient) { if (gradient.is_valid()) { gradient->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GradientTexture2D::_queue_update)); } - _queue_update(); + _update(); + emit_changed(); } Ref<Gradient> GradientTexture2D::get_gradient() const { diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 63e3af1395..a2459501c8 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -1033,9 +1033,9 @@ void GodotSpace2D::_broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_ return; } - GodotSpace2D *self = (GodotSpace2D *)p_self; + GodotSpace2D *self = static_cast<GodotSpace2D *>(p_self); self->collision_pairs--; - GodotConstraint2D *c = (GodotConstraint2D *)p_data; + GodotConstraint2D *c = static_cast<GodotConstraint2D *>(p_data); memdelete(c); } diff --git a/servers/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp index 02223b83f0..699f515270 100644 --- a/servers/physics_server_2d_wrap_mt.cpp +++ b/servers/physics_server_2d_wrap_mt.cpp @@ -37,7 +37,7 @@ void PhysicsServer2DWrapMT::thread_exit() { } void PhysicsServer2DWrapMT::thread_step(real_t p_delta) { - physics_2d_server->step(p_delta); + physics_server_2d->step(p_delta); step_sem.post(); } @@ -50,7 +50,7 @@ void PhysicsServer2DWrapMT::_thread_callback(void *_instance) { void PhysicsServer2DWrapMT::thread_loop() { server_thread = Thread::get_caller_id(); - physics_2d_server->init(); + physics_server_2d->init(); exit.clear(); step_thread_up.set(); @@ -61,7 +61,7 @@ void PhysicsServer2DWrapMT::thread_loop() { command_queue.flush_all(); // flush all - physics_2d_server->finish(); + physics_server_2d->finish(); } /* EVENT QUEUING */ @@ -71,7 +71,7 @@ void PhysicsServer2DWrapMT::step(real_t p_step) { command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step); } else { command_queue.flush_all(); //flush all pending from other threads - physics_2d_server->step(p_step); + physics_server_2d->step(p_step); } } @@ -83,15 +83,15 @@ void PhysicsServer2DWrapMT::sync() { step_sem.wait(); //must not wait if a step was not issued } } - physics_2d_server->sync(); + physics_server_2d->sync(); } void PhysicsServer2DWrapMT::flush_queries() { - physics_2d_server->flush_queries(); + physics_server_2d->flush_queries(); } void PhysicsServer2DWrapMT::end_sync() { - physics_2d_server->end_sync(); + physics_server_2d->end_sync(); } void PhysicsServer2DWrapMT::init() { @@ -102,7 +102,7 @@ void PhysicsServer2DWrapMT::init() { OS::get_singleton()->delay_usec(1000); } } else { - physics_2d_server->init(); + physics_server_2d->init(); } } @@ -111,13 +111,13 @@ void PhysicsServer2DWrapMT::finish() { command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit); thread.wait_to_finish(); } else { - physics_2d_server->finish(); + physics_server_2d->finish(); } } PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) : command_queue(p_create_thread) { - physics_2d_server = p_contained; + physics_server_2d = p_contained; create_thread = p_create_thread; pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); @@ -132,6 +132,6 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool } PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() { - memdelete(physics_2d_server); + memdelete(physics_server_2d); //finish(); } diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index aa3a8bc04a..ddb071f603 100644 --- a/servers/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -44,7 +44,7 @@ #endif class PhysicsServer2DWrapMT : public PhysicsServer2D { - mutable PhysicsServer2D *physics_2d_server; + mutable PhysicsServer2D *physics_server_2d; mutable CommandQueueMT command_queue; @@ -71,7 +71,7 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D { public: #define ServerName PhysicsServer2D #define ServerNameWrapMT PhysicsServer2DWrapMT -#define server_name physics_2d_server +#define server_name physics_server_2d #define WRITE_ACTION #include "servers/server_wrap_mt_common.h" @@ -96,7 +96,7 @@ public: //these work well, but should be used from the main thread only bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); + return physics_server_2d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); } /* SPACE API */ @@ -111,18 +111,18 @@ public: // this function only works on physics process, errors and returns null otherwise PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); - return physics_2d_server->space_get_direct_state(p_space); + return physics_server_2d->space_get_direct_state(p_space); } FUNC2(space_set_debug_contacts, RID, int); virtual Vector<Vector2> space_get_contacts(RID p_space) const override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector2>()); - return physics_2d_server->space_get_contacts(p_space); + return physics_server_2d->space_get_contacts(p_space); } virtual int space_get_contact_count(RID p_space) const override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0); - return physics_2d_server->space_get_contact_count(p_space); + return physics_server_2d->space_get_contact_count(p_space); } /* AREA API */ @@ -250,20 +250,20 @@ public: FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &); bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override { - return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); + return physics_server_2d->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); } FUNC2(body_set_pickable, RID, bool); bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->body_test_motion(p_body, p_parameters, r_result); + return physics_server_2d->body_test_motion(p_body, p_parameters, r_result); } // this function only works on physics process, errors and returns null otherwise PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); - return physics_2d_server->body_get_direct_state(p_body); + return physics_server_2d->body_get_direct_state(p_body); } /* JOINT API */ @@ -309,11 +309,11 @@ public: virtual void finish() override; virtual bool is_flushing_queries() const override { - return physics_2d_server->is_flushing_queries(); + return physics_server_2d->is_flushing_queries(); } int get_process_info(ProcessInfo p_info) override { - return physics_2d_server->get_process_info(p_info); + return physics_server_2d->get_process_info(p_info); } PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread); diff --git a/servers/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp index 822ca44b72..7faa193ec2 100644 --- a/servers/physics_server_3d_wrap_mt.cpp +++ b/servers/physics_server_3d_wrap_mt.cpp @@ -37,7 +37,7 @@ void PhysicsServer3DWrapMT::thread_exit() { } void PhysicsServer3DWrapMT::thread_step(real_t p_delta) { - physics_3d_server->step(p_delta); + physics_server_3d->step(p_delta); step_sem.post(); } @@ -50,7 +50,7 @@ void PhysicsServer3DWrapMT::_thread_callback(void *_instance) { void PhysicsServer3DWrapMT::thread_loop() { server_thread = Thread::get_caller_id(); - physics_3d_server->init(); + physics_server_3d->init(); exit = false; step_thread_up = true; @@ -61,7 +61,7 @@ void PhysicsServer3DWrapMT::thread_loop() { command_queue.flush_all(); // flush all - physics_3d_server->finish(); + physics_server_3d->finish(); } /* EVENT QUEUING */ @@ -71,7 +71,7 @@ void PhysicsServer3DWrapMT::step(real_t p_step) { command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step); } else { command_queue.flush_all(); //flush all pending from other threads - physics_3d_server->step(p_step); + physics_server_3d->step(p_step); } } @@ -83,15 +83,15 @@ void PhysicsServer3DWrapMT::sync() { step_sem.wait(); //must not wait if a step was not issued } } - physics_3d_server->sync(); + physics_server_3d->sync(); } void PhysicsServer3DWrapMT::flush_queries() { - physics_3d_server->flush_queries(); + physics_server_3d->flush_queries(); } void PhysicsServer3DWrapMT::end_sync() { - physics_3d_server->end_sync(); + physics_server_3d->end_sync(); } void PhysicsServer3DWrapMT::init() { @@ -102,7 +102,7 @@ void PhysicsServer3DWrapMT::init() { OS::get_singleton()->delay_usec(1000); } } else { - physics_3d_server->init(); + physics_server_3d->init(); } } @@ -111,13 +111,13 @@ void PhysicsServer3DWrapMT::finish() { command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit); thread.wait_to_finish(); } else { - physics_3d_server->finish(); + physics_server_3d->finish(); } } PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) : command_queue(p_create_thread) { - physics_3d_server = p_contained; + physics_server_3d = p_contained; create_thread = p_create_thread; pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); @@ -132,6 +132,6 @@ PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool } PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() { - memdelete(physics_3d_server); + memdelete(physics_server_3d); //finish(); } diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index e44f82672d..d4a4ad3132 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -43,7 +43,7 @@ #endif class PhysicsServer3DWrapMT : public PhysicsServer3D { - mutable PhysicsServer3D *physics_3d_server; + mutable PhysicsServer3D *physics_server_3d; mutable CommandQueueMT command_queue; @@ -70,7 +70,7 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D { public: #define ServerName PhysicsServer3D #define ServerNameWrapMT PhysicsServer3DWrapMT -#define server_name physics_3d_server +#define server_name physics_server_3d #define WRITE_ACTION #include "servers/server_wrap_mt_common.h" @@ -100,7 +100,7 @@ public: //these work well, but should be used from the main thread only bool shape_collide(RID p_shape_A, const Transform &p_xform_A, const Vector3 &p_motion_A, RID p_shape_B, const Transform &p_xform_B, const Vector3 &p_motion_B, Vector3 *r_results, int p_result_max, int &r_result_count) { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_3d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); + return physics_server_3d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); } #endif /* SPACE API */ @@ -115,18 +115,18 @@ public: // this function only works on physics process, errors and returns null otherwise PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); - return physics_3d_server->space_get_direct_state(p_space); + return physics_server_3d->space_get_direct_state(p_space); } FUNC2(space_set_debug_contacts, RID, int); virtual Vector<Vector3> space_get_contacts(RID p_space) const override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector3>()); - return physics_3d_server->space_get_contacts(p_space); + return physics_server_3d->space_get_contacts(p_space); } virtual int space_get_contact_count(RID p_space) const override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0); - return physics_3d_server->space_get_contact_count(p_space); + return physics_server_3d->space_get_contact_count(p_space); } /* AREA API */ @@ -256,13 +256,13 @@ public: bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_3d_server->body_test_motion(p_body, p_parameters, r_result); + return physics_server_3d->body_test_motion(p_body, p_parameters, r_result); } // this function only works on physics process, errors and returns null otherwise PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); - return physics_3d_server->body_get_direct_state(p_body); + return physics_server_3d->body_get_direct_state(p_body); } /* SOFT BODY API */ @@ -385,11 +385,11 @@ public: virtual void finish() override; virtual bool is_flushing_queries() const override { - return physics_3d_server->is_flushing_queries(); + return physics_server_3d->is_flushing_queries(); } int get_process_info(ProcessInfo p_info) override { - return physics_3d_server->get_process_info(p_info); + return physics_server_3d->get_process_info(p_info); } PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread); diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 9843492316..f02bf80645 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -85,17 +85,17 @@ ShaderTypes *shader_types = nullptr; PhysicsServer3D *_createGodotPhysics3DCallback() { bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread"); - PhysicsServer3D *physics_server = memnew(GodotPhysicsServer3D(using_threads)); + PhysicsServer3D *physics_server_3d = memnew(GodotPhysicsServer3D(using_threads)); - return memnew(PhysicsServer3DWrapMT(physics_server, using_threads)); + return memnew(PhysicsServer3DWrapMT(physics_server_3d, using_threads)); } PhysicsServer2D *_createGodotPhysics2DCallback() { bool using_threads = GLOBAL_GET("physics/2d/run_on_separate_thread"); - PhysicsServer2D *physics_server = memnew(GodotPhysicsServer2D(using_threads)); + PhysicsServer2D *physics_server_2d = memnew(GodotPhysicsServer2D(using_threads)); - return memnew(PhysicsServer2DWrapMT(physics_server, using_threads)); + return memnew(PhysicsServer2DWrapMT(physics_server_2d, using_threads)); } static bool has_server_feature_callback(const String &p_feature) { diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h index 3855222554..fa58322ea8 100644 --- a/servers/rendering/dummy/rasterizer_scene_dummy.h +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -184,7 +184,7 @@ public: void voxel_gi_set_quality(RS::VoxelGIQuality) override {} void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} + void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {} void set_scene_pass(uint64_t p_pass) override {} diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 93baa9a96f..ace948d149 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -210,7 +210,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c tf.array_layers = view_count; // create a layer for every view tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { + const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { RD::TEXTURE_SAMPLES_1, RD::TEXTURE_SAMPLES_2, RD::TEXTURE_SAMPLES_4, @@ -1124,7 +1124,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con distance = -distance_max; } - if (p_render_data->cam_ortogonal) { + if (p_render_data->cam_orthogonal) { distance = 1.0; } @@ -1815,7 +1815,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering 3D Material"); RD::get_singleton()->draw_command_begin_label("Render 3D Material"); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 37366d3e14..0e588aecb4 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -218,7 +218,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16, INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF, INSTANCE_DATA_FLAGS_FADE_SHIFT = 24, - INSTANCE_DATA_FLAGS_FADE_MASK = 0xFF << INSTANCE_DATA_FLAGS_FADE_SHIFT + INSTANCE_DATA_FLAGS_FADE_MASK = 0xFFUL << INSTANCE_DATA_FLAGS_FADE_SHIFT }; struct SceneState { @@ -611,7 +611,7 @@ protected: virtual void _render_shadow_process() override; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index ade2b976c8..b9f49cf008 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -158,7 +158,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b tf.array_layers = view_count; // create a layer for every view tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { + const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { RD::TEXTURE_SAMPLES_1, RD::TEXTURE_SAMPLES_2, RD::TEXTURE_SAMPLES_4, @@ -977,7 +977,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) { /* */ -void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering 3D Material"); RD::get_singleton()->draw_command_begin_label("Render 3D Material"); @@ -1441,7 +1441,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const distance = -distance_max; } - if (p_render_data->cam_ortogonal) { + if (p_render_data->cam_orthogonal) { distance = 1.0; } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 0ddfe89eea..0a7e973120 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -214,7 +214,7 @@ protected: virtual void _render_shadow_process() override; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 29bc767c86..8c727b2512 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -132,9 +132,9 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve buffers.resize(5); { - const uint8_t *r = polygon_buffer.ptr(); - float *fptr = (float *)r; - uint32_t *uptr = (uint32_t *)r; + uint8_t *r = polygon_buffer.ptrw(); + float *fptr = reinterpret_cast<float *>(r); + uint32_t *uptr = reinterpret_cast<uint32_t *>(r); uint32_t base_offset = 0; { //vertices RD::VertexAttribute vd; @@ -1843,7 +1843,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Ve { uint8_t *vw = geometry.ptrw(); - float *vwptr = (float *)vw; + float *vwptr = reinterpret_cast<float *>(vw); uint8_t *iw = indices.ptrw(); uint16_t *iwptr = (uint16_t *)iw; diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index d8b7d5384e..0a16bf4bd1 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -879,7 +879,7 @@ void RendererSceneGIRD::SDFGI::update_light() { push_constant.process_offset = 0; push_constant.process_increment = 1; } else { - static uint32_t frames_to_update_table[RS::ENV_SDFGI_UPDATE_LIGHT_MAX] = { + static const uint32_t frames_to_update_table[RS::ENV_SDFGI_UPDATE_LIGHT_MAX] = { 1, 2, 4, 8, 16 }; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 535f5ad9c5..26365aafc4 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2391,7 +2391,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende float bokeh_size = camfx->dof_blur_amount * 64.0; if (can_use_storage) { - storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); + storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal); } else { // Set framebuffers. buffers.base_fb = rb->texture_fb; @@ -2406,7 +2406,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende // Set weight buffers. buffers.base_weight_fb = rb->base_weight_fb; - storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); + storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal); } RD::get_singleton()->draw_command_end_label(); } @@ -4998,7 +4998,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_data.cam_transform = p_camera_data->main_transform; render_data.cam_projection = p_camera_data->main_projection; render_data.view_projection[0] = p_camera_data->main_projection; - render_data.cam_ortogonal = p_camera_data->is_ortogonal; + render_data.cam_orthogonal = p_camera_data->is_orthogonal; render_data.view_count = p_camera_data->view_count; for (uint32_t v = 0; v < p_camera_data->view_count; v++) { @@ -5327,8 +5327,8 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, } } -void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { - _render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region); +void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { + _render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region); } void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 3bfe37b413..2b79d8997f 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -51,7 +51,7 @@ struct RenderDataRD { Transform3D cam_transform = Transform3D(); CameraMatrix cam_projection = CameraMatrix(); - bool cam_ortogonal = false; + bool cam_orthogonal = false; // For stereo rendering uint32_t view_count = 1; @@ -115,7 +115,7 @@ protected: virtual void _render_shadow_process() = 0; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0; @@ -1413,7 +1413,7 @@ public: virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; - virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 75c502c666..d939a0d641 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -339,7 +339,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_FLOAT: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); if (p_array_size > 0) { const PackedFloat32Array &a = value; @@ -361,7 +361,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_VEC2: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); if (p_array_size > 0) { const PackedVector2Array &a = value; @@ -385,7 +385,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_VEC3: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); if (p_array_size > 0) { const PackedVector3Array &a = value; @@ -411,7 +411,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_VEC4: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); if (p_array_size > 0) { if (value.get_type() == Variant::PACKED_COLOR_ARRAY) { @@ -491,7 +491,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_MAT2: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); if (p_array_size > 0) { const PackedFloat32Array &a = value; @@ -532,7 +532,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_MAT3: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); if (p_array_size > 0) { const PackedFloat32Array &a = value; @@ -587,7 +587,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_MAT4: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); if (p_array_size > 0) { const PackedFloat32Array &a = value; @@ -748,12 +748,12 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, } } break; case ShaderLanguage::TYPE_FLOAT: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); gui[0] = value[0].real; } break; case ShaderLanguage::TYPE_VEC2: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); for (int i = 0; i < 2; i++) { gui[i] = value[i].real; @@ -761,7 +761,7 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, } break; case ShaderLanguage::TYPE_VEC3: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); for (int i = 0; i < 3; i++) { gui[i] = value[i].real; @@ -769,14 +769,14 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, } break; case ShaderLanguage::TYPE_VEC4: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); for (int i = 0; i < 4; i++) { gui[i] = value[i].real; } } break; case ShaderLanguage::TYPE_MAT2: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); //in std140 members of mat2 are treated as vec4s gui[0] = value[0].real; @@ -789,7 +789,7 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, gui[7] = 0; } break; case ShaderLanguage::TYPE_MAT3: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); gui[0] = value[0].real; gui[1] = value[1].real; @@ -805,7 +805,7 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, gui[11] = 0; } break; case ShaderLanguage::TYPE_MAT4: { - float *gui = (float *)data; + float *gui = reinterpret_cast<float *>(data); for (int i = 0; i < 16; i++) { gui[i] = value[i].real; @@ -1885,7 +1885,7 @@ void MaterialStorage::global_variable_remove(const StringName &p_name) { if (!global_variables.variables.has(p_name)) { return; } - GlobalVariables::Variable &gv = global_variables.variables[p_name]; + const GlobalVariables::Variable &gv = global_variables.variables[p_name]; if (gv.buffer_index >= 0) { global_variables.buffer_usage[gv.buffer_index].elements = 0; @@ -2110,7 +2110,7 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported - ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = { + const ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = { ShaderLanguage::TYPE_MAX, //nil ShaderLanguage::TYPE_BOOL, //bool ShaderLanguage::TYPE_INT, //int diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 8c60264ce3..0f74c591c6 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -50,7 +50,7 @@ MeshStorage::MeshStorage() { buffer.resize(sizeof(float) * 3); { uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; + float *fptr = reinterpret_cast<float *>(w); fptr[0] = 0.0; fptr[1] = 0.0; fptr[2] = 0.0; @@ -62,7 +62,7 @@ MeshStorage::MeshStorage() { buffer.resize(sizeof(float) * 3); { uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; + float *fptr = reinterpret_cast<float *>(w); fptr[0] = 1.0; fptr[1] = 0.0; fptr[2] = 0.0; @@ -74,7 +74,7 @@ MeshStorage::MeshStorage() { buffer.resize(sizeof(float) * 4); { uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; + float *fptr = reinterpret_cast<float *>(w); fptr[0] = 1.0; fptr[1] = 0.0; fptr[2] = 0.0; @@ -87,7 +87,7 @@ MeshStorage::MeshStorage() { buffer.resize(sizeof(float) * 4); { uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; + float *fptr = reinterpret_cast<float *>(w); fptr[0] = 1.0; fptr[1] = 1.0; fptr[2] = 1.0; @@ -100,7 +100,7 @@ MeshStorage::MeshStorage() { buffer.resize(sizeof(float) * 2); { uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; + float *fptr = reinterpret_cast<float *>(w); fptr[0] = 0.0; fptr[1] = 0.0; } @@ -110,7 +110,7 @@ MeshStorage::MeshStorage() { buffer.resize(sizeof(float) * 2); { uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; + float *fptr = reinterpret_cast<float *>(w); fptr[0] = 0.0; fptr[1] = 0.0; } @@ -121,7 +121,7 @@ MeshStorage::MeshStorage() { buffer.resize(sizeof(float) * 4); { uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; + float *fptr = reinterpret_cast<float *>(w); fptr[0] = 0.0; fptr[1] = 0.0; fptr[2] = 0.0; @@ -134,7 +134,7 @@ MeshStorage::MeshStorage() { buffer.resize(sizeof(uint32_t) * 4); { uint8_t *w = buffer.ptrw(); - uint32_t *fptr = (uint32_t *)w; + uint32_t *fptr = reinterpret_cast<uint32_t *>(w); fptr[0] = 0; fptr[1] = 0; fptr[2] = 0; @@ -147,7 +147,7 @@ MeshStorage::MeshStorage() { buffer.resize(sizeof(float) * 4); { uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; + float *fptr = reinterpret_cast<float *>(w); fptr[0] = 0.0; fptr[1] = 0.0; fptr[2] = 0.0; @@ -284,9 +284,9 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) case RS::ARRAY_CUSTOM2: case RS::ARRAY_CUSTOM3: { int idx = i - RS::ARRAY_CUSTOM0; - uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; + const uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; - uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; + const uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; attrib_stride += fmtsize[fmt]; } break; @@ -1098,10 +1098,10 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V vd.offset = attribute_stride; int idx = i - RS::ARRAY_CUSTOM0; - uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; + const uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; - uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; - RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT }; + const uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; + const RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT }; vd.format = fmtrd[fmt]; attribute_stride += fmtsize[fmt]; buffer = s->attribute_buffer; @@ -1238,7 +1238,7 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { if (multimesh->buffer_set) { Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); const uint8_t *r = buffer.ptr(); - const float *data = (const float *)r; + const float *data = reinterpret_cast<const float *>(r); _multimesh_re_create_aabb(multimesh, data, multimesh->instances); } } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 75dd20bdbd..402536de88 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -1722,7 +1722,7 @@ RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_part if (particles_collision->heightfield_texture == RID()) { //create - int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 }; + const int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 }; Size2i size; if (particles_collision->extents.x > particles_collision->extents.z) { size.x = resolutions[particles_collision->heightfield_resolution]; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 55193a45f0..528f381139 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2444,7 +2444,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ Transform3D transform = camera->transform; CameraMatrix projection; bool vaspect = camera->vaspect; - bool is_ortogonal = false; + bool is_orthogonal = false; switch (camera->type) { case Camera::ORTHOGONAL: { @@ -2454,7 +2454,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ camera->znear, camera->zfar, camera->vaspect); - is_ortogonal = true; + is_orthogonal = true; } break; case Camera::PERSPECTIVE: { projection.set_perspective( @@ -2476,7 +2476,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ } break; } - camera_data.set_camera(transform, projection, is_ortogonal, vaspect); + camera_data.set_camera(transform, projection, is_orthogonal, vaspect); } else { // Setup our camera for our XR interface. // We can support multiple views here each with their own camera @@ -2510,7 +2510,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_ RENDER_TIMESTAMP("Update Occlusion Buffer") // For now just cull on the first camera - RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_ortogonal, RendererThreadPool::singleton->thread_work_pool); + RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal, RendererThreadPool::singleton->thread_work_pool); _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info); #endif @@ -2920,7 +2920,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c RENDER_TIMESTAMP("Cull 3D Scene"); - //rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_ortogonal); + //rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_orthogonal); /* STEP 2 - CULL */ @@ -2959,7 +2959,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c scene_render->set_directional_shadow_count(lights_with_shadow.size()); for (int i = 0; i < lights_with_shadow.size(); i++) { - _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect); + _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect); } } @@ -3097,7 +3097,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c ins->transform.origin + cam_xf.basis.get_axis(0) * radius }; - if (!p_camera_data->is_ortogonal) { + if (!p_camera_data->is_orthogonal) { //if using perspetive, map them to near plane for (int j = 0; j < 2; j++) { if (p.distance_to(points[j]) < 0) { @@ -3125,7 +3125,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c base + cam_xf.basis.get_axis(0) * w }; - if (!p_camera_data->is_ortogonal) { + if (!p_camera_data->is_orthogonal) { //if using perspetive, map them to near plane for (int j = 0; j < 2; j++) { if (p.distance_to(points[j]) < 0) { @@ -3156,7 +3156,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) { //must redraw! RENDER_TIMESTAMP("> Render Light3D " + itos(i)); - light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold); + light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold); RENDER_TIMESTAMP("< Render Light3D " + itos(i)); } else { light->shadow_dirty = redraw; @@ -3229,7 +3229,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c render_sdfgi_data[i].instances.clear(); } - // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0; + // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0; } RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) { diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index c802f72fdf..fadece317a 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -30,9 +30,9 @@ #include "renderer_scene_render.h" -void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect) { +void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect) { view_count = 1; - is_ortogonal = p_is_ortogonal; + is_orthogonal = p_is_orthogonal; vaspect = p_vaspect; main_transform = p_transform; @@ -42,11 +42,11 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, view_projection[0] = p_projection; } -void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect) { +void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect) { ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view"); view_count = p_view_count; - is_ortogonal = p_is_ortogonal; + is_orthogonal = p_is_orthogonal; vaspect = p_vaspect; Vector<Plane> planes[2]; diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 0b8734e68c..d43bfb170e 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -234,7 +234,7 @@ public: struct CameraData { // flags uint32_t view_count; - bool is_ortogonal; + bool is_orthogonal; bool vaspect; // Main/center projection @@ -244,13 +244,13 @@ public: Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS]; CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; - void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect); - void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect); + void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect); + void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect); }; virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0; - virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0; virtual void set_scene_pass(uint64_t p_pass) = 0; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index af5da6ae6f..54d1a6fd8d 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -4670,16 +4670,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr = _parse_array_constructor(p_block, p_function_info); } else { DataType datatype; - DataPrecision precision; - bool precision_defined = false; + DataPrecision precision = PRECISION_DEFAULT; if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); - precision_defined = true; tk = _get_token(); } datatype = get_token_datatype(tk.type); + if (precision != PRECISION_DEFAULT && _validate_precision(datatype, precision) != OK) { + return nullptr; + } + tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { @@ -4697,7 +4699,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons OperatorNode *func = alloc_node<OperatorNode>(); func->op = OP_CONSTRUCT; - if (precision_defined) { + if (precision != PRECISION_DEFAULT) { func->return_precision_cache = precision; } @@ -6426,10 +6428,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (!is_struct) { is_struct = shader->structs.has(tk.text); // check again. } - if (is_struct && precision != PRECISION_DEFAULT) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } if (!is_token_nonvoid_datatype(tk.type)) { _set_error(RTR("Expected variable type after precision modifier.")); return ERR_PARSE_ERROR; @@ -6449,6 +6447,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + int array_size = 0; bool fixed_array_size = false; bool first = true; @@ -6600,10 +6602,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (is_token_precision(tk.type)) { precision2 = get_token_precision(tk.type); tk = _get_token(); - if (shader->structs.has(tk.text)) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } if (!is_token_nonvoid_datatype(tk.type)) { _set_error(RTR("Expected data type after precision modifier.")); return ERR_PARSE_ERROR; @@ -6624,6 +6622,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun type2 = get_token_datatype(tk.type); } + if (precision2 != PRECISION_DEFAULT && _validate_precision(type2, precision2) != OK) { + return ERR_PARSE_ERROR; + } + int array_size2 = 0; tk = _get_token(); @@ -7427,6 +7429,25 @@ String ShaderLanguage::_get_qualifier_str(ArgumentQualifier p_qualifier) const { return ""; } +Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_precision) { + switch (p_type) { + case TYPE_STRUCT: { + _set_error(RTR("The precision modifier cannot be used on structs.")); + return FAILED; + } break; + case TYPE_BOOL: + case TYPE_BVEC2: + case TYPE_BVEC3: + case TYPE_BVEC4: { + _set_error(RTR("The precision modifier cannot be used on boolean types.")); + return FAILED; + } break; + default: + break; + } + return OK; +} + Error ShaderLanguage::_validate_datatype(DataType p_type) { if (RenderingServer::get_singleton()->is_low_end()) { bool invalid_type = false; @@ -7608,8 +7629,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } StringName struct_name = ""; bool struct_dt = false; - bool use_precision = false; - DataPrecision precision = DataPrecision::PRECISION_DEFAULT; + DataPrecision precision = PRECISION_DEFAULT; if (tk.type == TK_STRUCT) { _set_error(RTR("Nested structs are not allowed.")); @@ -7618,7 +7638,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); - use_precision = true; tk = _get_token(); } @@ -7630,10 +7649,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } #endif // DEBUG_ENABLED struct_dt = true; - if (use_precision) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } } if (!is_token_datatype(tk.type) && !struct_dt) { @@ -7642,6 +7657,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { type = struct_dt ? TYPE_STRUCT : get_token_datatype(tk.type); + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + if (type == TYPE_VOID || is_sampler_type(type)) { _set_error(vformat(RTR("A '%s' data type is not allowed here."), get_datatype_name(type))); return ERR_PARSE_ERROR; @@ -7762,7 +7781,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } } - bool precision_defined = false; DataPrecision precision = PRECISION_DEFAULT; DataInterpolation interpolation = INTERPOLATION_SMOOTH; DataType type; @@ -7781,16 +7799,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); - precision_defined = true; tk = _get_token(); } if (shader->structs.has(tk.text)) { if (uniform) { - if (precision_defined) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } _set_error(vformat(RTR("The '%s' data type is not supported for uniforms."), "struct")); return ERR_PARSE_ERROR; } else { @@ -7806,6 +7819,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct type = get_token_datatype(tk.type); + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + if (type == TYPE_VOID) { _set_error(vformat(RTR("The '%s' data type is not allowed here."), "void")); return ERR_PARSE_ERROR; @@ -8249,10 +8266,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (shader->structs.has(tk.text)) { - if (precision != PRECISION_DEFAULT) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } is_struct = true; struct_name = tk.text; } else { @@ -8276,6 +8289,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { type = get_token_datatype(tk.type); } + + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + prev_pos = _get_tkpos(); tk = _get_token(); @@ -8652,44 +8670,41 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct break; } - bool is_const = false; + bool param_is_const = false; if (tk.type == TK_CONST) { - is_const = true; + param_is_const = true; tk = _get_token(); } - ArgumentQualifier qualifier = ARGUMENT_QUALIFIER_IN; - + ArgumentQualifier param_qualifier = ARGUMENT_QUALIFIER_IN; if (tk.type == TK_ARG_IN) { - qualifier = ARGUMENT_QUALIFIER_IN; + param_qualifier = ARGUMENT_QUALIFIER_IN; tk = _get_token(); } else if (tk.type == TK_ARG_OUT) { - if (is_const) { + if (param_is_const) { _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "out", "const")); return ERR_PARSE_ERROR; } - qualifier = ARGUMENT_QUALIFIER_OUT; + param_qualifier = ARGUMENT_QUALIFIER_OUT; tk = _get_token(); } else if (tk.type == TK_ARG_INOUT) { - if (is_const) { + if (param_is_const) { _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "inout", "const")); return ERR_PARSE_ERROR; } - qualifier = ARGUMENT_QUALIFIER_INOUT; + param_qualifier = ARGUMENT_QUALIFIER_INOUT; tk = _get_token(); } - DataType ptype; - StringName pname; + DataType param_type; + StringName param_name; StringName param_struct_name; - DataPrecision pprecision = PRECISION_DEFAULT; - bool use_precision = false; + DataPrecision param_precision = PRECISION_DEFAULT; int arg_array_size = 0; if (is_token_precision(tk.type)) { - pprecision = get_token_precision(tk.type); + param_precision = get_token_precision(tk.type); tk = _get_token(); - use_precision = true; } is_struct = false; @@ -8702,10 +8717,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct used_structs[param_struct_name].used = true; } #endif // DEBUG_ENABLED - if (use_precision) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } } if (!is_struct && !is_token_datatype(tk.type)) { @@ -8713,7 +8724,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (qualifier == ARGUMENT_QUALIFIER_OUT || qualifier == ARGUMENT_QUALIFIER_INOUT) { + if (param_qualifier == ARGUMENT_QUALIFIER_OUT || param_qualifier == ARGUMENT_QUALIFIER_INOUT) { if (is_sampler_type(get_token_datatype(tk.type))) { _set_error(RTR("Opaque types cannot be output parameters.")); return ERR_PARSE_ERROR; @@ -8721,18 +8732,22 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (is_struct) { - ptype = TYPE_STRUCT; + param_type = TYPE_STRUCT; } else { - ptype = get_token_datatype(tk.type); - if (_validate_datatype(ptype) != OK) { + param_type = get_token_datatype(tk.type); + if (_validate_datatype(param_type) != OK) { return ERR_PARSE_ERROR; } - if (ptype == TYPE_VOID) { + if (param_type == TYPE_VOID) { _set_error(RTR("Void type not allowed as argument.")); return ERR_PARSE_ERROR; } } + if (param_precision != PRECISION_DEFAULT && _validate_precision(param_type, param_precision) != OK) { + return ERR_PARSE_ERROR; + } + tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { @@ -8747,32 +8762,32 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - pname = tk.text; + param_name = tk.text; ShaderLanguage::IdentifierType itype; - if (_find_identifier(func_node->body, false, builtins, pname, (ShaderLanguage::DataType *)nullptr, &itype)) { + if (_find_identifier(func_node->body, false, builtins, param_name, (ShaderLanguage::DataType *)nullptr, &itype)) { if (itype != IDENTIFIER_FUNCTION) { - _set_redefinition_error(String(pname)); + _set_redefinition_error(String(param_name)); return ERR_PARSE_ERROR; } } - if (has_builtin(p_functions, pname)) { - _set_redefinition_error(String(pname)); + if (has_builtin(p_functions, param_name)) { + _set_redefinition_error(String(param_name)); return ERR_PARSE_ERROR; } FunctionNode::Argument arg; - arg.type = ptype; - arg.name = pname; + arg.type = param_type; + arg.name = param_name; arg.type_str = param_struct_name; - arg.precision = pprecision; - arg.qualifier = qualifier; + arg.precision = param_precision; + arg.qualifier = param_qualifier; arg.tex_argument_check = false; arg.tex_builtin_check = false; arg.tex_argument_filter = FILTER_DEFAULT; arg.tex_argument_repeat = REPEAT_DEFAULT; - arg.is_const = is_const; + arg.is_const = param_is_const; tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 66ae220edf..de6d912a4f 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -1038,6 +1038,7 @@ private: static bool is_const_suffix_lut_initialized; + Error _validate_precision(DataType p_type, DataPrecision p_precision); Error _validate_datatype(DataType p_type); bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b); bool _compare_datatypes_in_nodes(Node *a, Node *b); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index b58e6138eb..c2a6b83485 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -424,7 +424,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; if (src[i * 4 + 3] > 0) { - value |= 3 << 30; + value |= 3UL << 30; } memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4); @@ -440,7 +440,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; if (src[i * 4 + 3] > 0) { - value |= 3 << 30; + value |= 3UL << 30; } memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4); } @@ -1093,7 +1093,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t Vector2 *w = arr_2d.ptrw(); for (int j = 0; j < p_vertex_len; j++) { - const float *v = (const float *)&r[j * vertex_elem_size + offsets[i]]; + const float *v = reinterpret_cast<const float *>(&r[j * vertex_elem_size + offsets[i]]); w[j] = Vector2(v[0], v[1]); } } @@ -1107,7 +1107,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t Vector3 *w = arr_3d.ptrw(); for (int j = 0; j < p_vertex_len; j++) { - const float *v = (const float *)&r[j * vertex_elem_size + offsets[i]]; + const float *v = reinterpret_cast<const float *>(&r[j * vertex_elem_size + offsets[i]]); w[j] = Vector3(v[0], v[1], v[2]); } } @@ -1156,7 +1156,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t Color *w = arr.ptrw(); for (int32_t j = 0; j < p_vertex_len; j++) { - const uint8_t *v = (const uint8_t *)&ar[j * attrib_elem_size + offsets[i]]; + const uint8_t *v = reinterpret_cast<const uint8_t *>(&ar[j * attrib_elem_size + offsets[i]]); w[j] = Color(v[0] / 255.0, v[1] / 255.0, v[2] / 255.0, v[3] / 255.0); } @@ -1170,7 +1170,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t Vector2 *w = arr.ptrw(); for (int j = 0; j < p_vertex_len; j++) { - const float *v = (const float *)&ar[j * attrib_elem_size + offsets[i]]; + const float *v = reinterpret_cast<const float *>(&ar[j * attrib_elem_size + offsets[i]]); w[j] = Vector2(v[0], v[1]); } @@ -1184,7 +1184,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t Vector2 *w = arr.ptrw(); for (int j = 0; j < p_vertex_len; j++) { - const float *v = (const float *)&ar[j * attrib_elem_size + offsets[i]]; + const float *v = reinterpret_cast<const float *>(&ar[j * attrib_elem_size + offsets[i]]); w[j] = Vector2(v[0], v[1]); } @@ -1209,7 +1209,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t uint8_t *w = arr.ptrw(); for (int j = 0; j < p_vertex_len; j++) { - const uint8_t *v = (const uint8_t *)&ar[j * attrib_elem_size + offsets[i]]; + const uint8_t *v = reinterpret_cast<const uint8_t *>(&ar[j * attrib_elem_size + offsets[i]]); memcpy(&w[j * s], v, s); } @@ -1228,7 +1228,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t float *w = arr.ptrw(); for (int j = 0; j < p_vertex_len; j++) { - const float *v = (const float *)&ar[j * attrib_elem_size + offsets[i]]; + const float *v = reinterpret_cast<const float *>(&ar[j * attrib_elem_size + offsets[i]]); memcpy(&w[j * s], v, s * sizeof(float)); } ret[i] = arr; diff --git a/tests/test_main.cpp b/tests/test_main.cpp index dc28a98c97..a059949105 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -160,10 +160,10 @@ struct GodotTestCaseListener : public doctest::IReporter { SignalWatcher *signal_watcher = nullptr; - PhysicsServer3D *physics_3d_server = nullptr; - PhysicsServer2D *physics_2d_server = nullptr; - NavigationServer3D *navigation_3d_server = nullptr; - NavigationServer2D *navigation_2d_server = nullptr; + PhysicsServer3D *physics_server_3d = nullptr; + PhysicsServer2D *physics_server_2d = nullptr; + NavigationServer3D *navigation_server_3d = nullptr; + NavigationServer2D *navigation_server_2d = nullptr; void test_case_start(const doctest::TestCaseData &p_in) override { SignalWatcher::get_singleton()->_clear_signals(); @@ -190,19 +190,19 @@ struct GodotTestCaseListener : public doctest::IReporter { RenderingServerDefault::get_singleton()->init(); RenderingServerDefault::get_singleton()->set_render_loop_enabled(false); - physics_3d_server = PhysicsServer3DManager::new_default_server(); - physics_3d_server->init(); + physics_server_3d = PhysicsServer3DManager::new_default_server(); + physics_server_3d->init(); - physics_2d_server = PhysicsServer2DManager::new_default_server(); - physics_2d_server->init(); + physics_server_2d = PhysicsServer2DManager::new_default_server(); + physics_server_2d->init(); - navigation_3d_server = NavigationServer3DManager::new_default_server(); - navigation_2d_server = memnew(NavigationServer2D); + navigation_server_3d = NavigationServer3DManager::new_default_server(); + navigation_server_2d = memnew(NavigationServer2D); memnew(InputMap); InputMap::get_singleton()->load_default(); - make_default_theme(1.0, Ref<Font>(), TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::HINTING_LIGHT, true); + make_default_theme(1.0, Ref<Font>()); memnew(SceneTree); SceneTree::get_singleton()->initialize(); @@ -225,26 +225,26 @@ struct GodotTestCaseListener : public doctest::IReporter { clear_default_theme(); - if (navigation_3d_server) { - memdelete(navigation_3d_server); - navigation_3d_server = nullptr; + if (navigation_server_3d) { + memdelete(navigation_server_3d); + navigation_server_3d = nullptr; } - if (navigation_2d_server) { - memdelete(navigation_2d_server); - navigation_2d_server = nullptr; + if (navigation_server_2d) { + memdelete(navigation_server_2d); + navigation_server_2d = nullptr; } - if (physics_3d_server) { - physics_3d_server->finish(); - memdelete(physics_3d_server); - physics_3d_server = nullptr; + if (physics_server_3d) { + physics_server_3d->finish(); + memdelete(physics_server_3d); + physics_server_3d = nullptr; } - if (physics_2d_server) { - physics_2d_server->finish(); - memdelete(physics_2d_server); - physics_2d_server = nullptr; + if (physics_server_2d) { + physics_server_2d->finish(); + memdelete(physics_server_2d); + physics_server_2d = nullptr; } if (Input::get_singleton()) { diff --git a/thirdparty/noise/FastNoiseLite.h b/thirdparty/noise/FastNoiseLite.h index 3db344c149..8015bf636a 100644 --- a/thirdparty/noise/FastNoiseLite.h +++ b/thirdparty/noise/FastNoiseLite.h @@ -295,7 +295,7 @@ public: /// Noise output bounded between -1...1 /// </returns> template <typename FNfloat> - float GetNoise(FNfloat x, FNfloat y) + float GetNoise(FNfloat x, FNfloat y) const { Arguments_must_be_floating_point_values<FNfloat>(); @@ -321,7 +321,7 @@ public: /// Noise output bounded between -1...1 /// </returns> template <typename FNfloat> - float GetNoise(FNfloat x, FNfloat y, FNfloat z) + float GetNoise(FNfloat x, FNfloat y, FNfloat z) const { Arguments_must_be_floating_point_values<FNfloat>(); @@ -350,7 +350,7 @@ public: /// noise = GetNoise(x, y)</code> /// </example> template <typename FNfloat> - void DomainWarp(FNfloat& x, FNfloat& y) + void DomainWarp(FNfloat& x, FNfloat& y) const { Arguments_must_be_floating_point_values<FNfloat>(); @@ -377,7 +377,7 @@ public: /// noise = GetNoise(x, y, z)</code> /// </example> template <typename FNfloat> - void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) + void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) const { Arguments_must_be_floating_point_values<FNfloat>(); @@ -528,7 +528,7 @@ private: } - float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) + float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) const { int hash = Hash(seed, xPrimed, yPrimed); hash ^= hash >> 15; @@ -541,7 +541,7 @@ private: } - float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) + float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) const { int hash = Hash(seed, xPrimed, yPrimed, zPrimed); hash ^= hash >> 15; @@ -555,7 +555,7 @@ private: } - void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) + void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) const { int hash = Hash(seed, xPrimed, yPrimed) & (255 << 1); @@ -564,7 +564,7 @@ private: } - void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) + void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) const { int hash = Hash(seed, xPrimed, yPrimed, zPrimed) & (255 << 2); @@ -574,7 +574,7 @@ private: } - void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) + void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) const { int hash = Hash(seed, xPrimed, yPrimed); int index1 = hash & (127 << 1); @@ -592,7 +592,7 @@ private: } - void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) + void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) const { int hash = Hash(seed, xPrimed, yPrimed, zPrimed); int index1 = hash & (63 << 2); @@ -616,7 +616,7 @@ private: // Generic noise gen template <typename FNfloat> - float GenNoiseSingle(int seed, FNfloat x, FNfloat y) + float GenNoiseSingle(int seed, FNfloat x, FNfloat y) const { switch (mNoiseType) { @@ -638,7 +638,7 @@ private: } template <typename FNfloat> - float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) + float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) const { switch (mNoiseType) { @@ -663,7 +663,7 @@ private: // Noise Coordinate Transforms (frequency, and possible skew or rotation) template <typename FNfloat> - void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) + void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) const { x *= mFrequency; y *= mFrequency; @@ -686,7 +686,7 @@ private: } template <typename FNfloat> - void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) + void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const { x *= mFrequency; y *= mFrequency; @@ -757,7 +757,7 @@ private: // Domain Warp Coordinate Transforms template <typename FNfloat> - void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) + void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) const { switch (mDomainWarpType) { @@ -777,7 +777,7 @@ private: } template <typename FNfloat> - void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) + void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const { switch (mWarpTransformType3D) { @@ -844,7 +844,7 @@ private: // Fractal FBm template <typename FNfloat> - float GenFractalFBm(FNfloat x, FNfloat y) + float GenFractalFBm(FNfloat x, FNfloat y) const { int seed = mSeed; float sum = 0; @@ -865,7 +865,7 @@ private: } template <typename FNfloat> - float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) + float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) const { int seed = mSeed; float sum = 0; @@ -890,7 +890,7 @@ private: // Fractal Ridged template <typename FNfloat> - float GenFractalRidged(FNfloat x, FNfloat y) + float GenFractalRidged(FNfloat x, FNfloat y) const { int seed = mSeed; float sum = 0; @@ -911,7 +911,7 @@ private: } template <typename FNfloat> - float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) + float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) const { int seed = mSeed; float sum = 0; @@ -936,7 +936,7 @@ private: // Fractal PingPong template <typename FNfloat> - float GenFractalPingPong(FNfloat x, FNfloat y) + float GenFractalPingPong(FNfloat x, FNfloat y) const { int seed = mSeed; float sum = 0; @@ -957,7 +957,7 @@ private: } template <typename FNfloat> - float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) + float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) const { int seed = mSeed; float sum = 0; @@ -982,7 +982,7 @@ private: // Simplex/OpenSimplex2 Noise template <typename FNfloat> - float SingleSimplex(int seed, FNfloat x, FNfloat y) + float SingleSimplex(int seed, FNfloat x, FNfloat y) const { // 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex. @@ -1053,7 +1053,7 @@ private: } template <typename FNfloat> - float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) const { // 3D OpenSimplex2 case uses two offset rotated cube grids. @@ -1155,7 +1155,7 @@ private: // OpenSimplex2S Noise template <typename FNfloat> - float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) + float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) const { // 2D OpenSimplex2S case is a modified 2D simplex noise. @@ -1286,7 +1286,7 @@ private: } template <typename FNfloat> - float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) const { // 3D OpenSimplex2S case uses two offset rotated cube grids. @@ -1482,7 +1482,7 @@ private: // Cellular Noise template <typename FNfloat> - float SingleCellular(int seed, FNfloat x, FNfloat y) + float SingleCellular(int seed, FNfloat x, FNfloat y) const { int xr = FastRound(x); int yr = FastRound(y); @@ -1612,7 +1612,7 @@ private: } template <typename FNfloat> - float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) const { int xr = FastRound(x); int yr = FastRound(y); @@ -1769,7 +1769,7 @@ private: // Perlin Noise template <typename FNfloat> - float SinglePerlin(int seed, FNfloat x, FNfloat y) + float SinglePerlin(int seed, FNfloat x, FNfloat y) const { int x0 = FastFloor(x); int y0 = FastFloor(y); @@ -1794,7 +1794,7 @@ private: } template <typename FNfloat> - float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) + float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) const { int x0 = FastFloor(x); int y0 = FastFloor(y); @@ -1833,7 +1833,7 @@ private: // Value Cubic Noise template <typename FNfloat> - float SingleValueCubic(int seed, FNfloat x, FNfloat y) + float SingleValueCubic(int seed, FNfloat x, FNfloat y) const { int x1 = FastFloor(x); int y1 = FastFloor(y); @@ -1863,7 +1863,7 @@ private: } template <typename FNfloat> - float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) const { int x1 = FastFloor(x); int y1 = FastFloor(y); @@ -1920,7 +1920,7 @@ private: // Value Noise template <typename FNfloat> - float SingleValue(int seed, FNfloat x, FNfloat y) + float SingleValue(int seed, FNfloat x, FNfloat y) const { int x0 = FastFloor(x); int y0 = FastFloor(y); @@ -1940,7 +1940,7 @@ private: } template <typename FNfloat> - float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) + float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) const { int x0 = FastFloor(x); int y0 = FastFloor(y); @@ -1972,7 +1972,7 @@ private: // Domain Warp template <typename FNfloat> - void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) + void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const { switch (mDomainWarpType) { @@ -1989,7 +1989,7 @@ private: } template <typename FNfloat> - void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) + void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const { switch (mDomainWarpType) { @@ -2009,7 +2009,7 @@ private: // Domain Warp Single Wrapper template <typename FNfloat> - void DomainWarpSingle(FNfloat& x, FNfloat& y) + void DomainWarpSingle(FNfloat& x, FNfloat& y) const { int seed = mSeed; float amp = mDomainWarpAmp * mFractalBounding; @@ -2023,7 +2023,7 @@ private: } template <typename FNfloat> - void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) + void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) const { int seed = mSeed; float amp = mDomainWarpAmp * mFractalBounding; @@ -2041,7 +2041,7 @@ private: // Domain Warp Fractal Progressive template <typename FNfloat> - void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) + void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) const { int seed = mSeed; float amp = mDomainWarpAmp * mFractalBounding; @@ -2062,7 +2062,7 @@ private: } template <typename FNfloat> - void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) + void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) const { int seed = mSeed; float amp = mDomainWarpAmp * mFractalBounding; @@ -2087,7 +2087,7 @@ private: // Domain Warp Fractal Independant template <typename FNfloat> - void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) + void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) const { FNfloat xs = x; FNfloat ys = y; @@ -2108,7 +2108,7 @@ private: } template <typename FNfloat> - void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) + void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) const { FNfloat xs = x; FNfloat ys = y; @@ -2133,7 +2133,7 @@ private: // Domain Warp Basic Grid template <typename FNfloat> - void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) + void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const { FNfloat xf = x * frequency; FNfloat yf = y * frequency; @@ -2166,7 +2166,7 @@ private: } template <typename FNfloat> - void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) + void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const { FNfloat xf = x * frequency; FNfloat yf = y * frequency; @@ -2228,7 +2228,7 @@ private: // Domain Warp Simplex/OpenSimplex2 template <typename FNfloat> - void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) + void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) const { const float SQRT3 = 1.7320508075688772935274463415059f; const float G2 = (3 - SQRT3) / 6; @@ -2326,7 +2326,7 @@ private: } template <typename FNfloat> - void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) + void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) const { x *= frequency; y *= frequency; diff --git a/thirdparty/noise/patches/FastNoiseLite.patch b/thirdparty/noise/patches/FastNoiseLite.patch index acb1edfd73..41ec943077 100644 --- a/thirdparty/noise/patches/FastNoiseLite.patch +++ b/thirdparty/noise/patches/FastNoiseLite.patch @@ -16,3 +16,417 @@ -#endif +} +#endif // namespace fastnoiselite +@@ -295,7 +295,7 @@ public: + /// Noise output bounded between -1...1 + /// </returns> + template <typename FNfloat> +- float GetNoise(FNfloat x, FNfloat y) ++ float GetNoise(FNfloat x, FNfloat y) const + { + Arguments_must_be_floating_point_values<FNfloat>(); + +@@ -321,7 +321,7 @@ public: + /// Noise output bounded between -1...1 + /// </returns> + template <typename FNfloat> +- float GetNoise(FNfloat x, FNfloat y, FNfloat z) ++ float GetNoise(FNfloat x, FNfloat y, FNfloat z) const + { + Arguments_must_be_floating_point_values<FNfloat>(); + +@@ -350,7 +350,7 @@ public: + /// noise = GetNoise(x, y)</code> + /// </example> + template <typename FNfloat> +- void DomainWarp(FNfloat& x, FNfloat& y) ++ void DomainWarp(FNfloat& x, FNfloat& y) const + { + Arguments_must_be_floating_point_values<FNfloat>(); + +@@ -377,7 +377,7 @@ public: + /// noise = GetNoise(x, y, z)</code> + /// </example> + template <typename FNfloat> +- void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) ++ void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) const + { + Arguments_must_be_floating_point_values<FNfloat>(); + +@@ -528,7 +528,7 @@ private: + } + + +- float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) ++ float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) const + { + int hash = Hash(seed, xPrimed, yPrimed); + hash ^= hash >> 15; +@@ -541,7 +541,7 @@ private: + } + + +- float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) ++ float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) const + { + int hash = Hash(seed, xPrimed, yPrimed, zPrimed); + hash ^= hash >> 15; +@@ -555,7 +555,7 @@ private: + } + + +- void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) ++ void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) const + { + int hash = Hash(seed, xPrimed, yPrimed) & (255 << 1); + +@@ -564,7 +564,7 @@ private: + } + + +- void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) ++ void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) const + { + int hash = Hash(seed, xPrimed, yPrimed, zPrimed) & (255 << 2); + +@@ -574,7 +574,7 @@ private: + } + + +- void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) ++ void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) const + { + int hash = Hash(seed, xPrimed, yPrimed); + int index1 = hash & (127 << 1); +@@ -592,7 +592,7 @@ private: + } + + +- void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) ++ void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) const + { + int hash = Hash(seed, xPrimed, yPrimed, zPrimed); + int index1 = hash & (63 << 2); +@@ -616,7 +616,7 @@ private: + // Generic noise gen + + template <typename FNfloat> +- float GenNoiseSingle(int seed, FNfloat x, FNfloat y) ++ float GenNoiseSingle(int seed, FNfloat x, FNfloat y) const + { + switch (mNoiseType) + { +@@ -638,7 +638,7 @@ private: + } + + template <typename FNfloat> +- float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + switch (mNoiseType) + { +@@ -663,7 +663,7 @@ private: + // Noise Coordinate Transforms (frequency, and possible skew or rotation) + + template <typename FNfloat> +- void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) ++ void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) const + { + x *= mFrequency; + y *= mFrequency; +@@ -686,7 +686,7 @@ private: + } + + template <typename FNfloat> +- void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) ++ void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const + { + x *= mFrequency; + y *= mFrequency; +@@ -757,7 +757,7 @@ private: + // Domain Warp Coordinate Transforms + + template <typename FNfloat> +- void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) ++ void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) const + { + switch (mDomainWarpType) + { +@@ -777,7 +777,7 @@ private: + } + + template <typename FNfloat> +- void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) ++ void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const + { + switch (mWarpTransformType3D) + { +@@ -844,7 +844,7 @@ private: + // Fractal FBm + + template <typename FNfloat> +- float GenFractalFBm(FNfloat x, FNfloat y) ++ float GenFractalFBm(FNfloat x, FNfloat y) const + { + int seed = mSeed; + float sum = 0; +@@ -865,7 +865,7 @@ private: + } + + template <typename FNfloat> +- float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) ++ float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) const + { + int seed = mSeed; + float sum = 0; +@@ -890,7 +890,7 @@ private: + // Fractal Ridged + + template <typename FNfloat> +- float GenFractalRidged(FNfloat x, FNfloat y) ++ float GenFractalRidged(FNfloat x, FNfloat y) const + { + int seed = mSeed; + float sum = 0; +@@ -911,7 +911,7 @@ private: + } + + template <typename FNfloat> +- float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) ++ float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) const + { + int seed = mSeed; + float sum = 0; +@@ -936,7 +936,7 @@ private: + // Fractal PingPong + + template <typename FNfloat> +- float GenFractalPingPong(FNfloat x, FNfloat y) ++ float GenFractalPingPong(FNfloat x, FNfloat y) const + { + int seed = mSeed; + float sum = 0; +@@ -957,7 +957,7 @@ private: + } + + template <typename FNfloat> +- float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) ++ float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) const + { + int seed = mSeed; + float sum = 0; +@@ -982,7 +982,7 @@ private: + // Simplex/OpenSimplex2 Noise + + template <typename FNfloat> +- float SingleSimplex(int seed, FNfloat x, FNfloat y) ++ float SingleSimplex(int seed, FNfloat x, FNfloat y) const + { + // 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex. + +@@ -1053,7 +1053,7 @@ private: + } + + template <typename FNfloat> +- float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + // 3D OpenSimplex2 case uses two offset rotated cube grids. + +@@ -1155,7 +1155,7 @@ private: + // OpenSimplex2S Noise + + template <typename FNfloat> +- float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) ++ float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) const + { + // 2D OpenSimplex2S case is a modified 2D simplex noise. + +@@ -1286,7 +1286,7 @@ private: + } + + template <typename FNfloat> +- float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + // 3D OpenSimplex2S case uses two offset rotated cube grids. + +@@ -1482,7 +1482,7 @@ private: + // Cellular Noise + + template <typename FNfloat> +- float SingleCellular(int seed, FNfloat x, FNfloat y) ++ float SingleCellular(int seed, FNfloat x, FNfloat y) const + { + int xr = FastRound(x); + int yr = FastRound(y); +@@ -1612,7 +1612,7 @@ private: + } + + template <typename FNfloat> +- float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + int xr = FastRound(x); + int yr = FastRound(y); +@@ -1769,7 +1769,7 @@ private: + // Perlin Noise + + template <typename FNfloat> +- float SinglePerlin(int seed, FNfloat x, FNfloat y) ++ float SinglePerlin(int seed, FNfloat x, FNfloat y) const + { + int x0 = FastFloor(x); + int y0 = FastFloor(y); +@@ -1794,7 +1794,7 @@ private: + } + + template <typename FNfloat> +- float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + int x0 = FastFloor(x); + int y0 = FastFloor(y); +@@ -1833,7 +1833,7 @@ private: + // Value Cubic Noise + + template <typename FNfloat> +- float SingleValueCubic(int seed, FNfloat x, FNfloat y) ++ float SingleValueCubic(int seed, FNfloat x, FNfloat y) const + { + int x1 = FastFloor(x); + int y1 = FastFloor(y); +@@ -1863,7 +1863,7 @@ private: + } + + template <typename FNfloat> +- float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + int x1 = FastFloor(x); + int y1 = FastFloor(y); +@@ -1920,7 +1920,7 @@ private: + // Value Noise + + template <typename FNfloat> +- float SingleValue(int seed, FNfloat x, FNfloat y) ++ float SingleValue(int seed, FNfloat x, FNfloat y) const + { + int x0 = FastFloor(x); + int y0 = FastFloor(y); +@@ -1940,7 +1940,7 @@ private: + } + + template <typename FNfloat> +- float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) ++ float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) const + { + int x0 = FastFloor(x); + int y0 = FastFloor(y); +@@ -1972,7 +1972,7 @@ private: + // Domain Warp + + template <typename FNfloat> +- void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) ++ void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const + { + switch (mDomainWarpType) + { +@@ -1989,7 +1989,7 @@ private: + } + + template <typename FNfloat> +- void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) ++ void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const + { + switch (mDomainWarpType) + { +@@ -2009,7 +2009,7 @@ private: + // Domain Warp Single Wrapper + + template <typename FNfloat> +- void DomainWarpSingle(FNfloat& x, FNfloat& y) ++ void DomainWarpSingle(FNfloat& x, FNfloat& y) const + { + int seed = mSeed; + float amp = mDomainWarpAmp * mFractalBounding; +@@ -2023,7 +2023,7 @@ private: + } + + template <typename FNfloat> +- void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) ++ void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) const + { + int seed = mSeed; + float amp = mDomainWarpAmp * mFractalBounding; +@@ -2041,7 +2041,7 @@ private: + // Domain Warp Fractal Progressive + + template <typename FNfloat> +- void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) ++ void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) const + { + int seed = mSeed; + float amp = mDomainWarpAmp * mFractalBounding; +@@ -2062,7 +2062,7 @@ private: + } + + template <typename FNfloat> +- void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) ++ void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) const + { + int seed = mSeed; + float amp = mDomainWarpAmp * mFractalBounding; +@@ -2087,7 +2087,7 @@ private: + // Domain Warp Fractal Independant + + template <typename FNfloat> +- void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) ++ void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) const + { + FNfloat xs = x; + FNfloat ys = y; +@@ -2108,7 +2108,7 @@ private: + } + + template <typename FNfloat> +- void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) ++ void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) const + { + FNfloat xs = x; + FNfloat ys = y; +@@ -2133,7 +2133,7 @@ private: + // Domain Warp Basic Grid + + template <typename FNfloat> +- void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) ++ void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const + { + FNfloat xf = x * frequency; + FNfloat yf = y * frequency; +@@ -2166,7 +2166,7 @@ private: + } + + template <typename FNfloat> +- void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) ++ void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const + { + FNfloat xf = x * frequency; + FNfloat yf = y * frequency; +@@ -2228,7 +2228,7 @@ private: + // Domain Warp Simplex/OpenSimplex2 + + template <typename FNfloat> +- void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) ++ void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) const + { + const float SQRT3 = 1.7320508075688772935274463415059f; + const float G2 = (3 - SQRT3) / 6; +@@ -2326,7 +2326,7 @@ private: + } + + template <typename FNfloat> +- void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) ++ void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) const + { + x *= frequency; + y *= frequency; |