diff options
114 files changed, 1202 insertions, 626 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 25dd408dce..0d699cdacb 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1104,6 +1104,8 @@ ProjectSettings::ProjectSettings() { } extensions.push_back("shader"); + GLOBAL_DEF("editor/run/main_run_args", ""); + GLOBAL_DEF("editor/script/search_in_file_extensions", extensions); custom_prop_info["editor/script/search_in_file_extensions"] = PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/script/search_in_file_extensions"); diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp index 90b0975159..39113eda14 100644 --- a/core/debugger/remote_debugger_peer.cpp +++ b/core/debugger/remote_debugger_peer.cpp @@ -152,7 +152,7 @@ void RemoteDebuggerPeerTCP::_read_in() { } Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_port) { - IP_Address ip; + IPAddress ip; if (p_host.is_valid_ip_address()) { ip = p_host; } else { diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index 31b7d658d0..4cc73bcd22 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -171,7 +171,7 @@ void FileAccessNetworkClient::_thread_func(void *s) { } Error FileAccessNetworkClient::connect(const String &p_host, int p_port, const String &p_password) { - IP_Address ip; + IPAddress ip; if (p_host.is_valid_ip_address()) { ip = p_host; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 4b053d576c..0cf870e7e7 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -77,7 +77,7 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, if (conn_host.is_valid_ip_address()) { // Host contains valid IP - Error err = tcp_connection->connect_to_host(IP_Address(conn_host), p_port); + Error err = tcp_connection->connect_to_host(IPAddress(conn_host), p_port); if (err) { status = STATUS_CANT_CONNECT; return err; @@ -328,7 +328,7 @@ Error HTTPClient::poll() { return OK; // Still resolving case IP::RESOLVER_STATUS_DONE: { - IP_Address host = IP::get_singleton()->get_resolve_item_address(resolving); + IPAddress host = IP::get_singleton()->get_resolve_item_address(resolving); Error err = tcp_connection->connect_to_host(host, conn_port); IP::get_singleton()->erase_resolve_item(resolving); resolving = IP::RESOLVER_INVALID_ID; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index e1d9c19f10..eb7814054b 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -41,13 +41,13 @@ VARIANT_ENUM_CAST(IP::ResolverStatus); struct _IP_ResolverPrivate { struct QueueItem { SafeNumeric<IP::ResolverStatus> status; - IP_Address response; + IPAddress response; String hostname; IP::Type type; void clear() { status.set(IP::RESOLVER_STATUS_NONE); - response = IP_Address(); + response = IPAddress(); type = IP::TYPE_NONE; hostname = ""; }; @@ -101,23 +101,23 @@ struct _IP_ResolverPrivate { } } - HashMap<String, IP_Address> cache; + HashMap<String, IPAddress> cache; static String get_cache_key(String p_hostname, IP::Type p_type) { return itos(p_type) + p_hostname; } }; -IP_Address IP::resolve_hostname(const String &p_hostname, IP::Type p_type) { +IPAddress IP::resolve_hostname(const String &p_hostname, IP::Type p_type) { MutexLock lock(resolver->mutex); String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type); if (resolver->cache.has(key) && resolver->cache[key].is_valid()) { - IP_Address res = resolver->cache[key]; + IPAddress res = resolver->cache[key]; return res; } - IP_Address res = _resolve_hostname(p_hostname, p_type); + IPAddress res = _resolve_hostname(p_hostname, p_type); resolver->cache[key] = res; return res; } @@ -139,7 +139,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ resolver->queue[id].response = resolver->cache[key]; resolver->queue[id].status.set(IP::RESOLVER_STATUS_DONE); } else { - resolver->queue[id].response = IP_Address(); + resolver->queue[id].response = IPAddress(); resolver->queue[id].status.set(IP::RESOLVER_STATUS_WAITING); if (resolver->thread.is_started()) { resolver->sem.post(); @@ -164,15 +164,15 @@ IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const { return resolver->queue[p_id].status.get(); } -IP_Address IP::get_resolve_item_address(ResolverID p_id) const { - ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP_Address()); +IPAddress IP::get_resolve_item_address(ResolverID p_id) const { + ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IPAddress()); MutexLock lock(resolver->mutex); if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) { ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet."); resolver->mutex.unlock(); - return IP_Address(); + return IPAddress(); } return resolver->queue[p_id].response; @@ -201,9 +201,9 @@ void IP::clear_cache(const String &p_hostname) { Array IP::_get_local_addresses() const { Array addresses; - List<IP_Address> ip_addresses; + List<IPAddress> ip_addresses; get_local_addresses(&ip_addresses); - for (List<IP_Address>::Element *E = ip_addresses.front(); E; E = E->next()) { + for (List<IPAddress>::Element *E = ip_addresses.front(); E; E = E->next()) { addresses.push_back(E->get()); } @@ -222,7 +222,7 @@ Array IP::_get_local_interfaces() const { rc["index"] = c.index; Array ips; - for (const List<IP_Address>::Element *F = c.ip_addresses.front(); F; F = F->next()) { + for (const List<IPAddress>::Element *F = c.ip_addresses.front(); F; F = F->next()) { ips.push_front(F->get()); } rc["addresses"] = ips; @@ -233,11 +233,11 @@ Array IP::_get_local_interfaces() const { return results; } -void IP::get_local_addresses(List<IP_Address> *r_addresses) const { +void IP::get_local_addresses(List<IPAddress> *r_addresses) const { Map<String, Interface_Info> interfaces; get_local_interfaces(&interfaces); for (Map<String, Interface_Info>::Element *E = interfaces.front(); E; E = E->next()) { - for (const List<IP_Address>::Element *F = E->get().ip_addresses.front(); F; F = F->next()) { + for (const List<IPAddress>::Element *F = E->get().ip_addresses.front(); F; F = F->next()) { r_addresses->push_front(F->get()); } } diff --git a/core/io/ip.h b/core/io/ip.h index ae080b8e26..0c4a83257d 100644 --- a/core/io/ip.h +++ b/core/io/ip.h @@ -69,7 +69,7 @@ protected: static IP *singleton; static void _bind_methods(); - virtual IP_Address _resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY) = 0; + virtual IPAddress _resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY) = 0; Array _get_local_addresses() const; Array _get_local_interfaces() const; @@ -80,15 +80,15 @@ public: String name; String name_friendly; String index; - List<IP_Address> ip_addresses; + List<IPAddress> ip_addresses; }; - IP_Address resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY); + IPAddress resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY); // async resolver hostname ResolverID resolve_hostname_queue_item(const String &p_hostname, Type p_type = TYPE_ANY); ResolverStatus get_resolve_item_status(ResolverID p_id) const; - IP_Address get_resolve_item_address(ResolverID p_id) const; - virtual void get_local_addresses(List<IP_Address> *r_addresses) const; + IPAddress get_resolve_item_address(ResolverID p_id) const; + virtual void get_local_addresses(List<IPAddress> *r_addresses) const; virtual void get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const = 0; void erase_resolve_item(ResolverID p_id); diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 5f98eb69e8..1c1ac8a88f 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -30,14 +30,14 @@ #include "ip_address.h" /* -IP_Address::operator Variant() const { +IPAddress::operator Variant() const { return operator String(); }*/ #include <stdio.h> #include <string.h> -IP_Address::operator String() const { +IPAddress::operator String() const { if (wildcard) { return "*"; } @@ -90,7 +90,7 @@ static void _parse_hex(const String &p_string, int p_start, uint8_t *p_dst) { p_dst[1] = ret & 0xff; } -void IP_Address::_parse_ipv6(const String &p_string) { +void IPAddress::_parse_ipv6(const String &p_string) { static const int parts_total = 8; int parts[parts_total] = { 0 }; int parts_count = 0; @@ -146,7 +146,7 @@ void IP_Address::_parse_ipv6(const String &p_string) { } } -void IP_Address::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret) { +void IPAddress::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret) { String ip; if (p_start != 0) { ip = p_string.substr(p_start, p_string.length() - p_start); @@ -161,33 +161,33 @@ void IP_Address::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret } } -void IP_Address::clear() { +void IPAddress::clear() { memset(&field8[0], 0, sizeof(field8)); valid = false; wildcard = false; } -bool IP_Address::is_ipv4() const { +bool IPAddress::is_ipv4() const { return (field32[0] == 0 && field32[1] == 0 && field16[4] == 0 && field16[5] == 0xffff); } -const uint8_t *IP_Address::get_ipv4() const { +const uint8_t *IPAddress::get_ipv4() const { ERR_FAIL_COND_V_MSG(!is_ipv4(), &(field8[12]), "IPv4 requested, but current IP is IPv6."); // Not the correct IPv4 (it's an IPv6), but we don't want to return a null pointer risking an engine crash. return &(field8[12]); } -void IP_Address::set_ipv4(const uint8_t *p_ip) { +void IPAddress::set_ipv4(const uint8_t *p_ip) { clear(); valid = true; field16[5] = 0xffff; field32[3] = *((const uint32_t *)p_ip); } -const uint8_t *IP_Address::get_ipv6() const { +const uint8_t *IPAddress::get_ipv6() const { return field8; } -void IP_Address::set_ipv6(const uint8_t *p_buf) { +void IPAddress::set_ipv6(const uint8_t *p_buf) { clear(); valid = true; for (int i = 0; i < 16; i++) { @@ -195,7 +195,7 @@ void IP_Address::set_ipv6(const uint8_t *p_buf) { } } -IP_Address::IP_Address(const String &p_string) { +IPAddress::IPAddress(const String &p_string) { clear(); if (p_string == "*") { @@ -225,7 +225,7 @@ _FORCE_INLINE_ static void _32_to_buf(uint8_t *p_dst, uint32_t p_n) { p_dst[3] = (p_n >> 0) & 0xff; } -IP_Address::IP_Address(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d, bool is_v6) { +IPAddress::IPAddress(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d, bool is_v6) { clear(); valid = true; if (!is_v6) { diff --git a/core/io/ip_address.h b/core/io/ip_address.h index 49bf83d72f..05da675704 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -33,7 +33,7 @@ #include "core/string/ustring.h" -struct IP_Address { +struct IPAddress { private: union { uint8_t field8[16]; @@ -50,7 +50,7 @@ protected: public: //operator Variant() const; - bool operator==(const IP_Address &p_ip) const { + bool operator==(const IPAddress &p_ip) const { if (p_ip.valid != valid) { return false; } @@ -65,7 +65,7 @@ public: return true; } - bool operator!=(const IP_Address &p_ip) const { + bool operator!=(const IPAddress &p_ip) const { if (p_ip.valid != valid) { return true; } @@ -91,9 +91,9 @@ public: void set_ipv6(const uint8_t *p_buf); operator String() const; - IP_Address(const String &p_string); - IP_Address(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d, bool is_v6 = false); - IP_Address() { clear(); } + IPAddress(const String &p_string); + IPAddress(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d, bool is_v6 = false); + IPAddress() { clear(); } }; #endif // IP_ADDRESS_H diff --git a/core/io/net_socket.h b/core/io/net_socket.h index a632ad2ea7..98ff9562d9 100644 --- a/core/io/net_socket.h +++ b/core/io/net_socket.h @@ -55,27 +55,27 @@ public: virtual Error open(Type p_type, IP::Type &ip_type) = 0; virtual void close() = 0; - virtual Error bind(IP_Address p_addr, uint16_t p_port) = 0; + virtual Error bind(IPAddress p_addr, uint16_t p_port) = 0; virtual Error listen(int p_max_pending) = 0; - virtual Error connect_to_host(IP_Address p_addr, uint16_t p_port) = 0; + virtual Error connect_to_host(IPAddress p_addr, uint16_t p_port) = 0; virtual Error poll(PollType p_type, int timeout) const = 0; virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0; - virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port, bool p_peek = false) = 0; + virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false) = 0; virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0; - virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0; - virtual Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port) = 0; + virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) = 0; + virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port) = 0; virtual bool is_open() const = 0; virtual int get_available_bytes() const = 0; - virtual Error get_socket_address(IP_Address *r_ip, uint16_t *r_port) const = 0; + virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const = 0; virtual Error set_broadcasting_enabled(bool p_enabled) = 0; // Returns OK if the socket option has been set successfully. virtual void set_blocking_enabled(bool p_enabled) = 0; virtual void set_ipv6_only_enabled(bool p_enabled) = 0; virtual void set_tcp_no_delay_enabled(bool p_enabled) = 0; virtual void set_reuse_address_enabled(bool p_enabled) = 0; - virtual Error join_multicast_group(const IP_Address &p_multi_address, String p_if_name) = 0; - virtual Error leave_multicast_group(const IP_Address &p_multi_address, String p_if_name) = 0; + virtual Error join_multicast_group(const IPAddress &p_multi_address, String p_if_name) = 0; + virtual Error leave_multicast_group(const IPAddress &p_multi_address, String p_if_name) = 0; }; #endif // NET_SOCKET_H diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index 40e4ce4f77..f951a5158c 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -45,7 +45,7 @@ void PacketPeerUDP::set_broadcast_enabled(bool p_enabled) { } } -Error PacketPeerUDP::join_multicast_group(IP_Address p_multi_address, String p_if_name) { +Error PacketPeerUDP::join_multicast_group(IPAddress p_multi_address, String p_if_name) { ERR_FAIL_COND_V(udp_server, ERR_LOCKED); ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(!p_multi_address.is_valid(), ERR_INVALID_PARAMETER); @@ -60,7 +60,7 @@ Error PacketPeerUDP::join_multicast_group(IP_Address p_multi_address, String p_i return _sock->join_multicast_group(p_multi_address, p_if_name); } -Error PacketPeerUDP::leave_multicast_group(IP_Address p_multi_address, String p_if_name) { +Error PacketPeerUDP::leave_multicast_group(IPAddress p_multi_address, String p_if_name) { ERR_FAIL_COND_V(udp_server, ERR_LOCKED); ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(!_sock->is_open(), ERR_UNCONFIGURED); @@ -72,7 +72,7 @@ String PacketPeerUDP::_get_packet_ip() const { } Error PacketPeerUDP::_set_dest_address(const String &p_address, int p_port) { - IP_Address ip; + IPAddress ip; if (p_address.is_valid_ip_address()) { ip = p_address; } else { @@ -159,7 +159,7 @@ int PacketPeerUDP::get_max_packet_size() const { return 512; // uhm maybe not } -Error PacketPeerUDP::bind(int p_port, const IP_Address &p_bind_address, int p_recv_buffer_size) { +Error PacketPeerUDP::bind(int p_port, const IPAddress &p_bind_address, int p_recv_buffer_size) { ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); @@ -190,7 +190,7 @@ Error PacketPeerUDP::bind(int p_port, const IP_Address &p_bind_address, int p_re return OK; } -Error PacketPeerUDP::connect_shared_socket(Ref<NetSocket> p_sock, IP_Address p_ip, uint16_t p_port, UDPServer *p_server) { +Error PacketPeerUDP::connect_shared_socket(Ref<NetSocket> p_sock, IPAddress p_ip, uint16_t p_port, UDPServer *p_server) { udp_server = p_server; connected = true; _sock = p_sock; @@ -207,7 +207,7 @@ void PacketPeerUDP::disconnect_shared_socket() { close(); } -Error PacketPeerUDP::connect_to_host(const IP_Address &p_host, int p_port) { +Error PacketPeerUDP::connect_to_host(const IPAddress &p_host, int p_port) { ERR_FAIL_COND_V(udp_server, ERR_LOCKED); ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER); @@ -276,7 +276,7 @@ Error PacketPeerUDP::_poll() { Error err; int read; - IP_Address ip; + IPAddress ip; uint16_t port; while (true) { @@ -306,7 +306,7 @@ Error PacketPeerUDP::_poll() { return OK; } -Error PacketPeerUDP::store_packet(IP_Address p_ip, uint32_t p_port, uint8_t *p_buf, int p_buf_size) { +Error PacketPeerUDP::store_packet(IPAddress p_ip, uint32_t p_port, uint8_t *p_buf, int p_buf_size) { if (rb.space_left() < p_buf_size + 24) { return ERR_OUT_OF_MEMORY; } @@ -322,7 +322,7 @@ bool PacketPeerUDP::is_bound() const { return _sock.is_valid() && _sock->is_open(); } -IP_Address PacketPeerUDP::get_packet_address() const { +IPAddress PacketPeerUDP::get_packet_address() const { return packet_ip; } @@ -336,7 +336,7 @@ int PacketPeerUDP::get_local_port() const { return local_port; } -void PacketPeerUDP::set_dest_address(const IP_Address &p_address, int p_port) { +void PacketPeerUDP::set_dest_address(const IPAddress &p_address, int p_port) { ERR_FAIL_COND_MSG(connected, "Destination address cannot be set for connected sockets"); peer_addr = p_address; peer_port = p_port; diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index b9d11c465c..40d3c44e40 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -48,11 +48,11 @@ protected: RingBuffer<uint8_t> rb; uint8_t recv_buffer[PACKET_BUFFER_SIZE]; uint8_t packet_buffer[PACKET_BUFFER_SIZE]; - IP_Address packet_ip; + IPAddress packet_ip; int packet_port = 0; int queue_count = 0; - IP_Address peer_addr; + IPAddress peer_addr; int peer_port = 0; bool connected = false; bool blocking = true; @@ -70,29 +70,29 @@ protected: public: void set_blocking_mode(bool p_enable); - Error bind(int p_port, const IP_Address &p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536); + Error bind(int p_port, const IPAddress &p_bind_address = IPAddress("*"), int p_recv_buffer_size = 65536); void close(); Error wait(); bool is_bound() const; - Error connect_shared_socket(Ref<NetSocket> p_sock, IP_Address p_ip, uint16_t p_port, UDPServer *ref); // Used by UDPServer + Error connect_shared_socket(Ref<NetSocket> p_sock, IPAddress p_ip, uint16_t p_port, UDPServer *ref); // Used by UDPServer void disconnect_shared_socket(); // Used by UDPServer - Error store_packet(IP_Address p_ip, uint32_t p_port, uint8_t *p_buf, int p_buf_size); // Used internally and by UDPServer - Error connect_to_host(const IP_Address &p_host, int p_port); + 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; - IP_Address get_packet_address() const; + IPAddress get_packet_address() const; int get_packet_port() const; int get_local_port() const; - void set_dest_address(const IP_Address &p_address, int p_port); + void set_dest_address(const IPAddress &p_address, int p_port); Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override; Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; int get_available_packet_count() const override; int get_max_packet_size() const override; void set_broadcast_enabled(bool p_enabled); - Error join_multicast_group(IP_Address p_multi_address, String p_if_name); - Error leave_multicast_group(IP_Address p_multi_address, String p_if_name); + Error join_multicast_group(IPAddress p_multi_address, String p_if_name); + Error leave_multicast_group(IPAddress p_multi_address, String p_if_name); PacketPeerUDP(); ~PacketPeerUDP(); diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 9906b9e4c3..5b794274ca 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -56,7 +56,7 @@ Error StreamPeerTCP::_poll_connection() { return ERR_CONNECTION_ERROR; } -void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint16_t p_port) { +void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IPAddress p_host, uint16_t p_port) { _sock = p_sock; _sock->set_blocking_enabled(false); @@ -67,7 +67,7 @@ void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint peer_port = p_port; } -Error StreamPeerTCP::bind(int p_port, const IP_Address &p_host) { +Error StreamPeerTCP::bind(int p_port, const IPAddress &p_host) { ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive)."); @@ -84,7 +84,7 @@ Error StreamPeerTCP::bind(int p_port, const IP_Address &p_host) { return _sock->bind(p_host, p_port); } -Error StreamPeerTCP::connect_to_host(const IP_Address &p_host, int p_port) { +Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) { ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(status != STATUS_NONE, ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER); @@ -283,7 +283,7 @@ void StreamPeerTCP::disconnect_from_host() { timeout = 0; status = STATUS_NONE; - peer_host = IP_Address(); + peer_host = IPAddress(); peer_port = 0; } @@ -315,7 +315,7 @@ int StreamPeerTCP::get_available_bytes() const { return _sock->get_available_bytes(); } -IP_Address StreamPeerTCP::get_connected_host() const { +IPAddress StreamPeerTCP::get_connected_host() const { return peer_host; } @@ -330,7 +330,7 @@ int StreamPeerTCP::get_local_port() const { } Error StreamPeerTCP::_connect(const String &p_address, int p_port) { - IP_Address ip; + IPAddress ip; if (p_address.is_valid_ip_address()) { ip = p_address; } else { diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index 3bc7b252dc..a2a7f447d8 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -52,7 +52,7 @@ protected: Ref<NetSocket> _sock; uint64_t timeout = 0; Status status = STATUS_NONE; - IP_Address peer_host; + IPAddress peer_host; uint16_t peer_port = 0; Error _connect(const String &p_address, int p_port); @@ -63,12 +63,12 @@ protected: static void _bind_methods(); public: - void accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint16_t p_port); + void accept_socket(Ref<NetSocket> p_sock, IPAddress p_host, uint16_t p_port); - Error bind(int p_port, const IP_Address &p_host); - Error connect_to_host(const IP_Address &p_host, int p_port); + 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; - IP_Address get_connected_host() const; + IPAddress get_connected_host() const; int get_connected_port() const; int get_local_port() const; void disconnect_from_host(); diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 348be66ba4..b760a9ef80 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -30,16 +30,16 @@ #include "tcp_server.h" -void TCP_Server::_bind_methods() { - ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*")); - ClassDB::bind_method(D_METHOD("is_connection_available"), &TCP_Server::is_connection_available); - ClassDB::bind_method(D_METHOD("is_listening"), &TCP_Server::is_listening); - ClassDB::bind_method(D_METHOD("get_local_port"), &TCP_Server::get_local_port); - ClassDB::bind_method(D_METHOD("take_connection"), &TCP_Server::take_connection); - ClassDB::bind_method(D_METHOD("stop"), &TCP_Server::stop); +void TCPServer::_bind_methods() { + ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCPServer::listen, DEFVAL("*")); + ClassDB::bind_method(D_METHOD("is_connection_available"), &TCPServer::is_connection_available); + ClassDB::bind_method(D_METHOD("is_listening"), &TCPServer::is_listening); + ClassDB::bind_method(D_METHOD("get_local_port"), &TCPServer::get_local_port); + ClassDB::bind_method(D_METHOD("take_connection"), &TCPServer::take_connection); + ClassDB::bind_method(D_METHOD("stop"), &TCPServer::stop); } -Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) { +Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) { ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); @@ -76,19 +76,19 @@ Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) { return OK; } -int TCP_Server::get_local_port() const { +int TCPServer::get_local_port() const { uint16_t local_port; _sock->get_socket_address(nullptr, &local_port); return local_port; } -bool TCP_Server::is_listening() const { +bool TCPServer::is_listening() const { ERR_FAIL_COND_V(!_sock.is_valid(), false); return _sock->is_open(); } -bool TCP_Server::is_connection_available() const { +bool TCPServer::is_connection_available() const { ERR_FAIL_COND_V(!_sock.is_valid(), false); if (!_sock->is_open()) { @@ -99,14 +99,14 @@ bool TCP_Server::is_connection_available() const { return (err == OK); } -Ref<StreamPeerTCP> TCP_Server::take_connection() { +Ref<StreamPeerTCP> TCPServer::take_connection() { Ref<StreamPeerTCP> conn; if (!is_connection_available()) { return conn; } Ref<NetSocket> ns; - IP_Address ip; + IPAddress ip; uint16_t port = 0; ns = _sock->accept(ip, port); if (!ns.is_valid()) { @@ -118,16 +118,16 @@ Ref<StreamPeerTCP> TCP_Server::take_connection() { return conn; } -void TCP_Server::stop() { +void TCPServer::stop() { if (_sock.is_valid()) { _sock->close(); } } -TCP_Server::TCP_Server() : +TCPServer::TCPServer() : _sock(Ref<NetSocket>(NetSocket::create())) { } -TCP_Server::~TCP_Server() { +TCPServer::~TCPServer() { stop(); } diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index 58c04d87ec..abefa53c6f 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -36,8 +36,8 @@ #include "core/io/stream_peer.h" #include "core/io/stream_peer_tcp.h" -class TCP_Server : public Reference { - GDCLASS(TCP_Server, Reference); +class TCPServer : public Reference { + GDCLASS(TCPServer, Reference); protected: enum { @@ -48,7 +48,7 @@ protected: static void _bind_methods(); public: - Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*")); + Error listen(uint16_t p_port, const IPAddress &p_bind_address = IPAddress("*")); int get_local_port() const; bool is_listening() const; bool is_connection_available() const; @@ -56,8 +56,8 @@ public: void stop(); // Stop listening - TCP_Server(); - ~TCP_Server(); + TCPServer(); + ~TCPServer(); }; #endif // TCP_SERVER_H diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp index 99642f4af4..6a1af0c2a9 100644 --- a/core/io/udp_server.cpp +++ b/core/io/udp_server.cpp @@ -50,7 +50,7 @@ Error UDPServer::poll() { } Error err; int read; - IP_Address ip; + IPAddress ip; uint16_t port; while (true) { err = _sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, ip, port); @@ -87,7 +87,7 @@ Error UDPServer::poll() { return OK; } -Error UDPServer::listen(uint16_t p_port, const IP_Address &p_bind_address) { +Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) { ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); @@ -168,7 +168,7 @@ Ref<PacketPeerUDP> UDPServer::take_connection() { return peer.peer; } -void UDPServer::remove_peer(IP_Address p_ip, int p_port) { +void UDPServer::remove_peer(IPAddress p_ip, int p_port) { Peer peer; peer.ip = p_ip; peer.port = p_port; diff --git a/core/io/udp_server.h b/core/io/udp_server.h index 298d4d4b63..60d03f37f0 100644 --- a/core/io/udp_server.h +++ b/core/io/udp_server.h @@ -44,7 +44,7 @@ protected: struct Peer { PacketPeerUDP *peer; - IP_Address ip; + IPAddress ip; uint16_t port = 0; bool operator==(const Peer &p_other) const { @@ -61,8 +61,8 @@ protected: static void _bind_methods(); public: - void remove_peer(IP_Address p_ip, int p_port); - Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*")); + void remove_peer(IPAddress p_ip, int p_port); + Error listen(uint16_t p_port, const IPAddress &p_bind_address = IPAddress("*")); Error poll(); int get_local_port() const; bool is_listening() const; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index d6a5eff10d..f1b1b98bea 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -156,7 +156,7 @@ void register_core_types() { ClassDB::register_virtual_class<StreamPeer>(); ClassDB::register_class<StreamPeerBuffer>(); ClassDB::register_class<StreamPeerTCP>(); - ClassDB::register_class<TCP_Server>(); + ClassDB::register_class<TCPServer>(); ClassDB::register_class<PacketPeerUDP>(); ClassDB::register_class<UDPServer>(); ClassDB::register_custom_instance_class<PacketPeerDTLS>(); diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 2fb2dd4a30..3c7e2a0719 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -361,6 +361,79 @@ Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // l return new_arr; } +Array Array::filter(const Callable &p_callable) const { + Array new_arr; + new_arr.resize(size()); + int accepted_count = 0; + + for (int i = 0; i < size(); i++) { + const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *)); + argptrs[0] = &get(i); + + Variant result; + Callable::CallError ce; + p_callable.call(argptrs, 1, result, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_V_MSG(Array(), "Error calling method from 'filter': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + } + + if (result.operator bool()) { + new_arr[accepted_count] = get(i); + accepted_count++; + } + } + + new_arr.resize(accepted_count); + + return new_arr; +} + +Array Array::map(const Callable &p_callable) const { + Array new_arr; + new_arr.resize(size()); + + for (int i = 0; i < size(); i++) { + const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *)); + argptrs[0] = &get(i); + + Variant result; + Callable::CallError ce; + p_callable.call(argptrs, 1, result, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_V_MSG(Array(), "Error calling method from 'map': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + } + + new_arr[i] = result; + } + + return new_arr; +} + +Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const { + int start = 0; + Variant ret = p_accum; + if (ret == Variant() && size() > 0) { + ret = front(); + start = 1; + } + + for (int i = start; i < size(); i++) { + const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * 2); + argptrs[0] = &ret; + argptrs[1] = &get(i); + + Variant result; + Callable::CallError ce; + p_callable.call(argptrs, 2, result, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_V_MSG(Variant(), "Error calling method from 'reduce': " + Variant::get_callable_error_text(p_callable, argptrs, 2, ce)); + } + ret = result; + } + + return ret; +} + struct _ArrayVariantSort { _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const { bool valid = false; diff --git a/core/variant/array.h b/core/variant/array.h index 5ce977ee4b..540dcb1f4e 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -101,6 +101,9 @@ public: Array duplicate(bool p_deep = false) const; Array slice(int p_begin, int p_end, int p_step = 1, bool p_deep = false) const; + Array filter(const Callable &p_callable) const; + Array map(const Callable &p_callable) const; + Variant reduce(const Callable &p_callable, const Variant &p_accum) const; bool operator<(const Array &p_array) const; bool operator<=(const Array &p_array) const; diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h index c294592b63..e91029f330 100644 --- a/core/variant/method_ptrcall.h +++ b/core/variant/method_ptrcall.h @@ -364,7 +364,7 @@ MAKE_VECARR(Plane); } \ } -// Special case for IP_Address. +// Special case for IPAddress. #define MAKE_STRINGCONV_BY_REFERENCE(m_type) \ template <> \ @@ -387,7 +387,7 @@ MAKE_VECARR(Plane); } \ } -MAKE_STRINGCONV_BY_REFERENCE(IP_Address); +MAKE_STRINGCONV_BY_REFERENCE(IPAddress); template <> struct PtrToArg<Vector<Face3>> { diff --git a/core/variant/type_info.h b/core/variant/type_info.h index f61ff29b8f..d5b6d85dfb 100644 --- a/core/variant/type_info.h +++ b/core/variant/type_info.h @@ -168,7 +168,7 @@ MAKE_TYPE_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) MAKE_TYPE_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) MAKE_TYPE_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY) -MAKE_TYPE_INFO(IP_Address, Variant::STRING) +MAKE_TYPE_INFO(IPAddress, Variant::STRING) //objectID template <> diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 015cee09a7..333dd8e8d1 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -2346,15 +2346,15 @@ Variant::operator Orientation() const { return (Orientation) operator int(); } -Variant::operator IP_Address() const { +Variant::operator IPAddress() const { if (type == PACKED_FLOAT32_ARRAY || type == PACKED_INT32_ARRAY || type == PACKED_FLOAT64_ARRAY || type == PACKED_INT64_ARRAY || type == PACKED_BYTE_ARRAY) { Vector<int> addr = operator Vector<int>(); if (addr.size() == 4) { - return IP_Address(addr.get(0), addr.get(1), addr.get(2), addr.get(3)); + return IPAddress(addr.get(0), addr.get(1), addr.get(2), addr.get(3)); } } - return IP_Address(operator String()); + return IPAddress(operator String()); } Variant::Variant(bool p_bool) { @@ -2831,7 +2831,7 @@ void Variant::operator=(const Variant &p_variant) { } } -Variant::Variant(const IP_Address &p_address) { +Variant::Variant(const IPAddress &p_address) { type = STRING; memnew_placement(_data._mem, String(p_address)); } diff --git a/core/variant/variant.h b/core/variant/variant.h index 0acafc64fa..7f3c3477fc 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -359,7 +359,7 @@ public: operator Side() const; operator Orientation() const; - operator IP_Address() const; + operator IPAddress() const; Object *get_validated_object() const; Object *get_validated_object_with_check(bool &r_previously_freed) const; @@ -421,7 +421,7 @@ public: Variant(const Vector<::RID> &p_array); // helper Variant(const Vector<Vector2> &p_array); // helper - Variant(const IP_Address &p_address); + Variant(const IPAddress &p_address); // If this changes the table in variant_op must be updated enum Operator { diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 455e924568..efaaa8cd19 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1745,6 +1745,9 @@ static void _register_variant_builtin_methods() { bind_method(Array, reverse, sarray(), varray()); bind_method(Array, duplicate, sarray("deep"), varray(false)); bind_method(Array, slice, sarray("begin", "end", "step", "deep"), varray(1, false)); + bind_method(Array, filter, sarray("method"), varray()); + bind_method(Array, map, sarray("method"), varray()); + bind_method(Array, reduce, sarray("method", "accum"), varray(Variant())); bind_method(Array, max, sarray(), varray()); bind_method(Array, min, sarray(), varray()); diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 38b74cb436..404528db9a 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -258,6 +258,23 @@ [/codeblocks] </description> </method> + <method name="filter" qualifiers="const"> + <return type="Array"> + </return> + <argument index="0" name="method" type="Callable"> + </argument> + <description> + Calls the provided [Callable] for each element in array and removes all elements for which the method returned [code]false[/code]. + [codeblock] + func _ready(): + print([1, 2, 3].filter(remove_1)) # Prints [2, 3]. + print([1, 2, 3].filter(func(number): return number != 1)) # Same as above, but using lambda function. + + func remove_1(number): + return number != 1 + [/codeblock] + </description> + </method> <method name="find" qualifiers="const"> <return type="int"> </return> @@ -356,6 +373,23 @@ Returns [code]true[/code] if the array is empty. </description> </method> + <method name="map" qualifiers="const"> + <return type="Array"> + </return> + <argument index="0" name="method" type="Callable"> + </argument> + <description> + Calls the provided [Callable] for each element in array and replaces them with return value of the method. + [codeblock] + func _ready(): + print([1, 2, 3].map(negate)) # Prints [-1, -2, -3]. + print([1, 2, 3].map(func(number): return -number)) # Same as above, but using lambda function. + + func negate(number): + return -number + [/codeblock] + </description> + </method> <method name="max" qualifiers="const"> <return type="Variant"> </return> @@ -468,6 +502,25 @@ [b]Note:[/b] On large arrays, this method is much slower than [method push_back] as it will reindex all the array's elements every time it's called. The larger the array, the slower [method push_front] will be. </description> </method> + <method name="reduce" qualifiers="const"> + <return type="Variant"> + </return> + <argument index="0" name="method" type="Callable"> + </argument> + <argument index="1" name="accum" type="Variant" default="null"> + </argument> + <description> + Calls the provided [Callable] for each element in array and accumulates the result in [code]accum[/code]. The method for [Callable] takse two arguments: current value of [code]accum[/code] and the current array element. If [code]accum[/code] is [code]null[/code] (default value), the method will use first element from the array as initial value. + [codeblock] + func _ready(): + print([1, 2, 3].reduce(factorial, 1)) # Prints 6. + print([1, 2, 3].reduce(func(accum, number): return accum * number)) # Same as above, but using lambda function. + + func factorial(accum, number): + return accum * number + [/codeblock] + </description> + </method> <method name="remove"> <return type="void"> </return> diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml index 55190c5f9f..113cc64b9d 100644 --- a/doc/classes/AudioStreamPlayer.xml +++ b/doc/classes/AudioStreamPlayer.xml @@ -5,6 +5,7 @@ </brief_description> <description> Plays an audio stream non-positionally. + To play audio positionally, use [AudioStreamPlayer2D] or [AudioStreamPlayer3D] instead of [AudioStreamPlayer]. </description> <tutorials> <link title="Audio streams">https://docs.godotengine.org/en/latest/tutorials/audio/audio_streams.html</link> diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml index d8b9385736..e7c276f463 100644 --- a/doc/classes/AudioStreamPlayer2D.xml +++ b/doc/classes/AudioStreamPlayer2D.xml @@ -1,10 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AudioStreamPlayer2D" inherits="Node2D" version="4.0"> <brief_description> - Plays audio in 2D. + Plays positional sound in 2D space. </brief_description> <description> Plays audio that dampens with distance from screen center. + See also [AudioStreamPlayer] to play a sound non-positionally. + [b]Note:[/b] Hiding an [AudioStreamPlayer2D] node does not disable its audio output. To temporarily disable an [AudioStreamPlayer2D]'s audio output, set [member volume_db] to a very low value like [code]-100[/code] (which isn't audible to human hearing). </description> <tutorials> <link title="Audio streams">https://docs.godotengine.org/en/latest/tutorials/audio/audio_streams.html</link> diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml index 7a8c4b2cc7..db46ed2778 100644 --- a/doc/classes/AudioStreamPlayer3D.xml +++ b/doc/classes/AudioStreamPlayer3D.xml @@ -1,11 +1,13 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AudioStreamPlayer3D" inherits="Node3D" version="4.0"> <brief_description> - Plays 3D sound in 3D space. + Plays positional sound in 3D space. </brief_description> <description> Plays a sound effect with directed sound effects, dampens with distance if needed, generates effect of hearable position in space. For greater realism, a low-pass filter is automatically applied to distant sounds. This can be disabled by setting [member attenuation_filter_cutoff_hz] to [code]20500[/code]. By default, audio is heard from the camera position. This can be changed by adding a [Listener3D] node to the scene and enabling it by calling [method Listener3D.make_current] on it. + See also [AudioStreamPlayer] to play a sound non-positionally. + [b]Note:[/b] Hiding an [AudioStreamPlayer3D] node does not disable its audio output. To temporarily disable an [AudioStreamPlayer3D]'s audio output, set [member unit_db] to a very low value like [code]-100[/code] (which isn't audible to human hearing). </description> <tutorials> <link title="Audio streams">https://docs.godotengine.org/en/latest/tutorials/audio/audio_streams.html</link> diff --git a/doc/classes/ButtonGroup.xml b/doc/classes/ButtonGroup.xml index 5aa2d699a8..0b31352611 100644 --- a/doc/classes/ButtonGroup.xml +++ b/doc/classes/ButtonGroup.xml @@ -28,6 +28,15 @@ <members> <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" override="true" default="true" /> </members> + <signals> + <signal name="pressed"> + <argument index="0" name="button" type="Object"> + </argument> + <description> + Emitted when one of the buttons of the group is pressed. + </description> + </signal> + </signals> <constants> </constants> </class> diff --git a/doc/classes/IP.xml b/doc/classes/IP.xml index 849f036bbd..44da913492 100644 --- a/doc/classes/IP.xml +++ b/doc/classes/IP.xml @@ -4,7 +4,7 @@ Internet protocol (IP) support functions such as DNS resolution. </brief_description> <description> - IP contains support functions for the Internet Protocol (IP). TCP/IP support is in different classes (see [StreamPeerTCP] and [TCP_Server]). IP provides DNS hostname resolution support, both blocking and threaded. + IP contains support functions for the Internet Protocol (IP). TCP/IP support is in different classes (see [StreamPeerTCP] and [TCPServer]). IP provides DNS hostname resolution support, both blocking and threaded. </description> <tutorials> </tutorials> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 8c90108aef..d997073849 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -143,7 +143,7 @@ Returns the command-line arguments passed to the engine. Command-line arguments can be written in any form, including both [code]--key value[/code] and [code]--key=value[/code] forms so they can be properly parsed, as long as custom command-line arguments do not conflict with engine arguments. You can also incorporate environment variables using the [method get_environment] method. - You can set [code]editor/main_run_args[/code] in the Project Settings to define command-line arguments to be passed by the editor when running the project. + You can set [member ProjectSettings.editor/run/main_run_args] to define command-line arguments to be passed by the editor when running the project. Here's a minimal example on how to parse command-line arguments into a dictionary using the [code]--key=value[/code] form for arguments: [codeblocks] [gdscript] diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 005873c2ff..3200f789b8 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -542,6 +542,14 @@ <member name="editor/node_naming/name_num_separator" type="int" setter="" getter="" default="0"> What to use to separate node name from number. This is mostly an editor setting. </member> + <member name="editor/run/main_run_args" type="String" setter="" getter="" default=""""> + The command-line arguments to append to Godot's own command line when running the project. This doesn't affect the editor itself. + It is possible to make another executable run Godot by using the [code]%command%[/code] placeholder. The placeholder will be replaced with Godot's own command line. Program-specific arguments should be placed [i]before[/i] the placeholder, whereas Godot-specific arguments should be placed [i]after[/i] the placeholder. + For example, this can be used to force the project to run on the dedicated GPU in a NVIDIA Optimus system on Linux: + [codeblock] + prime-run %command% + [/codeblock] + </member> <member name="editor/script/search_in_file_extensions" type="PackedStringArray" setter="" getter="" default="PackedStringArray( "gd", "shader" )"> Text-based file extensions to include in the script editor's "Find in Files" feature. You can add e.g. [code]tscn[/code] if you wish to also parse your scene files, especially if you use built-in scripts which are serialized in the scene files. </member> diff --git a/doc/classes/TCP_Server.xml b/doc/classes/TCPServer.xml index ec91d75d47..28f06ad3ae 100644 --- a/doc/classes/TCP_Server.xml +++ b/doc/classes/TCPServer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TCP_Server" inherits="Reference" version="4.0"> +<class name="TCPServer" inherits="Reference" version="4.0"> <brief_description> A TCP server. </brief_description> diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 8ec1de4386..053e3fd9d6 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -75,8 +75,8 @@ #include <net/if.h> // Order is important on OpenBSD, leave as last #endif -static IP_Address _sockaddr2ip(struct sockaddr *p_addr) { - IP_Address ip; +static IPAddress _sockaddr2ip(struct sockaddr *p_addr) { + IPAddress ip; if (p_addr->sa_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)p_addr; @@ -89,7 +89,7 @@ static IP_Address _sockaddr2ip(struct sockaddr *p_addr) { return ip; }; -IP_Address IP_Unix::_resolve_hostname(const String &p_hostname, Type p_type) { +IPAddress IPUnix::_resolve_hostname(const String &p_hostname, Type p_type) { struct addrinfo hints; struct addrinfo *result = nullptr; @@ -108,7 +108,7 @@ IP_Address IP_Unix::_resolve_hostname(const String &p_hostname, Type p_type) { int s = getaddrinfo(p_hostname.utf8().get_data(), nullptr, &hints, &result); if (s != 0) { ERR_PRINT("getaddrinfo failed! Cannot resolve hostname."); - return IP_Address(); + return IPAddress(); }; if (result == nullptr || result->ai_addr == nullptr) { @@ -116,10 +116,10 @@ IP_Address IP_Unix::_resolve_hostname(const String &p_hostname, Type p_type) { if (result) { freeaddrinfo(result); } - return IP_Address(); + return IPAddress(); }; - IP_Address ip = _sockaddr2ip(result->ai_addr); + IPAddress ip = _sockaddr2ip(result->ai_addr); freeaddrinfo(result); @@ -130,7 +130,7 @@ IP_Address IP_Unix::_resolve_hostname(const String &p_hostname, Type p_type) { #if defined(UWP_ENABLED) -void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const { +void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const { using namespace Windows::Networking; using namespace Windows::Networking::Connectivity; @@ -156,14 +156,14 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co Interface_Info &info = E->get(); - IP_Address ip = IP_Address(hostname->CanonicalName->Data()); + IPAddress ip = IPAddress(hostname->CanonicalName->Data()); info.ip_addresses.push_front(ip); } } #else -void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const { +void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const { ULONG buf_size = 1024; IP_ADAPTER_ADDRESSES *addrs; @@ -211,7 +211,7 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co #else // UNIX -void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const { +void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const { struct ifaddrs *ifAddrStruct = nullptr; struct ifaddrs *ifa = nullptr; int family; @@ -249,15 +249,15 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co } #endif -void IP_Unix::make_default() { +void IPUnix::make_default() { _create = _create_unix; } -IP *IP_Unix::_create_unix() { - return memnew(IP_Unix); +IP *IPUnix::_create_unix() { + return memnew(IPUnix); } -IP_Unix::IP_Unix() { +IPUnix::IPUnix() { } #endif diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index ca2ee17f4e..e6479be6e5 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -35,10 +35,10 @@ #if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) -class IP_Unix : public IP { - GDCLASS(IP_Unix, IP); +class IPUnix : public IP { + GDCLASS(IPUnix, IP); - virtual IP_Address _resolve_hostname(const String &p_hostname, IP::Type p_type) override; + virtual IPAddress _resolve_hostname(const String &p_hostname, IP::Type p_type) override; static IP *_create_unix(); @@ -46,7 +46,7 @@ public: virtual void get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const override; static void make_default(); - IP_Unix(); + IPUnix(); }; #endif diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index e2ad352c10..222aef998c 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -95,7 +95,7 @@ #endif -size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const IP_Address &p_ip, uint16_t p_port, IP::Type p_ip_type) { +size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type) { memset(p_addr, 0, sizeof(struct sockaddr_storage)); if (p_ip_type == IP::TYPE_IPV6 || p_ip_type == IP::TYPE_ANY) { // IPv6 socket @@ -130,7 +130,7 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const } } -void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IP_Address *r_ip, uint16_t *r_port) { +void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port) { if (p_addr->ss_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr; if (r_ip) { @@ -233,7 +233,7 @@ NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const { #pragma GCC diagnostic pop #endif -bool NetSocketPosix::_can_use_ip(const IP_Address &p_ip, const bool p_for_bind) const { +bool NetSocketPosix::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const { if (p_for_bind && !(p_ip.is_valid() || p_ip.is_wildcard())) { return false; } else if (!p_for_bind && !p_ip.is_valid()) { @@ -244,7 +244,7 @@ bool NetSocketPosix::_can_use_ip(const IP_Address &p_ip, const bool p_for_bind) return !(_ip_type != IP::TYPE_ANY && !p_ip.is_wildcard() && _ip_type != type); } -_FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, String p_if_name, bool p_add) { +_FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); ERR_FAIL_COND_V(!_can_use_ip(p_ip, false), ERR_INVALID_PARAMETER); @@ -254,7 +254,7 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, St int level = type == IP::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; int ret = -1; - IP_Address if_ip; + IPAddress if_ip; uint32_t if_v6id = 0; Map<String, IP::Interface_Info> if_info; IP::get_singleton()->get_local_interfaces(&if_info); @@ -269,7 +269,7 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, St break; // IPv6 uses index. } - for (List<IP_Address>::Element *F = c.ip_addresses.front(); F; F = F->next()) { + for (List<IPAddress>::Element *F = c.ip_addresses.front(); F; F = F->next()) { if (!F->get().is_ipv4()) { continue; // Wrong IP type } @@ -395,7 +395,7 @@ void NetSocketPosix::close() { _is_stream = false; } -Error NetSocketPosix::bind(IP_Address p_addr, uint16_t p_port) { +Error NetSocketPosix::bind(IPAddress p_addr, uint16_t p_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); ERR_FAIL_COND_V(!_can_use_ip(p_addr, true), ERR_INVALID_PARAMETER); @@ -425,7 +425,7 @@ Error NetSocketPosix::listen(int p_max_pending) { return OK; } -Error NetSocketPosix::connect_to_host(IP_Address p_host, uint16_t p_port) { +Error NetSocketPosix::connect_to_host(IPAddress p_host, uint16_t p_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); ERR_FAIL_COND_V(!_can_use_ip(p_host, false), ERR_INVALID_PARAMETER); @@ -559,7 +559,7 @@ Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) { return OK; } -Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port, bool p_peek) { +Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); struct sockaddr_storage from; @@ -616,7 +616,7 @@ Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { return OK; } -Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) { +Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); struct sockaddr_storage addr; @@ -735,7 +735,7 @@ int NetSocketPosix::get_available_bytes() const { return len; } -Error NetSocketPosix::get_socket_address(IP_Address *r_ip, uint16_t *r_port) const { +Error NetSocketPosix::get_socket_address(IPAddress *r_ip, uint16_t *r_port) const { ERR_FAIL_COND_V(!is_open(), FAILED); struct sockaddr_storage saddr; @@ -749,7 +749,7 @@ Error NetSocketPosix::get_socket_address(IP_Address *r_ip, uint16_t *r_port) con return OK; } -Ref<NetSocket> NetSocketPosix::accept(IP_Address &r_ip, uint16_t &r_port) { +Ref<NetSocket> NetSocketPosix::accept(IPAddress &r_ip, uint16_t &r_port) { Ref<NetSocket> out; ERR_FAIL_COND_V(!is_open(), out); @@ -770,11 +770,11 @@ Ref<NetSocket> NetSocketPosix::accept(IP_Address &r_ip, uint16_t &r_port) { return Ref<NetSocket>(ns); } -Error NetSocketPosix::join_multicast_group(const IP_Address &p_multi_address, String p_if_name) { +Error NetSocketPosix::join_multicast_group(const IPAddress &p_multi_address, String p_if_name) { return _change_multicast_group(p_multi_address, p_if_name, true); } -Error NetSocketPosix::leave_multicast_group(const IP_Address &p_multi_address, String p_if_name) { +Error NetSocketPosix::leave_multicast_group(const IPAddress &p_multi_address, String p_if_name) { return _change_multicast_group(p_multi_address, p_if_name, false); } #endif diff --git a/drivers/unix/net_socket_posix.h b/drivers/unix/net_socket_posix.h index dbfe3a524e..38c8170a52 100644 --- a/drivers/unix/net_socket_posix.h +++ b/drivers/unix/net_socket_posix.h @@ -61,35 +61,35 @@ private: NetError _get_socket_error() const; void _set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_is_stream); - _FORCE_INLINE_ Error _change_multicast_group(IP_Address p_ip, String p_if_name, bool p_add); + _FORCE_INLINE_ Error _change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add); _FORCE_INLINE_ void _set_close_exec_enabled(bool p_enabled); protected: static NetSocket *_create_func(); - bool _can_use_ip(const IP_Address &p_ip, const bool p_for_bind) const; + bool _can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const; public: static void make_default(); static void cleanup(); - static void _set_ip_port(struct sockaddr_storage *p_addr, IP_Address *r_ip, uint16_t *r_port); - static size_t _set_addr_storage(struct sockaddr_storage *p_addr, const IP_Address &p_ip, uint16_t p_port, IP::Type p_ip_type); + static void _set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port); + static size_t _set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type); virtual Error open(Type p_sock_type, IP::Type &ip_type); virtual void close(); - virtual Error bind(IP_Address p_addr, uint16_t p_port); + virtual Error bind(IPAddress p_addr, uint16_t p_port); virtual Error listen(int p_max_pending); - virtual Error connect_to_host(IP_Address p_host, uint16_t p_port); + virtual Error connect_to_host(IPAddress p_host, uint16_t p_port); virtual Error poll(PollType p_type, int timeout) const; virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read); - virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port, bool p_peek = false); + virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false); virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent); - virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port); - virtual Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port); + virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port); + virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port); virtual bool is_open() const; virtual int get_available_bytes() const; - virtual Error get_socket_address(IP_Address *r_ip, uint16_t *r_port) const; + virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const; virtual Error set_broadcasting_enabled(bool p_enabled); virtual void set_blocking_enabled(bool p_enabled); @@ -97,8 +97,8 @@ public: virtual void set_tcp_no_delay_enabled(bool p_enabled); virtual void set_reuse_address_enabled(bool p_enabled); virtual void set_reuse_port_enabled(bool p_enabled); - virtual Error join_multicast_group(const IP_Address &p_multi_address, String p_if_name); - virtual Error leave_multicast_group(const IP_Address &p_multi_address, String p_if_name); + virtual Error join_multicast_group(const IPAddress &p_multi_address, String p_if_name); + virtual Error leave_multicast_group(const IPAddress &p_multi_address, String p_if_name); NetSocketPosix(); ~NetSocketPosix(); diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index b9bd773c2e..15cd7bee92 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -129,7 +129,7 @@ void OS_Unix::initialize_core() { #ifndef NO_NETWORK NetSocketPosix::make_default(); - IP_Unix::make_default(); + IPUnix::make_default(); #endif _setup_clock(); diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 30cc01fd10..43b2a24172 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -7844,6 +7844,10 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de device_capabilities.subgroup_size = subgroup_capabilities.size; device_capabilities.subgroup_in_shaders = subgroup_capabilities.supported_stages_flags_rd(); device_capabilities.subgroup_operations = subgroup_capabilities.supported_operations_flags_rd(); + + // get info about further features + VulkanContext::MultiviewCapabilities multiview_capabilies = p_context->get_multiview_capabilities(); + device_capabilities.supports_multiview = multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1; } context = p_context; diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 0a8a5c746f..12a67c0e07 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -352,8 +352,6 @@ Error VulkanContext::_initialize_extensions() { return OK; } -typedef void(VKAPI_PTR *_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice, VkPhysicalDeviceProperties2 *); - uint32_t VulkanContext::SubgroupCapabilities::supported_stages_flags_rd() const { uint32_t flags = 0; @@ -496,20 +494,70 @@ String VulkanContext::SubgroupCapabilities::supported_operations_desc() const { } Error VulkanContext::_check_capabilities() { - // check subgroups + // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html // https://www.khronos.org/blog/vulkan-subgroup-tutorial + // for Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android. - _vkGetPhysicalDeviceProperties2 func = (_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2"); - if (func != nullptr) { + + // so we check if the functions are accessible by getting their function pointers and skipping if not + // (note that the desktop loader does a better job here but the android loader doesn't) + + // assume not supported until proven otherwise + multiview_capabilities.is_supported = false; + multiview_capabilities.max_view_count = 0; + multiview_capabilities.max_instance_count = 0; + subgroup_capabilities.size = 0; + subgroup_capabilities.supportedStages = 0; + subgroup_capabilities.supportedOperations = 0; + subgroup_capabilities.quadOperationsInAllStages = false; + + // check for extended features + PFN_vkGetPhysicalDeviceFeatures2 device_features_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2"); + if (device_features_func == nullptr) { + // In Vulkan 1.0 might be accessible under its original extension name + device_features_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR"); + } + if (device_features_func != nullptr) { + // check our extended features + VkPhysicalDeviceMultiviewFeatures multiview_features; + multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES; + multiview_features.pNext = NULL; + + VkPhysicalDeviceFeatures2 device_features; + device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + device_features.pNext = &multiview_features; + + device_features_func(gpu, &device_features); + multiview_capabilities.is_supported = multiview_features.multiview; + // For now we ignore if multiview is available in geometry and tesselation as we do not currently support those + } + + // check extended properties + PFN_vkGetPhysicalDeviceProperties2 device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2"); + if (device_properties_func == nullptr) { + // In Vulkan 1.0 might be accessible under its original extension name + device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR"); + } + if (device_properties_func != nullptr) { + VkPhysicalDeviceMultiviewProperties multiviewProperties; VkPhysicalDeviceSubgroupProperties subgroupProperties; + VkPhysicalDeviceProperties2 physicalDeviceProperties; + subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; subgroupProperties.pNext = nullptr; - VkPhysicalDeviceProperties2 physicalDeviceProperties; physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - physicalDeviceProperties.pNext = &subgroupProperties; - func(gpu, &physicalDeviceProperties); + if (multiview_capabilities.is_supported) { + multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES; + multiviewProperties.pNext = &subgroupProperties; + + physicalDeviceProperties.pNext = &multiviewProperties; + } else { + physicalDeviceProperties.pNext = &subgroupProperties; + } + + device_properties_func(gpu, &physicalDeviceProperties); subgroup_capabilities.size = subgroupProperties.subgroupSize; subgroup_capabilities.supportedStages = subgroupProperties.supportedStages; @@ -519,18 +567,30 @@ Error VulkanContext::_check_capabilities() { // - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages; - // only output this when debugging? - print_line("- Vulkan subgroup size " + itos(subgroup_capabilities.size)); - print_line("- Vulkan subgroup stages " + subgroup_capabilities.supported_stages_desc()); - print_line("- Vulkan subgroup supported ops " + subgroup_capabilities.supported_operations_desc()); + if (multiview_capabilities.is_supported) { + multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount; + multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex; + +#ifdef DEBUG_ENABLED + print_line("- Vulkan multiview supported:"); + print_line(" max views: " + itos(multiview_capabilities.max_view_count)); + print_line(" max instances: " + itos(multiview_capabilities.max_instance_count)); + } else { + print_line("- Vulkan multiview not supported"); +#endif + } + +#ifdef DEBUG_ENABLED + print_line("- Vulkan subgroup:"); + print_line(" size: " + itos(subgroup_capabilities.size)); + print_line(" stages: " + subgroup_capabilities.supported_stages_desc()); + print_line(" supported ops: " + subgroup_capabilities.supported_operations_desc()); if (subgroup_capabilities.quadOperationsInAllStages) { - print_line("- Vulkan subgroup quad operations in all stages"); + print_line(" quad operations in all stages"); } } else { - subgroup_capabilities.size = 0; - subgroup_capabilities.supportedStages = 0; - subgroup_capabilities.supportedOperations = 0; - subgroup_capabilities.quadOperationsInAllStages = false; + print_line("- Couldn't call vkGetPhysicalDeviceProperties2"); +#endif } return OK; diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index 88e4f26bb1..3d9b295c5a 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -54,6 +54,12 @@ public: String supported_operations_desc() const; }; + struct MultiviewCapabilities { + bool is_supported; + int32_t max_view_count; + int32_t max_instance_count; + }; + private: enum { MAX_EXTENSIONS = 128, @@ -75,6 +81,7 @@ private: uint32_t vulkan_major = 1; uint32_t vulkan_minor = 0; SubgroupCapabilities subgroup_capabilities; + MultiviewCapabilities multiview_capabilities; String device_vendor; String device_name; @@ -227,6 +234,7 @@ public: uint32_t get_vulkan_major() const { return vulkan_major; }; uint32_t get_vulkan_minor() const { return vulkan_minor; }; SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; }; + MultiviewCapabilities get_multiview_capabilities() const { return multiview_capabilities; }; VkDevice get_device(); VkPhysicalDevice get_physical_device(); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 711072f4b2..1c0a55e4ec 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -708,7 +708,6 @@ CreateDialog::CreateDialog() { search_hb->add_child(search_box); favorite = memnew(Button); - favorite->set_flat(true); favorite->set_toggle_mode(true); favorite->set_tooltip(TTR("(Un)favorite selected item.")); favorite->connect("pressed", callable_mp(this, &CreateDialog::_favorite_toggled)); diff --git a/editor/debugger/editor_debugger_server.cpp b/editor/debugger/editor_debugger_server.cpp index 4add891bcb..662f247062 100644 --- a/editor/debugger/editor_debugger_server.cpp +++ b/editor/debugger/editor_debugger_server.cpp @@ -40,7 +40,7 @@ class EditorDebuggerServerTCP : public EditorDebuggerServer { private: - Ref<TCP_Server> server; + Ref<TCPServer> server; public: static EditorDebuggerServer *create(const String &p_protocol); diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 9f188b53c4..7c485d53c5 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -75,6 +75,8 @@ void EditorLog::_notification(int p_what) { collapse_button->set_icon(get_theme_icon("CombineLines", "EditorIcons")); show_search_button->set_icon(get_theme_icon("Search", "EditorIcons")); + _load_state(); + } else if (p_what == NOTIFICATION_THEME_CHANGED) { Ref<Font> df_output_code = get_theme_font("output_source", "EditorFonts"); if (df_output_code.is_valid()) { @@ -89,9 +91,56 @@ void EditorLog::_notification(int p_what) { void EditorLog::_set_collapse(bool p_collapse) { collapse = p_collapse; + _start_state_save_timer(); _rebuild_log(); } +void EditorLog::_start_state_save_timer() { + if (!is_loading_state) { + save_state_timer->start(); + } +} + +void EditorLog::_save_state() { + Ref<ConfigFile> config; + config.instance(); + // Load and amend existing config if it exists. + config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + + const String section = "editor_log"; + for (Map<MessageType, LogFilter *>::Element *E = type_filter_map.front(); E; E = E->next()) { + config->set_value(section, "log_filter_" + itos(E->key()), E->get()->is_active()); + } + + config->set_value(section, "collapse", collapse); + config->set_value(section, "show_search", search_box->is_visible()); + + config->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); +} + +void EditorLog::_load_state() { + is_loading_state = true; + + Ref<ConfigFile> config; + config.instance(); + Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + + if (err == OK) { + const String section = "editor_log"; + for (Map<MessageType, LogFilter *>::Element *E = type_filter_map.front(); E; E = E->next()) { + E->get()->set_active(config->get_value(section, "log_filter_" + itos(E->key()), false)); + } + + collapse = config->get_value(section, "collapse", false); + collapse_button->set_pressed(collapse); + bool show_search = config->get_value(section, "show_search", true); + search_box->set_visible(show_search); + show_search_button->set_pressed(show_search); + } + + is_loading_state = false; +} + void EditorLog::_clear_request() { log->clear(); messages.clear(); @@ -175,7 +224,7 @@ void EditorLog::_rebuild_log() { void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) { // Only add the message to the log if it passes the filters. - bool filter_active = type_filter_map[p_message.type]->active; + bool filter_active = type_filter_map[p_message.type]->is_active(); String search_text = search_box->get_text(); bool search_match = search_text == String() || p_message.text.findn(search_text) > -1; @@ -187,8 +236,6 @@ void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) { // Remove last line if replacing, as it will be replace by the next added line. log->remove_line(log->get_line_count() - 1); log->increment_line_count(); - } else { - log->add_newline(); } switch (p_message.type) { @@ -222,6 +269,7 @@ void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) { } log->add_text(p_message.text); + log->add_newline(); // Need to use pop() to exit out of the RichTextLabels current "push" stack. // We only "push" in the above switch when message type != STD, so only pop when that is the case. @@ -231,7 +279,8 @@ void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) { } void EditorLog::_set_filter_active(bool p_active, MessageType p_message_type) { - type_filter_map[p_message_type]->active = p_active; + type_filter_map[p_message_type]->set_active(p_active); + _start_state_save_timer(); _rebuild_log(); } @@ -240,6 +289,7 @@ void EditorLog::_set_search_visible(bool p_visible) { if (p_visible) { search_box->grab_focus(); } + _start_state_save_timer(); } void EditorLog::_search_changed(const String &p_text) { @@ -258,6 +308,12 @@ void EditorLog::_bind_methods() { } EditorLog::EditorLog() { + save_state_timer = memnew(Timer); + save_state_timer->set_wait_time(2); + save_state_timer->set_one_shot(true); + save_state_timer->connect("timeout", callable_mp(this, &EditorLog::_save_state)); + add_child(save_state_timer); + HBoxContainer *hb = this; VBoxContainer *vb_left = memnew(VBoxContainer); diff --git a/editor/editor_log.h b/editor/editor_log.h index 89d00d0fa0..3b6476634a 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -72,11 +72,11 @@ private: private: // Force usage of set method since it has functionality built-in. int message_count = 0; + bool active = true; public: MessageType type; Button *toggle_button = nullptr; - bool active = true; void initialize_button(const String &p_tooltip, Callable p_toggled_callback) { toggle_button = memnew(Button); @@ -100,6 +100,15 @@ private: toggle_button->set_text(itos(message_count)); } + bool is_active() { + return active; + } + + void set_active(bool p_active) { + toggle_button->set_pressed(p_active); + active = p_active; + } + LogFilter(MessageType p_type) : type(p_type) { } @@ -124,6 +133,9 @@ private: // Warnings or Errors are encounetered. Button *tool_button; + bool is_loading_state = false; // Used to disable saving requests while loading (some signals from buttons will try trigger a save, which happens during loading). + Timer *save_state_timer; + static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type); ErrorHandlerList eh; @@ -147,6 +159,10 @@ private: void _set_collapse(bool p_collapse); + void _start_state_save_timer(); + void _save_state(); + void _load_state(); + protected: static void _bind_methods(); void _notification(int p_what); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 8eeabf9cfd..6390755656 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4362,6 +4362,8 @@ void EditorNode::_save_docks() { } Ref<ConfigFile> config; config.instance(); + // Load and amend existing config if it exists. + config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); _save_docks_to_config(config, "docks"); _save_open_scenes_to_config(config, "EditorNode"); @@ -5877,8 +5879,6 @@ EditorNode::EditorNode() { register_exporters(); - GLOBAL_DEF("editor/run/main_run_args", ""); - ClassDB::set_class_enabled("RootMotionView", true); //defs here, use EDITOR_GET in logic @@ -6491,7 +6491,6 @@ EditorNode::EditorNode() { // Toggle for video driver video_driver = memnew(OptionButton); - video_driver->set_flat(true); video_driver->set_focus_mode(Control::FOCUS_NONE); video_driver->connect("item_selected", callable_mp(this, &EditorNode::_video_driver_selected)); video_driver->add_theme_font_override("font", gui_base->get_theme_font("bold", "EditorFonts")); diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index de688f2709..fb2980c948 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -575,7 +575,6 @@ EditorPropertyArray::EditorPropertyArray() { object.instance(); page_len = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page")); edit = memnew(Button); - edit->set_flat(true); edit->set_h_size_flags(SIZE_EXPAND_FILL); edit->set_clip_text(true); edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_edit_pressed)); @@ -1070,7 +1069,6 @@ EditorPropertyDictionary::EditorPropertyDictionary() { object.instance(); page_len = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page")); edit = memnew(Button); - edit->set_flat(true); edit->set_h_size_flags(SIZE_EXPAND_FILL); edit->set_clip_text(true); edit->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_edit_pressed)); diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index e46f4eb65a..5e6d2ab69c 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -183,15 +183,50 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L args.push_back(p_scene); } + String exec = OS::get_singleton()->get_executable_path(); + if (p_custom_args != "") { - Vector<String> cargs = p_custom_args.split(" ", false); - for (int i = 0; i < cargs.size(); i++) { - args.push_back(cargs[i].replace(" ", "%20")); + // Allow the user to specify a command to run, similar to Steam's launch options. + // In this case, Godot will no longer be run directly; it's up to the underlying command + // to run it. For instance, this can be used on Linux to force a running project + // to use Optimus using `prime-run` or similar. + // Example: `prime-run %command% --time-scale 0.5` + const int placeholder_pos = p_custom_args.find("%command%"); + + Vector<String> custom_args; + + if (placeholder_pos != -1) { + // Prepend executable-specific custom arguments. + // If nothing is placed before `%command%`, behave as if no placeholder was specified. + Vector<String> exec_args = p_custom_args.substr(0, placeholder_pos).split(" ", false); + if (exec_args.size() >= 1) { + exec = exec_args[0]; + exec_args.remove(0); + + // Append the Godot executable name before we append executable arguments + // (since the order is reversed when using `push_front()`). + args.push_front(OS::get_singleton()->get_executable_path()); + } + + for (int i = exec_args.size() - 1; i >= 0; i--) { + // Iterate backwards as we're pushing items in the reverse order. + args.push_front(exec_args[i].replace(" ", "%20")); + } + + // Append Godot-specific custom arguments. + custom_args = p_custom_args.substr(placeholder_pos + String("%command%").size()).split(" ", false); + for (int i = 0; i < custom_args.size(); i++) { + args.push_back(custom_args[i].replace(" ", "%20")); + } + } else { + // Append Godot-specific custom arguments. + custom_args = p_custom_args.split(" ", false); + for (int i = 0; i < custom_args.size(); i++) { + args.push_back(custom_args[i].replace(" ", "%20")); + } } } - String exec = OS::get_singleton()->get_executable_path(); - printf("Running: %s", exec.utf8().get_data()); for (List<String>::Element *E = args.front(); E; E = E->next()) { printf(" %s", E->get().utf8().get_data()); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 4ddae7c062..7e450ed5fc 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -437,7 +437,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Theme _initial_set("interface/theme/preset", "Default"); - hints["interface/theme/preset"] = PropertyInfo(Variant::STRING, "interface/theme/preset", PROPERTY_HINT_ENUM, "Default,Alien,Arc,Godot 2,Grey,Light,Solarized (Dark),Solarized (Light),Custom", PROPERTY_USAGE_DEFAULT); + hints["interface/theme/preset"] = PropertyInfo(Variant::STRING, "interface/theme/preset", PROPERTY_HINT_ENUM, "Default,Breeze Dark,Godot 2,Grey,Light,Solarized (Dark),Solarized (Light),Custom", PROPERTY_USAGE_DEFAULT); _initial_set("interface/theme/icon_and_font_color", 0); hints["interface/theme/icon_and_font_color"] = PropertyInfo(Variant::INT, "interface/theme/icon_and_font_color", PROPERTY_HINT_ENUM, "Auto,Dark,Light", PROPERTY_USAGE_DEFAULT); _initial_set("interface/theme/base_color", Color(0.2, 0.23, 0.31)); @@ -450,10 +450,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { hints["interface/theme/icon_saturation"] = PropertyInfo(Variant::FLOAT, "interface/theme/icon_saturation", PROPERTY_HINT_RANGE, "0,2,0.01", PROPERTY_USAGE_DEFAULT); _initial_set("interface/theme/relationship_line_opacity", 0.1); hints["interface/theme/relationship_line_opacity"] = PropertyInfo(Variant::FLOAT, "interface/theme/relationship_line_opacity", PROPERTY_HINT_RANGE, "0.00, 1, 0.01"); - _initial_set("interface/theme/highlight_tabs", false); - _initial_set("interface/theme/border_size", 1); - _initial_set("interface/theme/use_graph_node_headers", false); + _initial_set("interface/theme/border_size", 0); hints["interface/theme/border_size"] = PropertyInfo(Variant::INT, "interface/theme/border_size", PROPERTY_HINT_RANGE, "0,2,1", PROPERTY_USAGE_DEFAULT); + _initial_set("interface/theme/corner_radius", 3); + hints["interface/theme/corner_radius"] = PropertyInfo(Variant::INT, "interface/theme/corner_radius", PROPERTY_HINT_RANGE, "0,6,1", PROPERTY_USAGE_DEFAULT); _initial_set("interface/theme/additional_spacing", 0); hints["interface/theme/additional_spacing"] = PropertyInfo(Variant::FLOAT, "interface/theme/additional_spacing", PROPERTY_HINT_RANGE, "0,5,0.1", PROPERTY_USAGE_DEFAULT); _initial_set("interface/theme/custom_theme", ""); @@ -1138,14 +1138,14 @@ void EditorSettings::setup_language() { } void EditorSettings::setup_network() { - List<IP_Address> local_ip; + List<IPAddress> local_ip; IP::get_singleton()->get_local_addresses(&local_ip); String hint; String current = has_setting("network/debug/remote_host") ? get("network/debug/remote_host") : ""; String selected = "127.0.0.1"; // Check that current remote_host is a valid interface address and populate hints. - for (List<IP_Address>::Element *E = local_ip.front(); E; E = E->next()) { + for (List<IPAddress>::Element *E = local_ip.front(); E; E = E->next()) { String ip = E->get(); // link-local IPv6 addresses don't work, skipping them diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 7cc9ebd63e..44b4a9f688 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -65,9 +65,12 @@ static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_ return style; } -static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { +static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, int p_corner_width = 0) { Ref<StyleBoxFlat> style(memnew(StyleBoxFlat)); style->set_bg_color(p_color); + // Adjust level of detail based on the corners' effective sizes. + style->set_corner_detail(Math::ceil(1.5 * p_corner_width * EDSCALE)); + style->set_corner_radius_all(p_corner_width); style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE); style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE); style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE); @@ -286,9 +289,9 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { Ref<Theme> theme = Ref<Theme>(memnew(Theme)); - const float default_contrast = 0.25; + const float default_contrast = 0.3; - //Theme settings + // Theme settings Color accent_color = EDITOR_GET("interface/theme/accent_color"); Color base_color = EDITOR_GET("interface/theme/base_color"); float contrast = EDITOR_GET("interface/theme/contrast"); @@ -297,56 +300,47 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { String preset = EDITOR_GET("interface/theme/preset"); - bool highlight_tabs = EDITOR_GET("interface/theme/highlight_tabs"); int border_size = EDITOR_GET("interface/theme/border_size"); - - bool use_gn_headers = EDITOR_GET("interface/theme/use_graph_node_headers"); + int corner_radius = EDITOR_GET("interface/theme/corner_radius"); Color preset_accent_color; Color preset_base_color; float preset_contrast = 0; - // Please, use alphabet order if you've added new theme here(After "Default" and "Custom") + // Please use alphabetical order if you're adding a new theme here + // (after "Custom") - if (preset == "Default") { - preset_accent_color = Color(0.41, 0.61, 0.91); - preset_base_color = Color(0.2, 0.23, 0.31); - preset_contrast = default_contrast; - } else if (preset == "Custom") { + if (preset == "Custom") { accent_color = EDITOR_GET("interface/theme/accent_color"); base_color = EDITOR_GET("interface/theme/base_color"); contrast = EDITOR_GET("interface/theme/contrast"); - } else if (preset == "Alien") { - preset_accent_color = Color(0.11, 1.0, 0.6); - preset_base_color = Color(0.18, 0.22, 0.25); - preset_contrast = 0.25; - } else if (preset == "Arc") { - preset_accent_color = Color(0.32, 0.58, 0.89); - preset_base_color = Color(0.22, 0.24, 0.29); - preset_contrast = 0.25; + } else if (preset == "Breeze Dark") { + preset_accent_color = Color(0.26, 0.76, 1.00); + preset_base_color = Color(0.24, 0.26, 0.28); + preset_contrast = default_contrast; } else if (preset == "Godot 2") { preset_accent_color = Color(0.53, 0.67, 0.89); preset_base_color = Color(0.24, 0.23, 0.27); - preset_contrast = 0.25; + preset_contrast = default_contrast; } else if (preset == "Grey") { - preset_accent_color = Color(0.72, 0.89, 1.0); + preset_accent_color = Color(0.72, 0.89, 1.00); preset_base_color = Color(0.24, 0.24, 0.24); - preset_contrast = 0.2; + preset_contrast = default_contrast; } else if (preset == "Light") { - preset_accent_color = Color(0.13, 0.44, 1.0); - preset_base_color = Color(1, 1, 1); + preset_accent_color = Color(0.18, 0.50, 1.00); + preset_base_color = Color(1.00, 1.00, 1.00); preset_contrast = 0.08; } else if (preset == "Solarized (Dark)") { preset_accent_color = Color(0.15, 0.55, 0.82); - preset_base_color = Color(0.03, 0.21, 0.26); - preset_contrast = 0.23; + preset_base_color = Color(0.04, 0.23, 0.27); + preset_contrast = default_contrast; } else if (preset == "Solarized (Light)") { preset_accent_color = Color(0.15, 0.55, 0.82); preset_base_color = Color(0.99, 0.96, 0.89); - preset_contrast = 0.06; + preset_contrast = 0.08; } else { // Default - preset_accent_color = Color(0.41, 0.61, 0.91); - preset_base_color = Color(0.2, 0.23, 0.31); + preset_accent_color = Color(0.44, 0.73, 0.98); + preset_base_color = Color(0.21, 0.24, 0.29); preset_contrast = default_contrast; } @@ -358,12 +352,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", base_color); EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", contrast); } + EditorSettings::get_singleton()->set_manually("interface/theme/preset", preset); EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", accent_color); EditorSettings::get_singleton()->set_manually("interface/theme/base_color", base_color); EditorSettings::get_singleton()->set_manually("interface/theme/contrast", contrast); - //Colors + // Colors bool dark_theme = EditorSettings::get_singleton()->is_dark_theme(); const Color dark_color_1 = base_color.lerp(Color(0, 0, 0, 1), contrast); @@ -372,14 +367,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color background_color = dark_color_2; - // white (dark theme) or black (light theme), will be used to generate the rest of the colors + // White (dark theme) or black (light theme), will be used to generate the rest of the colors const Color mono_color = dark_theme ? Color(1, 1, 1) : Color(0, 0, 0); const Color contrast_color_1 = base_color.lerp(mono_color, MAX(contrast, default_contrast)); const Color contrast_color_2 = base_color.lerp(mono_color, MAX(contrast * 1.5, default_contrast * 1.5)); const Color font_color = mono_color.lerp(base_color, 0.25); - const Color font_hover_color = mono_color.lerp(base_color, 0.15); + const Color font_hover_color = mono_color.lerp(base_color, 0.125); const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.3); const Color selection_color = accent_color * Color(1, 1, 1, 0.4); const Color disabled_color = mono_color.inverted().lerp(base_color, 0.7); @@ -393,8 +388,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { icon_pressed_color.a = 1.0; const Color separator_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.1); - - const Color highlight_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.2); + const Color highlight_color = Color(accent_color.r, accent_color.g, accent_color.b, 0.275); float prev_icon_saturation = theme->has_color("icon_saturation", "Editor") ? theme->get_color("icon_saturation", "Editor").r : 1.0; @@ -447,35 +441,35 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("thumb_size", "Editor", thumb_size); theme->set_constant("dark_theme", "Editor", dark_theme); - //Register icons + font + // Register icons + font - // the resolution and the icon color (dark_theme bool) has not changed, so we do not regenerate the icons + // The resolution and the icon color (dark_theme bool) has not changed, so we do not regenerate the icons. if (p_theme != nullptr && fabs(p_theme->get_constant("scale", "Editor") - EDSCALE) < 0.00001 && (bool)p_theme->get_constant("dark_theme", "Editor") == dark_theme && prev_icon_saturation == icon_saturation) { - // register already generated icons + // Register already generated icons. for (int i = 0; i < editor_icons_count; i++) { theme->set_icon(editor_icons_names[i], "EditorIcons", p_theme->get_icon(editor_icons_names[i], "EditorIcons")); } } else { editor_register_and_generate_icons(theme, dark_theme, thumb_size, false, icon_saturation); } - // thumbnail size has changed, so we regenerate the medium sizes + // Thumbnail size has changed, so we regenerate the medium sizes if (p_theme != nullptr && fabs((double)p_theme->get_constant("thumb_size", "Editor") - thumb_size) > 0.00001) { editor_register_and_generate_icons(p_theme, dark_theme, thumb_size, true); } editor_register_fonts(theme); - // Highlighted tabs and border width - Color tab_color = highlight_tabs ? base_color.lerp(font_color, contrast) : base_color; // Ensure borders are visible when using an editor scale below 100%. - const int border_width = CLAMP(border_size, 0, 3) * MAX(1, EDSCALE); - + const int border_width = CLAMP(border_size, 0, 2) * MAX(1, EDSCALE); + const int corner_width = CLAMP(corner_radius, 0, 6) * EDSCALE; const int default_margin_size = 4; - const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 3); + const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 2); - // styleboxes - // this is the most commonly used stylebox, variations should be made as duplicate of this - Ref<StyleBoxFlat> style_default = make_flat_stylebox(base_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size); + // Styleboxes + // This is the most commonly used stylebox, variations should be made as duplicate of this + Ref<StyleBoxFlat> style_default = make_flat_stylebox(base_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size, corner_width); + // Work around issue about antialiased edges being blurrier (GH-35279). + style_default->set_anti_aliased(false); style_default->set_border_width_all(border_width); style_default->set_border_color(base_color); style_default->set_draw_center(true); @@ -483,11 +477,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Button and widgets const float extra_spacing = EDITOR_GET("interface/theme/additional_spacing"); + const Vector2 widget_default_margin = Vector2(extra_spacing + 6, extra_spacing + default_margin_size + 1) * EDSCALE; + Ref<StyleBoxFlat> style_widget = style_default->duplicate(); - style_widget->set_default_margin(SIDE_LEFT, (extra_spacing + 6) * EDSCALE); - style_widget->set_default_margin(SIDE_TOP, (extra_spacing + default_margin_size) * EDSCALE); - style_widget->set_default_margin(SIDE_RIGHT, (extra_spacing + 6) * EDSCALE); - style_widget->set_default_margin(SIDE_BOTTOM, (extra_spacing + default_margin_size) * EDSCALE); + style_widget->set_default_margin(SIDE_LEFT, widget_default_margin.x); + style_widget->set_default_margin(SIDE_TOP, widget_default_margin.y); + style_widget->set_default_margin(SIDE_RIGHT, widget_default_margin.x); + style_widget->set_default_margin(SIDE_BOTTOM, widget_default_margin.y); style_widget->set_bg_color(dark_color_1); style_widget->set_border_color(dark_color_2); @@ -496,69 +492,82 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_widget_disabled->set_bg_color(disabled_bg_color); Ref<StyleBoxFlat> style_widget_focus = style_widget->duplicate(); + style_widget_focus->set_draw_center(false); + style_widget_focus->set_border_width_all(Math::round(2 * MAX(1, EDSCALE))); style_widget_focus->set_border_color(accent_color); Ref<StyleBoxFlat> style_widget_pressed = style_widget->duplicate(); - style_widget_pressed->set_border_color(accent_color); + style_widget_pressed->set_bg_color(dark_color_1.darkened(0.125)); Ref<StyleBoxFlat> style_widget_hover = style_widget->duplicate(); - style_widget_hover->set_border_color(contrast_color_1); + style_widget_hover->set_bg_color(mono_color * Color(1, 1, 1, 0.11)); + style_widget_hover->set_border_color(mono_color * Color(1, 1, 1, 0.05)); - // style for windows, popups, etc.. + // Style for windows, popups, etc.. Ref<StyleBoxFlat> style_popup = style_default->duplicate(); - const int popup_margin_size = default_margin_size * EDSCALE * 2; + const int popup_margin_size = default_margin_size * EDSCALE * 3; style_popup->set_default_margin(SIDE_LEFT, popup_margin_size); style_popup->set_default_margin(SIDE_TOP, popup_margin_size); style_popup->set_default_margin(SIDE_RIGHT, popup_margin_size); style_popup->set_default_margin(SIDE_BOTTOM, popup_margin_size); style_popup->set_border_color(contrast_color_1); - style_popup->set_border_width_all(MAX(EDSCALE, border_width)); const Color shadow_color = Color(0, 0, 0, dark_theme ? 0.3 : 0.1); style_popup->set_shadow_color(shadow_color); style_popup->set_shadow_size(4 * EDSCALE); Ref<StyleBoxLine> style_popup_separator(memnew(StyleBoxLine)); style_popup_separator->set_color(separator_color); - style_popup_separator->set_grow_begin(popup_margin_size - MAX(EDSCALE, border_width)); - style_popup_separator->set_grow_end(popup_margin_size - MAX(EDSCALE, border_width)); - style_popup_separator->set_thickness(MAX(EDSCALE, border_width)); + style_popup_separator->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); + style_popup_separator->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); + style_popup_separator->set_thickness(MAX(Math::round(EDSCALE), border_width)); Ref<StyleBoxLine> style_popup_labeled_separator_left(memnew(StyleBoxLine)); - style_popup_labeled_separator_left->set_grow_begin(popup_margin_size - MAX(EDSCALE, border_width)); + style_popup_labeled_separator_left->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); style_popup_labeled_separator_left->set_color(separator_color); - style_popup_labeled_separator_left->set_thickness(MAX(EDSCALE, border_width)); + style_popup_labeled_separator_left->set_thickness(MAX(Math::round(EDSCALE), border_width)); Ref<StyleBoxLine> style_popup_labeled_separator_right(memnew(StyleBoxLine)); - style_popup_labeled_separator_right->set_grow_end(popup_margin_size - MAX(EDSCALE, border_width)); + style_popup_labeled_separator_right->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); style_popup_labeled_separator_right->set_color(separator_color); - style_popup_labeled_separator_right->set_thickness(MAX(EDSCALE, border_width)); + style_popup_labeled_separator_right->set_thickness(MAX(Math::round(EDSCALE), border_width)); Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size); // Tabs - const int tab_default_margin_side = 10 * EDSCALE + extra_spacing * EDSCALE; - const int tab_default_margin_vertical = 5 * EDSCALE + extra_spacing * EDSCALE; - Ref<StyleBoxFlat> style_tab_selected = style_widget->duplicate(); - style_tab_selected->set_border_width_all(border_width); - style_tab_selected->set_border_width(SIDE_BOTTOM, 0); - style_tab_selected->set_border_color(dark_color_3); - style_tab_selected->set_expand_margin_size(SIDE_BOTTOM, border_width); - style_tab_selected->set_default_margin(SIDE_LEFT, tab_default_margin_side); - style_tab_selected->set_default_margin(SIDE_RIGHT, tab_default_margin_side); - style_tab_selected->set_default_margin(SIDE_BOTTOM, tab_default_margin_vertical); - style_tab_selected->set_default_margin(SIDE_TOP, tab_default_margin_vertical); - style_tab_selected->set_bg_color(tab_color); + // Add a highlight line at the top of the selected tab. + style_tab_selected->set_border_width_all(0); + style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE)); + // Make the highlight line prominent, but not too prominent as to not be distracting. + style_tab_selected->set_border_color(dark_color_2.lerp(accent_color, 0.75)); + // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel. + // This also makes the top highlight look better. + style_tab_selected->set_corner_radius_all(0); + + // Prevent visible artifacts and cover the top-left rounded corner of the panel below the tab if selected + // We can't prevent them with both rounded corners and non-zero border width, though + style_tab_selected->set_expand_margin_size(SIDE_BOTTOM, corner_width > 0 ? corner_width : border_width); + + style_tab_selected->set_default_margin(SIDE_LEFT, widget_default_margin.x + 2 * EDSCALE); + style_tab_selected->set_default_margin(SIDE_RIGHT, widget_default_margin.x + 2 * EDSCALE); + style_tab_selected->set_default_margin(SIDE_BOTTOM, widget_default_margin.y); + style_tab_selected->set_default_margin(SIDE_TOP, widget_default_margin.y); + style_tab_selected->set_bg_color(base_color); Ref<StyleBoxFlat> style_tab_unselected = style_tab_selected->duplicate(); style_tab_unselected->set_bg_color(dark_color_1); + style_tab_unselected->set_expand_margin_size(SIDE_BOTTOM, 0); + // Add some spacing between unselected tabs to make them easier to distinguish from each other style_tab_unselected->set_border_color(dark_color_2); + style_tab_unselected->set_border_width(SIDE_LEFT, Math::round(2 * EDSCALE)); + style_tab_unselected->set_border_width(SIDE_RIGHT, Math::round(2 * EDSCALE)); Ref<StyleBoxFlat> style_tab_disabled = style_tab_selected->duplicate(); style_tab_disabled->set_bg_color(disabled_bg_color); - style_tab_disabled->set_border_color(disabled_color); + style_tab_disabled->set_expand_margin_size(SIDE_BOTTOM, 0); + style_tab_disabled->set_border_color(disabled_bg_color); // Editor background Color background_color_opaque = background_color; @@ -566,10 +575,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(background_color_opaque, default_margin_size, default_margin_size, default_margin_size, default_margin_size)); // Focus - Ref<StyleBoxFlat> style_focus = style_default->duplicate(); - style_focus->set_draw_center(false); - style_focus->set_border_color(contrast_color_2); - theme->set_stylebox("Focus", "EditorStyles", style_focus); + theme->set_stylebox("Focus", "EditorStyles", style_widget_focus); // Menu Ref<StyleBoxFlat> style_menu = style_widget->duplicate(); @@ -585,33 +591,25 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Play button group theme->set_stylebox("PlayButtonPanel", "EditorStyles", style_empty); - //MenuButton - Ref<StyleBoxFlat> style_menu_hover_border = style_widget->duplicate(); - style_menu_hover_border->set_draw_center(false); - style_menu_hover_border->set_border_width_all(0); - style_menu_hover_border->set_border_width(SIDE_BOTTOM, border_width); - style_menu_hover_border->set_border_color(accent_color); - - Ref<StyleBoxFlat> style_menu_hover_bg = style_widget->duplicate(); - style_menu_hover_bg->set_border_width_all(0); - style_menu_hover_bg->set_bg_color(dark_color_1); - theme->set_stylebox("normal", "MenuButton", style_menu); - theme->set_stylebox("hover", "MenuButton", style_menu); + theme->set_stylebox("hover", "MenuButton", style_widget_hover); theme->set_stylebox("pressed", "MenuButton", style_menu); theme->set_stylebox("focus", "MenuButton", style_menu); theme->set_stylebox("disabled", "MenuButton", style_menu); theme->set_stylebox("normal", "PopupMenu", style_menu); - theme->set_stylebox("hover", "PopupMenu", style_menu_hover_bg); - theme->set_stylebox("pressed", "PopupMenu", style_menu); + + Ref<StyleBoxFlat> style_menu_hover = style_widget_hover->duplicate(); + // Don't use rounded corners for hover highlights since the StyleBox touches the PopupMenu's edges. + style_menu_hover->set_corner_radius_all(0); + theme->set_stylebox("hover", "PopupMenu", style_menu_hover); theme->set_stylebox("focus", "PopupMenu", style_menu); theme->set_stylebox("disabled", "PopupMenu", style_menu); theme->set_color("font_color", "MenuButton", font_color); theme->set_color("font_hover_color", "MenuButton", font_hover_color); - theme->set_stylebox("MenuHover", "EditorStyles", style_menu_hover_border); + theme->set_stylebox("MenuHover", "EditorStyles", style_widget_hover); // Buttons theme->set_stylebox("normal", "Button", style_widget); @@ -646,7 +644,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_disabled_color", "OptionButton", font_disabled_color); theme->set_color("icon_hover_color", "OptionButton", icon_hover_color); theme->set_icon("arrow", "OptionButton", theme->get_icon("GuiOptionArrow", "EditorIcons")); - theme->set_constant("arrow_margin", "OptionButton", default_margin_size * EDSCALE); + theme->set_constant("arrow_margin", "OptionButton", widget_default_margin.x - 2 * EDSCALE); theme->set_constant("modulate_arrow", "OptionButton", true); theme->set_constant("hseparation", "OptionButton", 4 * EDSCALE); @@ -672,7 +670,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_disabled_color", "CheckButton", font_disabled_color); theme->set_color("icon_hover_color", "CheckButton", icon_hover_color); - theme->set_constant("hseparation", "CheckButton", 4 * EDSCALE); + theme->set_constant("hseparation", "CheckButton", 8 * EDSCALE); theme->set_constant("check_vadjust", "CheckButton", 0 * EDSCALE); // Checkbox @@ -697,7 +695,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_disabled_color", "CheckBox", font_disabled_color); theme->set_color("icon_hover_color", "CheckBox", icon_hover_color); - theme->set_constant("hseparation", "CheckBox", 4 * EDSCALE); + theme->set_constant("hseparation", "CheckBox", 8 * EDSCALE); theme->set_constant("check_vadjust", "CheckBox", 0 * EDSCALE); // PopupDialog @@ -794,12 +792,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Tree & ItemList background Ref<StyleBoxFlat> style_tree_bg = style_default->duplicate(); - style_tree_bg->set_bg_color(dark_color_1); + // Make Trees easier to distinguish from other controls by using a darker background color. + style_tree_bg->set_bg_color(dark_color_1.lerp(dark_color_2, 0.5)); style_tree_bg->set_border_color(dark_color_3); theme->set_stylebox("bg", "Tree", style_tree_bg); - const Color guide_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.05); - Color relationship_line_color = Color(mono_color.r, mono_color.g, mono_color.b, relationship_line_opacity); + const Color guide_color = mono_color * Color(1, 1, 1, 0.05); + Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity); // Tree theme->set_icon("checked", "Tree", theme->get_icon("GuiChecked", "EditorIcons")); theme->set_icon("unchecked", "Tree", theme->get_icon("GuiUnchecked", "EditorIcons")); @@ -808,7 +807,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("arrow_collapsed_mirrored", "Tree", theme->get_icon("GuiTreeArrowLeft", "EditorIcons")); theme->set_icon("updown", "Tree", theme->get_icon("GuiTreeUpdown", "EditorIcons")); theme->set_icon("select_arrow", "Tree", theme->get_icon("GuiDropdown", "EditorIcons")); - theme->set_stylebox("bg_focus", "Tree", style_focus); + theme->set_stylebox("bg_focus", "Tree", style_widget_focus); theme->set_stylebox("custom_button", "Tree", make_empty_stylebox()); theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox()); theme->set_stylebox("custom_button_hover", "Tree", style_widget); @@ -819,8 +818,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("guide_color", "Tree", guide_color); theme->set_color("relationship_line_color", "Tree", relationship_line_color); theme->set_color("drop_position_color", "Tree", accent_color); - theme->set_constant("vseparation", "Tree", (extra_spacing + default_margin_size) * EDSCALE); - theme->set_constant("hseparation", "Tree", (extra_spacing + default_margin_size) * EDSCALE); + theme->set_constant("vseparation", "Tree", widget_default_margin.y - EDSCALE); + theme->set_constant("hseparation", "Tree", 6 * EDSCALE); + theme->set_constant("guide_width", "Tree", border_width); theme->set_constant("item_margin", "Tree", 3 * default_margin_size * EDSCALE); theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE); theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01); @@ -829,7 +829,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("scroll_speed", "Tree", 12); Ref<StyleBoxFlat> style_tree_btn = style_default->duplicate(); - style_tree_btn->set_bg_color(contrast_color_1); + style_tree_btn->set_bg_color(highlight_color); style_tree_btn->set_border_width_all(0); theme->set_stylebox("button_pressed", "Tree", style_tree_btn); @@ -882,14 +882,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor); theme->set_stylebox("selected_focus", "ItemList", style_tree_focus); theme->set_stylebox("selected", "ItemList", style_tree_selected); - theme->set_stylebox("bg_focus", "ItemList", style_focus); + theme->set_stylebox("bg_focus", "ItemList", style_widget_focus); theme->set_stylebox("bg", "ItemList", style_itemlist_bg); theme->set_color("font_color", "ItemList", font_color); theme->set_color("font_selected_color", "ItemList", mono_color); theme->set_color("guide_color", "ItemList", guide_color); - theme->set_constant("vseparation", "ItemList", 3 * EDSCALE); - theme->set_constant("hseparation", "ItemList", 3 * EDSCALE); - theme->set_constant("icon_margin", "ItemList", default_margin_size * EDSCALE); + theme->set_constant("vseparation", "ItemList", widget_default_margin.y - EDSCALE); + theme->set_constant("hseparation", "ItemList", 6 * EDSCALE); + theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE); theme->set_constant("line_separation", "ItemList", 3 * EDSCALE); // Tabs & TabContainer @@ -940,8 +940,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp); // Separators - theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, border_width)); - theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, border_width, 0, 0, true)); + theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width))); + theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width), 0, 0, true)); // Debugger @@ -956,9 +956,23 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("BottomPanelDebuggerOverride", "EditorStyles", style_panel_invisible_top); // LineEdit - theme->set_stylebox("normal", "LineEdit", style_widget); + + Ref<StyleBoxFlat> style_line_edit = style_widget->duplicate(); + // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors + // such as the Project Settings. + style_line_edit->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE)); + style_line_edit->set_border_color(dark_color_2); + // Don't round the bottom corner to make the line look sharper. + style_tab_selected->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + style_tab_selected->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); + + Ref<StyleBoxFlat> style_line_edit_disabled = style_line_edit->duplicate(); + style_line_edit_disabled->set_border_color(disabled_color); + style_line_edit_disabled->set_bg_color(disabled_bg_color); + + theme->set_stylebox("normal", "LineEdit", style_line_edit); theme->set_stylebox("focus", "LineEdit", style_widget_focus); - theme->set_stylebox("read_only", "LineEdit", style_widget_disabled); + theme->set_stylebox("read_only", "LineEdit", style_line_edit_disabled); theme->set_icon("clear", "LineEdit", theme->get_icon("GuiClose", "EditorIcons")); theme->set_color("read_only", "LineEdit", font_disabled_color); theme->set_color("font_color", "LineEdit", font_color); @@ -969,9 +983,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("clear_button_color_pressed", "LineEdit", accent_color); // TextEdit - theme->set_stylebox("normal", "TextEdit", style_widget); - theme->set_stylebox("focus", "TextEdit", style_widget_hover); - theme->set_stylebox("read_only", "TextEdit", style_widget_disabled); + theme->set_stylebox("normal", "TextEdit", style_line_edit); + theme->set_stylebox("focus", "TextEdit", style_widget_focus); + theme->set_stylebox("read_only", "TextEdit", style_line_edit_disabled); theme->set_constant("side_margin", "TabContainer", 0); theme->set_icon("tab", "TextEdit", theme->get_icon("GuiTab", "EditorIcons")); theme->set_icon("space", "TextEdit", theme->get_icon("GuiSpace", "EditorIcons")); @@ -1014,14 +1028,22 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("hseparation", "GridContainer", default_margin_size * EDSCALE); theme->set_constant("vseparation", "GridContainer", default_margin_size * EDSCALE); - // WindowDialog + // Window + + // Prevent corner artifacts between window title and body. + Ref<StyleBoxFlat> style_window_title = style_default->duplicate(); + style_window_title->set_corner_radius(CORNER_TOP_LEFT, 0); + style_window_title->set_corner_radius(CORNER_TOP_RIGHT, 0); + // Prevent visible line between window title and body. + style_window_title->set_expand_margin_size(SIDE_BOTTOM, 2 * EDSCALE); + theme->set_stylebox("panel", "Window", style_window_title); + Ref<StyleBoxFlat> style_window = style_popup->duplicate(); - style_window->set_border_color(tab_color); + style_window->set_border_color(base_color); style_window->set_border_width(SIDE_TOP, 24 * EDSCALE); style_window->set_expand_margin_size(SIDE_TOP, 24 * EDSCALE); - - theme->set_stylebox("panel", "Window", style_default); theme->set_stylebox("panel_window", "Window", style_window); + theme->set_color("title_color", "Window", font_color); theme->set_icon("close", "Window", theme->get_icon("GuiClose", "EditorIcons")); theme->set_icon("close_highlight", "Window", theme->get_icon("GuiClose", "EditorIcons")); @@ -1032,10 +1054,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_font("title_font", "Window", theme->get_font("title", "EditorFonts")); theme->set_font_size("title_font_size", "Window", theme->get_font_size("title_size", "EditorFonts")); - // complex window, for now only Editor settings and Project settings + // Complex window (currently only Editor Settings and Project Settings) Ref<StyleBoxFlat> style_complex_window = style_window->duplicate(); style_complex_window->set_bg_color(dark_color_2); - style_complex_window->set_border_color(highlight_tabs ? tab_color : dark_color_2); + style_complex_window->set_border_color(dark_color_2); theme->set_stylebox("panel", "EditorSettingsDialog", style_complex_window); theme->set_stylebox("panel", "ProjectSettingsEditor", style_complex_window); theme->set_stylebox("panel", "EditorAbout", style_complex_window); @@ -1069,18 +1091,18 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // HSlider theme->set_icon("grabber_highlight", "HSlider", theme->get_icon("GuiSliderGrabberHl", "EditorIcons")); theme->set_icon("grabber", "HSlider", theme->get_icon("GuiSliderGrabber", "EditorIcons")); - theme->set_stylebox("slider", "HSlider", make_flat_stylebox(dark_color_3, 0, default_margin_size / 2, 0, default_margin_size / 2)); - theme->set_stylebox("grabber_area", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2)); + theme->set_stylebox("slider", "HSlider", make_flat_stylebox(dark_color_3, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width)); + theme->set_stylebox("grabber_area", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width)); theme->set_stylebox("grabber_area_highlight", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2)); // VSlider theme->set_icon("grabber", "VSlider", theme->get_icon("GuiSliderGrabber", "EditorIcons")); theme->set_icon("grabber_highlight", "VSlider", theme->get_icon("GuiSliderGrabberHl", "EditorIcons")); - theme->set_stylebox("slider", "VSlider", make_flat_stylebox(dark_color_3, default_margin_size / 2, 0, default_margin_size / 2, 0)); - theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0)); + theme->set_stylebox("slider", "VSlider", make_flat_stylebox(dark_color_3, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width)); + theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width)); theme->set_stylebox("grabber_area_highlight", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0)); - //RichTextLabel + // RichTextLabel theme->set_color("default_color", "RichTextLabel", font_color); theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0)); theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE); @@ -1092,7 +1114,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("headline_color", "EditorHelp", mono_color); // Panel - theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4)); + theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4, corner_width)); theme->set_stylebox("panel_fg", "Panel", style_default); // Label @@ -1113,16 +1135,15 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // TooltipPanel Ref<StyleBoxFlat> style_tooltip = style_popup->duplicate(); - float v = MAX(border_size * EDSCALE, 1.0); - style_tooltip->set_default_margin(SIDE_LEFT, v); - style_tooltip->set_default_margin(SIDE_TOP, v); - style_tooltip->set_default_margin(SIDE_RIGHT, v); - style_tooltip->set_default_margin(SIDE_BOTTOM, v); - style_tooltip->set_bg_color(Color(mono_color.r, mono_color.g, mono_color.b, 0.9)); - style_tooltip->set_border_width_all(border_width); - style_tooltip->set_border_color(mono_color); - theme->set_color("font_color", "TooltipLabel", font_color.inverted()); - theme->set_color("font_shadow_color", "TooltipLabel", mono_color.inverted() * Color(1, 1, 1, 0.1)); + style_tooltip->set_shadow_size(0); + style_tooltip->set_default_margin(SIDE_LEFT, default_margin_size * EDSCALE); + style_tooltip->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE * 0.5); + style_tooltip->set_default_margin(SIDE_RIGHT, default_margin_size * EDSCALE); + style_tooltip->set_default_margin(SIDE_BOTTOM, default_margin_size * EDSCALE * 0.5); + style_tooltip->set_bg_color(mono_color.inverted() * Color(1, 1, 1, 0.8)); + style_tooltip->set_border_width_all(0); + theme->set_color("font_color", "TooltipLabel", font_hover_color); + theme->set_color("font_color_shadow", "TooltipLabel", Color(0, 0, 0, 0)); theme->set_stylebox("panel", "TooltipPanel", style_tooltip); // PopupPanel @@ -1189,23 +1210,20 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color); // GraphNode - const float mv = dark_theme ? 0.0 : 1.0; - const float mv2 = 1.0 - mv; const int gn_margin_side = 28; - Ref<StyleBoxFlat> graphsb = make_flat_stylebox(Color(mv, mv, mv, 0.7), gn_margin_side, 24, gn_margin_side, 5); + + Ref<StyleBoxFlat> graphsb = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.7), gn_margin_side, 24, gn_margin_side, 5, corner_width); graphsb->set_border_width_all(border_width); - graphsb->set_border_color(Color(mv2, mv2, mv2, 0.9)); - Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(Color(mv, mv, mv, 0.9), gn_margin_side, 24, gn_margin_side, 5); - graphsbselected->set_border_width_all(border_width); + graphsb->set_border_color(dark_color_3); + Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.9), gn_margin_side, 24, gn_margin_side, 5, corner_width); + graphsbselected->set_border_width_all(2 * EDSCALE + border_width); graphsbselected->set_border_color(Color(accent_color.r, accent_color.g, accent_color.b, 0.9)); - graphsbselected->set_shadow_size(8 * EDSCALE); - graphsbselected->set_shadow_color(shadow_color); - Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(Color(mv, mv, mv, 0.3), gn_margin_side, 24, gn_margin_side, 5); + Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.3), gn_margin_side, 24, gn_margin_side, 5, corner_width); graphsbcomment->set_border_width_all(border_width); - graphsbcomment->set_border_color(Color(mv2, mv2, mv2, 0.9)); - Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(Color(mv, mv, mv, 0.4), gn_margin_side, 24, gn_margin_side, 5); + graphsbcomment->set_border_color(dark_color_3); + Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.4), gn_margin_side, 24, gn_margin_side, 5, corner_width); graphsbcommentselected->set_border_width_all(border_width); - graphsbcommentselected->set_border_color(Color(mv2, mv2, mv2, 0.9)); + graphsbcommentselected->set_border_color(dark_color_3); Ref<StyleBoxFlat> graphsbbreakpoint = graphsbselected->duplicate(); graphsbbreakpoint->set_draw_center(false); graphsbbreakpoint->set_border_color(warning_color); @@ -1214,21 +1232,19 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { graphsbposition->set_draw_center(false); graphsbposition->set_border_color(error_color); graphsbposition->set_shadow_color(error_color * Color(1.0, 1.0, 1.0, 0.2)); - Ref<StyleBoxFlat> smgraphsb = make_flat_stylebox(Color(mv, mv, mv, 0.7), gn_margin_side, 24, gn_margin_side, 5); + Ref<StyleBoxFlat> smgraphsb = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.7), gn_margin_side, 24, gn_margin_side, 5, corner_width); smgraphsb->set_border_width_all(border_width); - smgraphsb->set_border_color(Color(mv2, mv2, mv2, 0.9)); - Ref<StyleBoxFlat> smgraphsbselected = make_flat_stylebox(Color(mv, mv, mv, 0.9), gn_margin_side, 24, gn_margin_side, 5); - smgraphsbselected->set_border_width_all(border_width); + smgraphsb->set_border_color(dark_color_3); + Ref<StyleBoxFlat> smgraphsbselected = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.9), gn_margin_side, 24, gn_margin_side, 5, corner_width); + smgraphsbselected->set_border_width_all(2 * EDSCALE + border_width); smgraphsbselected->set_border_color(Color(accent_color.r, accent_color.g, accent_color.b, 0.9)); smgraphsbselected->set_shadow_size(8 * EDSCALE); smgraphsbselected->set_shadow_color(shadow_color); - if (use_gn_headers) { - graphsb->set_border_width(SIDE_TOP, 24 * EDSCALE); - graphsbselected->set_border_width(SIDE_TOP, 24 * EDSCALE); - graphsbcomment->set_border_width(SIDE_TOP, 24 * EDSCALE); - graphsbcommentselected->set_border_width(SIDE_TOP, 24 * EDSCALE); - } + graphsb->set_border_width(SIDE_TOP, 24 * EDSCALE); + graphsbselected->set_border_width(SIDE_TOP, 24 * EDSCALE); + graphsbcomment->set_border_width(SIDE_TOP, 24 * EDSCALE); + graphsbcommentselected->set_border_width(SIDE_TOP, 24 * EDSCALE); theme->set_stylebox("frame", "GraphNode", graphsb); theme->set_stylebox("selectedframe", "GraphNode", graphsbselected); @@ -1239,7 +1255,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("state_machine_frame", "GraphNode", smgraphsb); theme->set_stylebox("state_machine_selectedframe", "GraphNode", smgraphsbselected); - Color default_node_color = Color(mv2, mv2, mv2); + Color default_node_color = dark_color_1.inverted(); theme->set_color("title_color", "GraphNode", default_node_color); default_node_color.a = 0.7; theme->set_color("close_color", "GraphNode", default_node_color); @@ -1257,7 +1273,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("port", "GraphNode", theme->get_icon("GuiGraphNodePort", "EditorIcons")); // GridContainer - theme->set_constant("vseparation", "GridContainer", (extra_spacing + default_margin_size) * EDSCALE); + theme->set_constant("vseparation", "GridContainer", Math::round(widget_default_margin.y - 2 * EDSCALE)); // FileDialog theme->set_icon("folder", "FileDialog", theme->get_icon("Folder", "EditorIcons")); diff --git a/editor/fileserver/editor_file_server.h b/editor/fileserver/editor_file_server.h index 8ffd4f9692..d0405e0bb7 100644 --- a/editor/fileserver/editor_file_server.h +++ b/editor/fileserver/editor_file_server.h @@ -54,7 +54,7 @@ class EditorFileServer : public Object { bool quit = false; }; - Ref<TCP_Server> server; + Ref<TCPServer> server; Set<Thread *> to_wait; static void _close_client(ClientData *cd); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 09424647fe..6cd45fdf97 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2806,7 +2806,6 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { toolbar_hbc->add_child(current_path); button_reload = memnew(Button); - button_reload->set_flat(true); button_reload->connect("pressed", callable_mp(this, &FileSystemDock::_rescan)); button_reload->set_focus_mode(FOCUS_NONE); button_reload->set_tooltip(TTR("Re-Scan Filesystem")); @@ -2814,7 +2813,6 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { toolbar_hbc->add_child(button_reload); button_toggle_display_mode = memnew(Button); - button_toggle_display_mode->set_flat(true); button_toggle_display_mode->set_toggle_mode(true); button_toggle_display_mode->connect("toggled", callable_mp(this, &FileSystemDock::_toggle_split_mode)); button_toggle_display_mode->set_focus_mode(FOCUS_NONE); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index fbcd76a95f..6265dfc2e4 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -535,7 +535,6 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { } else { backward_button->set_icon(get_theme_icon("Back", "EditorIcons")); } - backward_button->set_flat(true); backward_button->set_tooltip(TTR("Go to the previous edited object in history.")); backward_button->set_disabled(true); backward_button->connect("pressed", callable_mp(this, &InspectorDock::_edit_back)); @@ -548,7 +547,6 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { } else { forward_button->set_icon(get_theme_icon("Forward", "EditorIcons")); } - forward_button->set_flat(true); forward_button->set_tooltip(TTR("Go to the next edited object in history.")); forward_button->set_disabled(true); forward_button->connect("pressed", callable_mp(this, &InspectorDock::_edit_forward)); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 48fb507bb1..78c30df04b 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -231,18 +231,16 @@ void AnimationNodeBlendTreeEditor::_update_graph() { mb->get_popup()->connect("index_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_anim_selected), varray(options, E->get()), CONNECT_DEFERRED); } - if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { - Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode"); - Color c = sb->get_border_color(); - Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0); - mono_color.a = 0.85; - c = mono_color; - - node->add_theme_color_override("title_color", c); - c.a = 0.7; - node->add_theme_color_override("close_color", c); - node->add_theme_color_override("resizer_color", c); - } + Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode"); + Color c = sb->get_border_color(); + Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0); + mono_color.a = 0.85; + c = mono_color; + + node->add_theme_color_override("title_color", c); + c.a = 0.7; + node->add_theme_color_override("close_color", c); + node->add_theme_color_override("resizer_color", c); } List<AnimationNodeBlendTree::NodeConnection> connections; diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index fd47d9964e..a0d9afee74 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -240,7 +240,6 @@ void EditorAssetLibraryItemDescription::add_preview(int p_id, bool p_video, cons preview.video_link = p_url; preview.is_video = p_video; preview.button = memnew(Button); - preview.button->set_flat(true); preview.button->set_icon(previews->get_theme_icon("ThumbnailWait", "EditorIcons")); preview.button->set_toggle_mode(true); preview.button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDescription::_preview_click), varray(p_id)); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 261621e10a..852c615dc8 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -5853,6 +5853,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { updating_scroll = false; + // Add some margin to the left for better aesthetics. + // This prevents the first button's hover/pressed effect from "touching" the panel's border, + // which looks ugly. + Control *margin_left = memnew(Control); + hb->add_child(margin_left); + margin_left->set_custom_minimum_size(Size2(2, 0) * EDSCALE); + select_button = memnew(Button); select_button->set_flat(true); hb->add_child(select_button); @@ -6089,7 +6096,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { key_loc_button = memnew(Button); key_loc_button->set_toggle_mode(true); - key_loc_button->set_flat(true); key_loc_button->set_pressed(true); key_loc_button->set_focus_mode(FOCUS_NONE); key_loc_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_POS)); @@ -6098,7 +6104,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { key_rot_button = memnew(Button); key_rot_button->set_toggle_mode(true); - key_rot_button->set_flat(true); key_rot_button->set_pressed(true); key_rot_button->set_focus_mode(FOCUS_NONE); key_rot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_ROT)); @@ -6107,14 +6112,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { key_scale_button = memnew(Button); key_scale_button->set_toggle_mode(true); - key_scale_button->set_flat(true); key_scale_button->set_focus_mode(FOCUS_NONE); key_scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_SCALE)); key_scale_button->set_tooltip(TTR("Scale mask for inserting keys.")); animation_hb->add_child(key_scale_button); key_insert_button = memnew(Button); - key_insert_button->set_flat(true); key_insert_button->set_focus_mode(FOCUS_NONE); key_insert_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_KEY)); key_insert_button->set_tooltip(TTR("Insert keys (based on mask).")); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 023d91be30..81f1852fba 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -6692,6 +6692,13 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { button_binds.resize(1); String sct; + // Add some margin to the left for better aesthetics. + // This prevents the first button's hover/pressed effect from "touching" the panel's border, + // which looks ugly. + Control *margin_left = memnew(Control); + hbc_menu->add_child(margin_left); + margin_left->set_custom_minimum_size(Size2(2, 0) * EDSCALE); + tool_button[TOOL_MODE_SELECT] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_SELECT]); tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true); diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index 50f4d8493f..1e6237ced1 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -205,7 +205,6 @@ void EditorPropertyRootMotion::update_property() { assign->set_flat(false); return; } - assign->set_flat(true); Node *base_node = nullptr; if (base_hint != NodePath()) { @@ -247,14 +246,12 @@ EditorPropertyRootMotion::EditorPropertyRootMotion() { HBoxContainer *hbc = memnew(HBoxContainer); add_child(hbc); assign = memnew(Button); - assign->set_flat(true); assign->set_h_size_flags(SIZE_EXPAND_FILL); assign->set_clip_text(true); assign->connect("pressed", callable_mp(this, &EditorPropertyRootMotion::_node_assign)); hbc->add_child(assign); clear = memnew(Button); - clear->set_flat(true); clear->connect("pressed", callable_mp(this, &EditorPropertyRootMotion::_node_clear)); hbc->add_child(clear); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 58e6717a3d..bc33d03d8b 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -698,7 +698,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { // Do not try to save internal scripts, but prompt to save in-memory // scripts which are not saved to disk yet (have empty path). if (script->get_path().find("local://") == -1 && script->get_path().find("::") == -1) { - _menu_option(FILE_SAVE); + _save_current_script(); } } if (script.is_valid()) { @@ -1096,6 +1096,59 @@ bool ScriptEditor::is_scripts_panel_toggled() { return list_split->is_visible(); } +void ScriptEditor::_save_current_script() { + ScriptEditorBase *current = _get_current_editor(); + + if (_test_script_times_on_disk()) { + return; + } + + if (trim_trailing_whitespace_on_save) { + current->trim_trailing_whitespace(); + } + + current->insert_final_newline(); + + if (convert_indent_on_save) { + if (use_space_indentation) { + current->convert_indent_to_spaces(); + } else { + current->convert_indent_to_tabs(); + } + } + + RES resource = current->get_edited_resource(); + Ref<TextFile> text_file = resource; + Ref<Script> script = resource; + + if (text_file != nullptr) { + current->apply_code(); + _save_text_file(text_file, text_file->get_path()); + return; + } + + if (script != nullptr) { + const Vector<DocData::ClassDoc> &documentations = script->get_documentation(); + for (int j = 0; j < documentations.size(); j++) { + const DocData::ClassDoc &doc = documentations.get(j); + if (EditorHelp::get_doc_data()->has_doc(doc.name)) { + EditorHelp::get_doc_data()->remove_doc(doc.name); + } + } + } + + editor->save_resource(resource); + + if (script != nullptr) { + const Vector<DocData::ClassDoc> &documentations = script->get_documentation(); + for (int j = 0; j < documentations.size(); j++) { + const DocData::ClassDoc &doc = documentations.get(j); + EditorHelp::get_doc_data()->add_doc(doc); + update_doc(doc.name); + } + } +} + void ScriptEditor::_menu_option(int p_option) { ScriptEditorBase *current = _get_current_editor(); switch (p_option) { @@ -1224,55 +1277,7 @@ void ScriptEditor::_menu_option(int p_option) { if (current) { switch (p_option) { case FILE_SAVE: { - if (_test_script_times_on_disk()) { - return; - } - - if (trim_trailing_whitespace_on_save) { - current->trim_trailing_whitespace(); - } - - current->insert_final_newline(); - - if (convert_indent_on_save) { - if (use_space_indentation) { - current->convert_indent_to_spaces(); - } else { - current->convert_indent_to_tabs(); - } - } - - RES resource = current->get_edited_resource(); - Ref<TextFile> text_file = resource; - Ref<Script> script = resource; - - if (text_file != nullptr) { - current->apply_code(); - _save_text_file(text_file, text_file->get_path()); - break; - } - - if (script != nullptr) { - const Vector<DocData::ClassDoc> &documentations = script->get_documentation(); - for (int j = 0; j < documentations.size(); j++) { - const DocData::ClassDoc &doc = documentations.get(j); - if (EditorHelp::get_doc_data()->has_doc(doc.name)) { - EditorHelp::get_doc_data()->remove_doc(doc.name); - } - } - } - - editor->save_resource(resource); - - if (script != nullptr) { - const Vector<DocData::ClassDoc> &documentations = script->get_documentation(); - for (int j = 0; j < documentations.size(); j++) { - const DocData::ClassDoc &doc = documentations.get(j); - EditorHelp::get_doc_data()->add_doc(doc); - update_doc(doc.name); - } - } - + _save_current_script(); } break; case FILE_SAVE_AS: { if (trim_trailing_whitespace_on_save) { @@ -1827,7 +1832,6 @@ void ScriptEditor::_update_help_overview() { void ScriptEditor::_update_script_colors() { bool script_temperature_enabled = EditorSettings::get_singleton()->get("text_editor/script_list/script_temperature_enabled"); - bool highlight_current = EditorSettings::get_singleton()->get("text_editor/script_list/highlight_current_script"); int hist_size = EditorSettings::get_singleton()->get("text_editor/script_list/script_temperature_history_size"); Color hot_color = get_theme_color("accent_color", "Editor"); @@ -1842,11 +1846,7 @@ void ScriptEditor::_update_script_colors() { script_list->set_item_custom_bg_color(i, Color(0, 0, 0, 0)); - bool current = tab_container->get_current_tab() == c; - if (current && highlight_current) { - script_list->set_item_custom_bg_color(i, EditorSettings::get_singleton()->get("text_editor/script_list/current_script_background_color")); - - } else if (script_temperature_enabled) { + if (script_temperature_enabled) { if (!n->has_meta("__editor_pass")) { continue; } @@ -2439,6 +2439,9 @@ void ScriptEditor::_add_callback(Object *p_obj, const String &p_function, const script_list->select(script_list->find_metadata(i)); + // Save the current script so the changes can be picked up by an external editor. + _save_current_script(); + break; } } @@ -3672,9 +3675,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) { EDITOR_DEF("text_editor/external/use_external_editor", false); EDITOR_DEF("text_editor/external/exec_path", ""); EDITOR_DEF("text_editor/script_list/script_temperature_enabled", true); - EDITOR_DEF("text_editor/script_list/highlight_current_script", true); EDITOR_DEF("text_editor/script_list/script_temperature_history_size", 15); - EDITOR_DEF("text_editor/script_list/current_script_background_color", Color(1, 1, 1, 0.3)); EDITOR_DEF("text_editor/script_list/group_help_pages", true); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/script_list/sort_scripts_by", PROPERTY_HINT_ENUM, "Name,Path,None")); EDITOR_DEF("text_editor/script_list/sort_scripts_by", 0); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index b2172e7f10..c70fd2e555 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -312,6 +312,7 @@ class ScriptEditor : public PanelContainer { String _get_debug_tooltip(const String &p_text, Node *_se); + void _save_current_script(); void _resave_scripts(const String &p_str); void _reload_scripts(); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index acc77bd098..7d5e72ff8e 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -1175,26 +1175,15 @@ void VisualShaderEditor::_draw_color_over_button(Object *obj, Color p_color) { } void VisualShaderEditor::_update_created_node(GraphNode *node) { - if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { - Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode"); - Color c = sb->get_border_color(); - Color ic; - Color mono_color; - if (((c.r + c.g + c.b) / 3) < 0.7) { - mono_color = Color(1.0, 1.0, 1.0); - ic = Color(0.0, 0.0, 0.0, 0.7); - } else { - mono_color = Color(0.0, 0.0, 0.0); - ic = Color(1.0, 1.0, 1.0, 0.7); - } - mono_color.a = 0.85; - c = mono_color; - - node->add_theme_color_override("title_color", c); - c.a = 0.7; - node->add_theme_color_override("close_color", c); - node->add_theme_color_override("resizer_color", ic); - } + const Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode"); + Color c = sb->get_border_color(); + const Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0, 0.85) : Color(0.0, 0.0, 0.0, 0.85); + c = mono_color; + + node->add_theme_color_override("title_color", c); + c.a = 0.7; + node->add_theme_color_override("close_color", c); + node->add_theme_color_override("resizer_color", c); } void VisualShaderEditor::_update_uniforms(bool p_update_refs) { diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 1a010b9168..8b0d9ae0fc 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -1823,7 +1823,6 @@ CustomPropertyEditor::CustomPropertyEditor() { Vector<Variant> binds; binds.push_back(i); action_buttons[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed), binds); - action_buttons[i]->set_flat(true); } color_picker = nullptr; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 49c231de69..2a2960ed6f 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2587,14 +2587,16 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { } } - if (profile_allow_script_editing) { + if (profile_allow_editing) { menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/cut_node"), TOOL_CUT); menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/copy_node"), TOOL_COPY); if (selection.size() == 1 && !node_clipboard.is_empty()) { menu->add_shortcut(ED_GET_SHORTCUT("scene_tree/paste_node"), TOOL_PASTE); } menu->add_separator(); + } + if (profile_allow_script_editing) { bool add_separator = false; if (full_selection.size() == 1) { diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index f979f61196..d0bf83eb2d 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -540,6 +540,10 @@ void SceneTreeEditor::_update_tree(bool p_scroll_to_selected) { return; } + if (tree->is_editing()) { + return; + } + updating_tree = true; tree->clear(); if (get_scene_node()) { diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index f3addd8904..c2bfdaae96 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -838,7 +838,6 @@ ScriptCreateDialog::ScriptCreateDialog() { parent_search_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_class_in_tree)); hb->add_child(parent_search_button); parent_browse_button = memnew(Button); - parent_browse_button->set_flat(true); parent_browse_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path), varray(true, false)); hb->add_child(parent_browse_button); gc->add_child(memnew(Label(TTR("Inherits:")))); @@ -877,7 +876,6 @@ ScriptCreateDialog::ScriptCreateDialog() { file_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb->add_child(file_path); path_button = memnew(Button); - path_button->set_flat(true); path_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path), varray(false, true)); hb->add_child(path_button); gc->add_child(memnew(Label(TTR("Path:")))); diff --git a/main/main.cpp b/main/main.cpp index bb16c49983..67d8d93728 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2252,7 +2252,7 @@ bool Main::start() { ProjectSettings::get_singleton()->set_custom_property_info( "rendering/textures/canvas_textures/default_texture_filter", PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, - "Nearest,Linear,MipmapLinear,MipmapNearest")); + "Nearest,Linear,Linear Mipmap,Nearest Mipmap")); GLOBAL_DEF_BASIC("rendering/textures/canvas_textures/default_texture_repeat", 0); ProjectSettings::get_singleton()->set_custom_property_info( "rendering/textures/canvas_textures/default_texture_repeat", diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index 1cf77b307d..9491373013 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -157,7 +157,7 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por _setup_compressor(); - IP_Address ip; + IPAddress ip; if (p_address.is_valid_ip_address()) { ip = p_address; } else { @@ -749,12 +749,12 @@ void NetworkedMultiplayerENet::enet_compressor_destroy(void *context) { // Nothing to do } -IP_Address NetworkedMultiplayerENet::get_peer_address(int p_peer_id) const { - ERR_FAIL_COND_V_MSG(!peer_map.has(p_peer_id), IP_Address(), vformat("Peer ID %d not found in the list of peers.", p_peer_id)); - ERR_FAIL_COND_V_MSG(!is_server() && p_peer_id != 1, IP_Address(), "Can't get the address of peers other than the server (ID -1) when acting as a client."); - ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == nullptr, IP_Address(), vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id)); +IPAddress NetworkedMultiplayerENet::get_peer_address(int p_peer_id) const { + ERR_FAIL_COND_V_MSG(!peer_map.has(p_peer_id), IPAddress(), vformat("Peer ID %d not found in the list of peers.", p_peer_id)); + ERR_FAIL_COND_V_MSG(!is_server() && p_peer_id != 1, IPAddress(), "Can't get the address of peers other than the server (ID -1) when acting as a client."); + ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == nullptr, IPAddress(), vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id)); - IP_Address out; + IPAddress out; #ifdef GODOT_ENET out.set_ipv6((uint8_t *)&(peer_map[p_peer_id]->address.host)); #else @@ -877,7 +877,7 @@ NetworkedMultiplayerENet::NetworkedMultiplayerENet() { enet_compressor.decompress = enet_decompress; enet_compressor.destroy = enet_compressor_destroy; - bind_ip = IP_Address("*"); + bind_ip = IPAddress("*"); } NetworkedMultiplayerENet::~NetworkedMultiplayerENet() { @@ -888,7 +888,7 @@ NetworkedMultiplayerENet::~NetworkedMultiplayerENet() { // Sets IP for ENet to bind when using create_server or create_client // if no IP is set, then ENet bind to ENET_HOST_ANY -void NetworkedMultiplayerENet::set_bind_ip(const IP_Address &p_ip) { +void NetworkedMultiplayerENet::set_bind_ip(const IPAddress &p_ip) { ERR_FAIL_COND_MSG(!p_ip.is_valid() && !p_ip.is_wildcard(), vformat("Invalid bind IP address: %s", String(p_ip))); bind_ip = p_ip; diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h index c589cd9fbf..2d928859fa 100644 --- a/modules/enet/networked_multiplayer_enet.h +++ b/modules/enet/networked_multiplayer_enet.h @@ -108,7 +108,7 @@ private: static void enet_compressor_destroy(void *context); void _setup_compressor(); - IP_Address bind_ip; + IPAddress bind_ip; bool dtls_enabled = false; Ref<CryptoKey> dtls_key; @@ -125,7 +125,7 @@ public: virtual int get_packet_peer() const override; - virtual IP_Address get_peer_address(int p_peer_id) const; + virtual IPAddress get_peer_address(int p_peer_id) const; virtual int get_peer_port(int p_peer_id) const; virtual int get_local_port() const; void set_peer_timeout(int p_peer_id, int p_timeout_limit, int p_timeout_min, int p_timeout_max); @@ -171,7 +171,7 @@ public: NetworkedMultiplayerENet(); ~NetworkedMultiplayerENet(); - void set_bind_ip(const IP_Address &p_ip); + void set_bind_ip(const IPAddress &p_ip); void set_dtls_enabled(bool p_enabled); bool is_dtls_enabled() const; void set_dtls_verify_enabled(bool p_enabled); diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 099abd35a7..6ae825d2bd 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -2998,6 +2998,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol is_function = true; [[fallthrough]]; } + case GDScriptParser::COMPLETION_CALL_ARGUMENTS: case GDScriptParser::COMPLETION_IDENTIFIER: { GDScriptParser::DataType base_type; if (context.current_class) { diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 2e6388d92f..3f14156dfa 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -643,6 +643,8 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() { push_error(error); } previous_was_underscore = true; + } else { + previous_was_underscore = false; } _advance(); } @@ -714,6 +716,8 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() { push_error(error); } previous_was_underscore = true; + } else { + previous_was_underscore = false; } _advance(); } diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index e63b6ab20e..15236d900d 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -49,8 +49,9 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostic.code = -1; lsp::Range range; lsp::Position pos; - int line = LINE_NUMBER_TO_INDEX(error.line); - const String &line_text = get_lines()[line]; + const PackedStringArray lines = get_lines(); + int line = CLAMP(LINE_NUMBER_TO_INDEX(error.line), 0, lines.size() - 1); + const String &line_text = lines[line]; pos.line = line; pos.character = line_text.length() - line_text.strip_edges(true, false).length(); range.start = pos; @@ -361,24 +362,73 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN r_symbol.detail += " -> " + p_func->get_datatype().to_string(); } - for (int i = 0; i < p_func->body->locals.size(); i++) { - const SuiteNode::Local &local = p_func->body->locals[i]; - lsp::DocumentSymbol symbol; - symbol.name = local.name; - symbol.kind = local.type == SuiteNode::Local::CONSTANT ? lsp::SymbolKind::Constant : lsp::SymbolKind::Variable; - symbol.range.start.line = LINE_NUMBER_TO_INDEX(local.start_line); - symbol.range.start.character = LINE_NUMBER_TO_INDEX(local.start_column); - symbol.range.end.line = LINE_NUMBER_TO_INDEX(local.end_line); - symbol.range.end.character = LINE_NUMBER_TO_INDEX(local.end_column); - symbol.uri = uri; - symbol.script_path = path; - symbol.detail = SuiteNode::Local::CONSTANT ? "const " : "var "; - symbol.detail += symbol.name; - if (local.get_datatype().is_hard_type()) { - symbol.detail += ": " + local.get_datatype().to_string(); + List<GDScriptParser::SuiteNode *> function_nodes; + + List<GDScriptParser::Node *> node_stack; + node_stack.push_back(p_func->body); + + while (!node_stack.is_empty()) { + GDScriptParser::Node *node = node_stack[0]; + node_stack.pop_front(); + + switch (node->type) { + case GDScriptParser::TypeNode::IF: { + GDScriptParser::IfNode *if_node = (GDScriptParser::IfNode *)node; + node_stack.push_back(if_node->true_block); + if (if_node->false_block) { + node_stack.push_back(if_node->false_block); + } + } break; + + case GDScriptParser::TypeNode::FOR: { + GDScriptParser::ForNode *for_node = (GDScriptParser::ForNode *)node; + node_stack.push_back(for_node->loop); + } break; + + case GDScriptParser::TypeNode::WHILE: { + GDScriptParser::WhileNode *while_node = (GDScriptParser::WhileNode *)node; + node_stack.push_back(while_node->loop); + } break; + + case GDScriptParser::TypeNode::MATCH_BRANCH: { + GDScriptParser::MatchBranchNode *match_node = (GDScriptParser::MatchBranchNode *)node; + node_stack.push_back(match_node->block); + } break; + + case GDScriptParser::TypeNode::SUITE: { + GDScriptParser::SuiteNode *suite_node = (GDScriptParser::SuiteNode *)node; + function_nodes.push_back(suite_node); + for (int i = 0; i < suite_node->statements.size(); ++i) { + node_stack.push_back(suite_node->statements[i]); + } + } break; + + default: + continue; + } + } + + for (List<GDScriptParser::SuiteNode *>::Element *N = function_nodes.front(); N; N = N->next()) { + const GDScriptParser::SuiteNode *suite_node = N->get(); + for (int i = 0; i < suite_node->locals.size(); i++) { + const SuiteNode::Local &local = suite_node->locals[i]; + lsp::DocumentSymbol symbol; + symbol.name = local.name; + symbol.kind = local.type == SuiteNode::Local::CONSTANT ? lsp::SymbolKind::Constant : lsp::SymbolKind::Variable; + symbol.range.start.line = LINE_NUMBER_TO_INDEX(local.start_line); + symbol.range.start.character = LINE_NUMBER_TO_INDEX(local.start_column); + symbol.range.end.line = LINE_NUMBER_TO_INDEX(local.end_line); + symbol.range.end.character = LINE_NUMBER_TO_INDEX(local.end_column); + symbol.uri = uri; + symbol.script_path = path; + symbol.detail = local.type == SuiteNode::Local::CONSTANT ? "const " : "var "; + symbol.detail += symbol.name; + if (local.get_datatype().is_hard_type()) { + symbol.detail += ": " + local.get_datatype().to_string(); + } + symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(local.start_line)); + r_symbol.children.push_back(symbol); } - symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(local.start_line)); - r_symbol.children.push_back(symbol); } } diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index 0432e7caea..c16a7fa889 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -255,7 +255,7 @@ void GDScriptLanguageProtocol::poll() { } } -Error GDScriptLanguageProtocol::start(int p_port, const IP_Address &p_bind_ip) { +Error GDScriptLanguageProtocol::start(int p_port, const IPAddress &p_bind_ip) { return server->listen(p_port, p_bind_ip); } diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h index 8b08ae0655..a5c5a233b1 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.h +++ b/modules/gdscript/language_server/gdscript_language_protocol.h @@ -69,7 +69,7 @@ private: static GDScriptLanguageProtocol *singleton; HashMap<int, Ref<LSPeer>> clients; - Ref<TCP_Server> server; + Ref<TCPServer> server; int latest_client_id = 0; int next_client_id = 0; @@ -97,7 +97,7 @@ public: _FORCE_INLINE_ bool is_initialized() const { return _initialized; } void poll(); - Error start(int p_port, const IP_Address &p_bind_ip); + Error start(int p_port, const IPAddress &p_bind_ip); void stop(); void notify_client(const String &p_method, const Variant &p_params = Variant(), int p_client_id = -1); diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index 98ada9de4d..340a7b9343 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -78,7 +78,7 @@ void GDScriptLanguageServer::thread_main(void *p_userdata) { void GDScriptLanguageServer::start() { port = (int)_EDITOR_GET("network/language_server/remote_port"); use_thread = (bool)_EDITOR_GET("network/language_server/use_thread"); - if (protocol.start(port, IP_Address("127.0.0.1")) == OK) { + if (protocol.start(port, IPAddress("127.0.0.1")) == OK) { EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR); if (use_thread) { thread_running = true; diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 69cad1a335..9b7b2b36b4 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -42,6 +42,7 @@ #include "scene/resources/packed_scene.h" void GDScriptWorkspace::_bind_methods() { + ClassDB::bind_method(D_METHOD("didDeleteFiles"), &GDScriptWorkspace::did_delete_files); ClassDB::bind_method(D_METHOD("symbol"), &GDScriptWorkspace::symbol); ClassDB::bind_method(D_METHOD("parse_script", "path", "content"), &GDScriptWorkspace::parse_script); ClassDB::bind_method(D_METHOD("parse_local_script", "path"), &GDScriptWorkspace::parse_local_script); @@ -51,6 +52,16 @@ void GDScriptWorkspace::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_script_api", "path"), &GDScriptWorkspace::generate_script_api); } +void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) { + Array files = p_params["files"]; + for (int i = 0; i < files.size(); ++i) { + Dictionary file = files[i]; + String uri = file["uri"]; + String path = get_file_path(uri); + parse_script(path, ""); + } +} + void GDScriptWorkspace::remove_cache_parser(const String &p_path) { Map<String, ExtendGDScriptParser *>::Element *parser = parse_results.find(p_path); Map<String, ExtendGDScriptParser *>::Element *script = scripts.find(p_path); diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h index 7fd8bfcf20..27616a2989 100644 --- a/modules/gdscript/language_server/gdscript_workspace.h +++ b/modules/gdscript/language_server/gdscript_workspace.h @@ -89,6 +89,7 @@ public: void resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list); Dictionary generate_script_api(const String &p_path); Error resolve_signature(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::SignatureHelp &r_signature); + void did_delete_files(const Dictionary &p_params); GDScriptWorkspace(); ~GDScriptWorkspace(); diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp index 6635098be2..47bcfeaefc 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/lsp.hpp @@ -1528,6 +1528,114 @@ struct SignatureHelp { } }; +/** + * A pattern to describe in which file operation requests or notifications + * the server is interested in. + */ +struct FileOperationPattern { + /** + * The glob pattern to match. + */ + String glob = "**/*.gd"; + + /** + * Whether to match `file`s or `folder`s with this pattern. + * + * Matches both if undefined. + */ + String matches = "file"; + + Dictionary to_json() const { + Dictionary dict; + + dict["glob"] = glob; + dict["matches"] = matches; + + return dict; + } +}; + +/** + * A filter to describe in which file operation requests or notifications + * the server is interested in. + */ +struct FileOperationFilter { + /** + * The actual file operation pattern. + */ + FileOperationPattern pattern; + + Dictionary to_json() const { + Dictionary dict; + + dict["pattern"] = pattern.to_json(); + + return dict; + } +}; + +/** + * The options to register for file operations. + */ +struct FileOperationRegistrationOptions { + /** + * The actual filters. + */ + Vector<FileOperationFilter> filters; + + FileOperationRegistrationOptions() { + filters.push_back(FileOperationFilter()); + } + + Dictionary to_json() const { + Dictionary dict; + + Array filts; + for (int i = 0; i < filters.size(); i++) { + filts.push_back(filters[i].to_json()); + } + dict["filters"] = filts; + + return dict; + } +}; + +/** + * The server is interested in file notifications/requests. + */ +struct FileOperations { + /** + * The server is interested in receiving didDeleteFiles file notifications. + */ + FileOperationRegistrationOptions didDelete; + + Dictionary to_json() const { + Dictionary dict; + + dict["didDelete"] = didDelete.to_json(); + + return dict; + } +}; + +/** + * Workspace specific server capabilities + */ +struct Workspace { + /** + * The server is interested in file notifications/requests. + */ + FileOperations fileOperations; + + Dictionary to_json() const { + Dictionary dict; + + dict["fileOperations"] = fileOperations.to_json(); + + return dict; + } +}; + struct ServerCapabilities { /** * Defines how text documents are synced. Is either a detailed structure defining each notification or @@ -1590,6 +1698,11 @@ struct ServerCapabilities { bool workspaceSymbolProvider = true; /** + * The server supports workspace folder. + */ + Workspace workspace; + + /** * The server provides code actions. The `CodeActionOptions` return type is only * valid if the client signals code action literal support via the property * `textDocument.codeAction.codeActionLiteralSupport`. @@ -1676,6 +1789,7 @@ struct ServerCapabilities { dict["documentHighlightProvider"] = documentHighlightProvider; dict["documentSymbolProvider"] = documentSymbolProvider; dict["workspaceSymbolProvider"] = workspaceSymbolProvider; + dict["workspace"] = workspace.to_json(); dict["codeActionProvider"] = codeActionProvider; dict["documentFormattingProvider"] = documentFormattingProvider; dict["documentRangeFormattingProvider"] = documentRangeFormattingProvider; diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp index 342ded6ea1..d77d946a77 100644 --- a/modules/mbedtls/packet_peer_mbed_dtls.cpp +++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp @@ -87,7 +87,7 @@ void PacketPeerMbedDTLS::_cleanup() { int PacketPeerMbedDTLS::_set_cookie() { // Setup DTLS session cookie for this client uint8_t client_id[18]; - IP_Address addr = base->get_packet_address(); + IPAddress addr = base->get_packet_address(); uint16_t port = base->get_packet_port(); memcpy(client_id, addr.get_ipv6(), 16); memcpy(&client_id[16], (uint8_t *)&port, 2); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 527eb0abc9..dc400982e8 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -740,21 +740,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) { Color c = sbf->get_border_color(); Color ic = c; - c.a = 1; - if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { - Color mono_color; - if (((c.r + c.g + c.b) / 3) < 0.7) { - mono_color = Color(1.0, 1.0, 1.0); - ic = Color(0.0, 0.0, 0.0, 0.7); - } else { - mono_color = Color(0.0, 0.0, 0.0); - ic = Color(1.0, 1.0, 1.0, 0.7); - } - mono_color.a = 0.85; - c = mono_color; - } gnode->add_theme_color_override("title_color", c); - c.a = 0.7; + c.a = 1; gnode->add_theme_color_override("close_color", c); gnode->add_theme_color_override("resizer_color", ic); gnode->add_theme_style_override("frame", sbf); @@ -3623,32 +3610,33 @@ void VisualScriptEditor::_notification(int p_what) { bool dark_theme = tm->get_constant("dark_theme", "Editor"); - List<Pair<String, Color>> colors; if (dark_theme) { - colors.push_back(Pair<String, Color>("flow_control", Color(0.96, 0.96, 0.96))); - colors.push_back(Pair<String, Color>("functions", Color(0.96, 0.52, 0.51))); - colors.push_back(Pair<String, Color>("data", Color(0.5, 0.96, 0.81))); - colors.push_back(Pair<String, Color>("operators", Color(0.67, 0.59, 0.87))); - colors.push_back(Pair<String, Color>("custom", Color(0.5, 0.73, 0.96))); - colors.push_back(Pair<String, Color>("constants", Color(0.96, 0.5, 0.69))); + node_colors["flow_control"] = Color(0.96, 0.96, 0.96); + node_colors["functions"] = Color(0.96, 0.52, 0.51); + node_colors["data"] = Color(0.5, 0.96, 0.81); + node_colors["operators"] = Color(0.67, 0.59, 0.87); + node_colors["custom"] = Color(0.5, 0.73, 0.96); + node_colors["constants"] = Color(0.96, 0.5, 0.69); } else { - colors.push_back(Pair<String, Color>("flow_control", Color(0.26, 0.26, 0.26))); - colors.push_back(Pair<String, Color>("functions", Color(0.95, 0.4, 0.38))); - colors.push_back(Pair<String, Color>("data", Color(0.07, 0.73, 0.51))); - colors.push_back(Pair<String, Color>("operators", Color(0.51, 0.4, 0.82))); - colors.push_back(Pair<String, Color>("custom", Color(0.31, 0.63, 0.95))); - colors.push_back(Pair<String, Color>("constants", Color(0.94, 0.18, 0.49))); + node_colors["flow_control"] = Color(0.26, 0.26, 0.26); + node_colors["functions"] = Color(0.95, 0.4, 0.38); + node_colors["data"] = Color(0.07, 0.73, 0.51); + node_colors["operators"] = Color(0.51, 0.4, 0.82); + node_colors["custom"] = Color(0.31, 0.63, 0.95); + node_colors["constants"] = Color(0.94, 0.18, 0.49); } - for (List<Pair<String, Color>>::Element *E = colors.front(); E; E = E->next()) { - Ref<StyleBoxFlat> sb = tm->get_stylebox("frame", "GraphNode"); + for (Map<StringName, Color>::Element *E = node_colors.front(); E; E = E->next()) { + const Ref<StyleBoxFlat> sb = tm->get_stylebox("frame", "GraphNode"); + if (!sb.is_null()) { Ref<StyleBoxFlat> frame_style = sb->duplicate(); - Color c = sb->get_border_color(); - Color cn = E->get().second; - cn.a = c.a; - frame_style->set_border_color(cn); - node_styles[E->get().first] = frame_style; + // Adjust the border color to be close to the GraphNode's background color. + // This keeps the node's title area from being too distracting. + Color color = dark_theme ? E->get().darkened(0.75) : E->get().lightened(0.75); + color.a = 0.9; + frame_style->set_border_color(color); + node_styles[E->key()] = frame_style; } } diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index bb6f194286..fc9a2df60f 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -135,6 +135,7 @@ class VisualScriptEditor : public ScriptEditorBase { Vector<Pair<Variant::Type, String>> args; }; + Map<StringName, Color> node_colors; HashMap<StringName, Ref<StyleBox>> node_styles; void _update_graph_connections(); diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index 25b6d6ef0e..626498e1ae 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -121,8 +121,8 @@ void EMWSClient::disconnect_from_host(int p_code, String p_reason) { _peer->close(p_code, p_reason); } -IP_Address EMWSClient::get_connected_host() const { - ERR_FAIL_V_MSG(IP_Address(), "Not supported in HTML5 export."); +IPAddress EMWSClient::get_connected_host() const { + ERR_FAIL_V_MSG(IPAddress(), "Not supported in HTML5 export."); } uint16_t EMWSClient::get_connected_port() const { diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h index 2ab7dc83d0..ca2d7ed986 100644 --- a/modules/websocket/emws_client.h +++ b/modules/websocket/emws_client.h @@ -56,7 +56,7 @@ public: Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()); Ref<WebSocketPeer> get_peer(int p_peer_id) const; void disconnect_from_host(int p_code = 1000, String p_reason = ""); - IP_Address get_connected_host() const; + IPAddress get_connected_host() const; uint16_t get_connected_port() const; virtual ConnectionStatus get_connection_status() const; int get_max_packet_size() const; diff --git a/modules/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp index 5e75e10d68..1ad3bdc825 100644 --- a/modules/websocket/emws_peer.cpp +++ b/modules/websocket/emws_peer.cpp @@ -93,8 +93,8 @@ void EMWSPeer::close(int p_code, String p_reason) { peer_sock = -1; }; -IP_Address EMWSPeer::get_connected_host() const { - ERR_FAIL_V_MSG(IP_Address(), "Not supported in HTML5 export."); +IPAddress EMWSPeer::get_connected_host() const { + ERR_FAIL_V_MSG(IPAddress(), "Not supported in HTML5 export."); }; uint16_t EMWSPeer::get_connected_port() const { diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h index abe5bf2bdb..73e701720b 100644 --- a/modules/websocket/emws_peer.h +++ b/modules/websocket/emws_peer.h @@ -73,7 +73,7 @@ public: virtual void close(int p_code = 1000, String p_reason = ""); virtual bool is_connected_to_host() const; - virtual IP_Address get_connected_host() const; + virtual IPAddress get_connected_host() const; virtual uint16_t get_connected_port() const; virtual WriteMode get_write_mode() const; diff --git a/modules/websocket/emws_server.cpp b/modules/websocket/emws_server.cpp index a35d84f372..4a4f09a943 100644 --- a/modules/websocket/emws_server.cpp +++ b/modules/websocket/emws_server.cpp @@ -58,8 +58,8 @@ Vector<String> EMWSServer::get_protocols() const { return out; } -IP_Address EMWSServer::get_peer_address(int p_peer_id) const { - return IP_Address(); +IPAddress EMWSServer::get_peer_address(int p_peer_id) const { + return IPAddress(); } int EMWSServer::get_peer_port(int p_peer_id) const { diff --git a/modules/websocket/emws_server.h b/modules/websocket/emws_server.h index 4179b20ffe..e7285ccb86 100644 --- a/modules/websocket/emws_server.h +++ b/modules/websocket/emws_server.h @@ -47,7 +47,7 @@ public: bool is_listening() const; bool has_peer(int p_id) const; Ref<WebSocketPeer> get_peer(int p_id) const; - IP_Address get_peer_address(int p_peer_id) const; + IPAddress get_peer_address(int p_peer_id) const; int get_peer_port(int p_peer_id) const; void disconnect_peer(int p_peer_id, int p_code = 1000, String p_reason = ""); int get_max_packet_size() const; diff --git a/modules/websocket/websocket_client.h b/modules/websocket/websocket_client.h index 0225c9b3d3..c7f17f1ffb 100644 --- a/modules/websocket/websocket_client.h +++ b/modules/websocket/websocket_client.h @@ -57,7 +57,7 @@ public: virtual Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) = 0; virtual void disconnect_from_host(int p_code = 1000, String p_reason = "") = 0; - virtual IP_Address get_connected_host() const = 0; + virtual IPAddress get_connected_host() const = 0; virtual uint16_t get_connected_port() const = 0; virtual bool is_server() const override; diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index 2ba83637f9..e9bb20f21f 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -55,7 +55,7 @@ public: virtual void close(int p_code = 1000, String p_reason = "") = 0; virtual bool is_connected_to_host() const = 0; - virtual IP_Address get_connected_host() const = 0; + virtual IPAddress get_connected_host() const = 0; virtual uint16_t get_connected_port() const = 0; virtual bool was_string_packet() const = 0; virtual void set_no_delay(bool p_enabled) = 0; diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp index f57e8d959c..7cf68b835c 100644 --- a/modules/websocket/websocket_server.cpp +++ b/modules/websocket/websocket_server.cpp @@ -34,7 +34,7 @@ GDCINULL(WebSocketServer); WebSocketServer::WebSocketServer() { _peer_id = 1; - bind_ip = IP_Address("*"); + bind_ip = IPAddress("*"); } WebSocketServer::~WebSocketServer() { @@ -71,11 +71,11 @@ void WebSocketServer::_bind_methods() { ADD_SIGNAL(MethodInfo("data_received", PropertyInfo(Variant::INT, "id"))); } -IP_Address WebSocketServer::get_bind_ip() const { +IPAddress WebSocketServer::get_bind_ip() const { return bind_ip; } -void WebSocketServer::set_bind_ip(const IP_Address &p_bind_ip) { +void WebSocketServer::set_bind_ip(const IPAddress &p_bind_ip) { ERR_FAIL_COND(is_listening()); ERR_FAIL_COND(!p_bind_ip.is_valid() && !p_bind_ip.is_wildcard()); bind_ip = p_bind_ip; diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h index 3fbd5e3b95..10da51fce5 100644 --- a/modules/websocket/websocket_server.h +++ b/modules/websocket/websocket_server.h @@ -40,7 +40,7 @@ class WebSocketServer : public WebSocketMultiplayerPeer { GDCLASS(WebSocketServer, WebSocketMultiplayerPeer); GDCICLASS(WebSocketServer); - IP_Address bind_ip; + IPAddress bind_ip; protected: static void _bind_methods(); @@ -57,7 +57,7 @@ public: virtual bool is_server() const override; ConnectionStatus get_connection_status() const override; - virtual IP_Address get_peer_address(int p_peer_id) const = 0; + virtual IPAddress get_peer_address(int p_peer_id) const = 0; virtual int get_peer_port(int p_peer_id) const = 0; virtual void disconnect_peer(int p_peer_id, int p_code = 1000, String p_reason = "") = 0; @@ -66,8 +66,8 @@ public: void _on_disconnect(int32_t p_peer_id, bool p_was_clean); void _on_close_request(int32_t p_peer_id, int p_code, String p_reason); - IP_Address get_bind_ip() const; - void set_bind_ip(const IP_Address &p_bind_ip); + IPAddress get_bind_ip() const; + void set_bind_ip(const IPAddress &p_bind_ip); Ref<CryptoKey> get_private_key() const; void set_private_key(Ref<CryptoKey> p_key); diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp index a075ae3982..111d2178d6 100644 --- a/modules/websocket/wsl_client.cpp +++ b/modules/websocket/wsl_client.cpp @@ -160,7 +160,7 @@ Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE); _peer = Ref<WSLPeer>(memnew(WSLPeer)); - IP_Address addr; + IPAddress addr; if (!p_host.is_valid_ip_address()) { addr = IP::get_singleton()->resolve_hostname(p_host); @@ -316,8 +316,8 @@ void WSLClient::disconnect_from_host(int p_code, String p_reason) { _resp_pos = 0; } -IP_Address WSLClient::get_connected_host() const { - ERR_FAIL_COND_V(!_peer->is_connected_to_host(), IP_Address()); +IPAddress WSLClient::get_connected_host() const { + ERR_FAIL_COND_V(!_peer->is_connected_to_host(), IPAddress()); return _peer->get_connected_host(); } diff --git a/modules/websocket/wsl_client.h b/modules/websocket/wsl_client.h index e7c91ed333..849639ee8b 100644 --- a/modules/websocket/wsl_client.h +++ b/modules/websocket/wsl_client.h @@ -75,7 +75,7 @@ public: int get_max_packet_size() const; Ref<WebSocketPeer> get_peer(int p_peer_id) const; void disconnect_from_host(int p_code = 1000, String p_reason = ""); - IP_Address get_connected_host() const; + IPAddress get_connected_host() const; uint16_t get_connected_port() const; virtual ConnectionStatus get_connection_status() const; virtual void poll(); diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp index dbbf86d0da..1dbadfed74 100644 --- a/modules/websocket/wsl_peer.cpp +++ b/modules/websocket/wsl_peer.cpp @@ -305,8 +305,8 @@ void WSLPeer::close(int p_code, String p_reason) { _packet_buffer.resize(0); } -IP_Address WSLPeer::get_connected_host() const { - ERR_FAIL_COND_V(!is_connected_to_host() || _data->tcp.is_null(), IP_Address()); +IPAddress WSLPeer::get_connected_host() const { + ERR_FAIL_COND_V(!is_connected_to_host() || _data->tcp.is_null(), IPAddress()); return _data->tcp->get_connected_host(); } diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h index 5e6a7e8554..f1ea98d384 100644 --- a/modules/websocket/wsl_peer.h +++ b/modules/websocket/wsl_peer.h @@ -90,7 +90,7 @@ public: virtual void close_now(); virtual void close(int p_code = 1000, String p_reason = ""); virtual bool is_connected_to_host() const; - virtual IP_Address get_connected_host() const; + virtual IPAddress get_connected_host() const; virtual uint16_t get_connected_port() const; virtual WriteMode get_write_mode() const; diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp index 437eb2061b..dc5b23c31e 100644 --- a/modules/websocket/wsl_server.cpp +++ b/modules/websocket/wsl_server.cpp @@ -272,8 +272,8 @@ Ref<WebSocketPeer> WSLServer::get_peer(int p_id) const { return _peer_map[p_id]; } -IP_Address WSLServer::get_peer_address(int p_peer_id) const { - ERR_FAIL_COND_V(!has_peer(p_peer_id), IP_Address()); +IPAddress WSLServer::get_peer_address(int p_peer_id) const { + ERR_FAIL_COND_V(!has_peer(p_peer_id), IPAddress()); return _peer_map[p_peer_id]->get_connected_host(); } diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h index 75669e12ee..c2cf9df58b 100644 --- a/modules/websocket/wsl_server.h +++ b/modules/websocket/wsl_server.h @@ -73,7 +73,7 @@ private: int _out_pkt_size = DEF_PKT_SHIFT; List<Ref<PendingPeer>> _pending; - Ref<TCP_Server> _server; + Ref<TCPServer> _server; Vector<String> _protocols; public: @@ -84,7 +84,7 @@ public: int get_max_packet_size() const; bool has_peer(int p_id) const; Ref<WebSocketPeer> get_peer(int p_id) const; - IP_Address get_peer_address(int p_peer_id) const; + IPAddress get_peer_address(int p_peer_id) const; int get_peer_port(int p_peer_id) const; void disconnect_peer(int p_peer_id, int p_code = 1000, String p_reason = ""); virtual void poll(); diff --git a/platform/android/net_socket_android.cpp b/platform/android/net_socket_android.cpp index ddc2368793..dbd1870ee6 100644 --- a/platform/android/net_socket_android.cpp +++ b/platform/android/net_socket_android.cpp @@ -103,7 +103,7 @@ Error NetSocketAndroid::set_broadcasting_enabled(bool p_enabled) { return OK; } -Error NetSocketAndroid::join_multicast_group(const IP_Address &p_multi_address, String p_if_name) { +Error NetSocketAndroid::join_multicast_group(const IPAddress &p_multi_address, String p_if_name) { Error err = NetSocketPosix::join_multicast_group(p_multi_address, p_if_name); if (err != OK) return err; @@ -115,7 +115,7 @@ Error NetSocketAndroid::join_multicast_group(const IP_Address &p_multi_address, return OK; } -Error NetSocketAndroid::leave_multicast_group(const IP_Address &p_multi_address, String p_if_name) { +Error NetSocketAndroid::leave_multicast_group(const IPAddress &p_multi_address, String p_if_name) { Error err = NetSocketPosix::leave_multicast_group(p_multi_address, p_if_name); if (err != OK) return err; diff --git a/platform/android/net_socket_android.h b/platform/android/net_socket_android.h index cc2a68ac49..60090c26bb 100644 --- a/platform/android/net_socket_android.h +++ b/platform/android/net_socket_android.h @@ -67,8 +67,8 @@ public: virtual void close(); virtual Error set_broadcasting_enabled(bool p_enabled); - virtual Error join_multicast_group(const IP_Address &p_multi_address, String p_if_name); - virtual Error leave_multicast_group(const IP_Address &p_multi_address, String p_if_name); + virtual Error join_multicast_group(const IPAddress &p_multi_address, String p_if_name); + virtual Error leave_multicast_group(const IPAddress &p_multi_address, String p_if_name); NetSocketAndroid() {} ~NetSocketAndroid(); diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 14e279b45b..951d86d09e 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -41,7 +41,7 @@ class EditorHTTPServer : public Reference { private: - Ref<TCP_Server> server; + Ref<TCPServer> server; Map<String, String> mimes; Ref<StreamPeerTCP> tcp; Ref<StreamPeerSSL> ssl; @@ -100,7 +100,7 @@ public: _clear_client(); } - Error listen(int p_port, IP_Address p_address, bool p_use_ssl, String p_ssl_key, String p_ssl_cert) { + Error listen(int p_port, IPAddress p_address, bool p_use_ssl, String p_ssl_key, String p_ssl_cert) { use_ssl = p_use_ssl; if (use_ssl) { Ref<Crypto> crypto = Crypto::create(); @@ -919,7 +919,7 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese const uint16_t bind_port = EDITOR_GET("export/web/http_port"); // Resolve host if needed. const String bind_host = EDITOR_GET("export/web/http_host"); - IP_Address bind_ip; + IPAddress bind_ip; if (bind_host.is_valid_ip_address()) { bind_ip = bind_host; } else { diff --git a/platform/javascript/http_client.h.inc b/platform/javascript/http_client.h.inc index 842a93fcba..6544d41c98 100644 --- a/platform/javascript/http_client.h.inc +++ b/platform/javascript/http_client.h.inc @@ -34,7 +34,8 @@ Error make_request(Method p_method, const String &p_url, const Vector<String> &p static void _parse_headers(int p_len, const char **p_headers, void *p_ref); int js_id = 0; -int read_limit = 4096; +// 64 KiB by default (favors fast download speeds at the cost of memory usage). +int read_limit = 65536; Status status = STATUS_DISCONNECTED; String host; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 33992069f9..2314a392cc 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -147,7 +147,7 @@ void OS_UWP::initialize_core() { ticks_start = 0; ticks_start = get_ticks_usec(); - IP_Unix::make_default(); + IPUnix::make_default(); cursor_shape = CURSOR_ARROW; } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 1e9cdd241d..f517190a89 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -204,7 +204,7 @@ void OS_Windows::initialize() { current_pi.pi.hProcess = GetCurrentProcess(); process_map->insert(GetCurrentProcessId(), current_pi); - IP_Unix::make_default(); + IPUnix::make_default(); main_loop = nullptr; } diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 826fd0189b..ac067aa001 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -155,6 +155,9 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) { } status.pressed = !status.pressed; _unpress_group(); + if (button_group.is_valid()) { + button_group->emit_signal("pressed", this); + } _toggled(status.pressed); _pressed(); } @@ -218,6 +221,9 @@ void BaseButton::set_pressed(bool p_pressed) { if (p_pressed) { _unpress_group(); + if (button_group.is_valid()) { + button_group->emit_signal("pressed", this); + } } _toggled(status.pressed); @@ -487,6 +493,7 @@ BaseButton *ButtonGroup::get_pressed_button() { void ButtonGroup::_bind_methods() { ClassDB::bind_method(D_METHOD("get_pressed_button"), &ButtonGroup::get_pressed_button); ClassDB::bind_method(D_METHOD("get_buttons"), &ButtonGroup::_get_buttons); + ADD_SIGNAL(MethodInfo("pressed", PropertyInfo(Variant::OBJECT, "button"))); } ButtonGroup::ButtonGroup() { diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index b78f9cad24..114abbd4da 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -189,6 +189,18 @@ void ColorPicker::set_pick_color(const Color &p_color) { _set_pick_color(p_color, true); //because setters can't have more arguments } +void ColorPicker::set_old_color(const Color &p_color) { + old_color = p_color; +} + +void ColorPicker::set_display_old_color(bool p_enabled) { + display_old_color = p_enabled; +} + +bool ColorPicker::is_displaying_old_color() const { + return display_old_color; +} + void ColorPicker::set_edit_alpha(bool p_show) { edit_alpha = p_show; _update_controls(); @@ -459,17 +471,39 @@ void ColorPicker::_update_text_value() { } void ColorPicker::_sample_draw() { - const Rect2 r = Rect2(Point2(), Size2(sample->get_size().width, sample->get_size().height * 0.95)); + // Covers the right half of the sample if the old color is being displayed, + // or the whole sample if it's not being displayed. + Rect2 rect_new; + + if (display_old_color) { + rect_new = Rect2(Point2(sample->get_size().width * 0.5, 0), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95)); + + // Draw both old and new colors for easier comparison (only if spawned from a ColorPickerButton). + const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95)); + + if (display_old_color && old_color.a < 1.0) { + sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), rect_old, true); + } + + sample->draw_rect(rect_old, old_color); + + if (old_color.r > 1 || old_color.g > 1 || old_color.b > 1) { + // Draw an indicator to denote that the old color is "overbright" and can't be displayed accurately in the preview. + sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2()); + } + } else { + rect_new = Rect2(Point2(), Size2(sample->get_size().width, sample->get_size().height * 0.95)); + } if (color.a < 1.0) { - sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), r, true); + sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), rect_new, true); } - sample->draw_rect(r, color); + sample->draw_rect(rect_new, color); if (color.r > 1 || color.g > 1 || color.b > 1) { - // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview - sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2()); + // Draw an indicator to denote that the new color is "overbright" and can't be displayed accurately in the preview. + sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2(uv_edit->get_size().width * 0.5, 0)); } } @@ -1174,6 +1208,11 @@ ColorPicker::ColorPicker() : ///////////////// +void ColorPickerButton::_about_to_popup() { + set_pressed(true); + picker->set_old_color(color); +} + void ColorPickerButton::_color_changed(const Color &p_color) { color = p_color; update(); @@ -1286,10 +1325,11 @@ void ColorPickerButton::_update_picker() { popup->add_child(picker); add_child(popup); picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed)); - popup->connect("about_to_popup", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true)); + popup->connect("about_to_popup", callable_mp(this, &ColorPickerButton::_about_to_popup)); popup->connect("popup_hide", callable_mp(this, &ColorPickerButton::_modal_closed)); picker->set_pick_color(color); picker->set_edit_alpha(edit_alpha); + picker->set_display_old_color(true); emit_signal("picker_created"); } } @@ -1301,6 +1341,7 @@ void ColorPickerButton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_popup"), &ColorPickerButton::get_popup); ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPickerButton::set_edit_alpha); ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPickerButton::is_editing_alpha); + ClassDB::bind_method(D_METHOD("_about_to_popup"), &ColorPickerButton::_about_to_popup); ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color"))); ADD_SIGNAL(MethodInfo("popup_closed")); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index a0d2aa95ca..13fe5fd60e 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -86,6 +86,8 @@ private: PickerShapeType picker_type = SHAPE_HSV_WHEEL; Color color; + Color old_color; + bool display_old_color = false; bool raw_mode_enabled = false; bool hsv_mode_enabled = false; bool deferred_mode_enabled = false; @@ -131,6 +133,10 @@ public: void _set_pick_color(const Color &p_color, bool p_update_sliders); void set_pick_color(const Color &p_color); Color get_pick_color() const; + void set_old_color(const Color &p_color); + + void set_display_old_color(bool p_enabled); + bool is_displaying_old_color() const; void set_picker_shape(PickerShapeType p_picker_type); PickerShapeType get_picker_shape() const; @@ -171,6 +177,7 @@ class ColorPickerButton : public Button { Color color; bool edit_alpha = true; + void _about_to_popup(); void _color_changed(const Color &p_color); void _modal_closed(); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6404f6fc0d..d10ce584b7 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1672,7 +1672,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 float line_width = 1.0; #ifdef TOOLS_ENABLED - line_width *= EDSCALE; + line_width *= Math::round(EDSCALE); #endif Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs; @@ -3013,6 +3013,10 @@ bool Tree::edit_selected() { return false; } +bool Tree::is_editing() { + return popup_editor->is_visible(); +} + Size2 Tree::get_internal_min_size() const { Size2i size = cache.bg->get_offset(); if (root) { diff --git a/scene/gui/tree.h b/scene/gui/tree.h index a40817b752..6d36f0df7f 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -604,6 +604,7 @@ public: int get_item_offset(TreeItem *p_item) const; Rect2 get_item_rect(TreeItem *p_item, int p_column = -1) const; bool edit_selected(); + bool is_editing(); // First item that starts with the text, from the current focused item down and wraps around. TreeItem *search_item_text(const String &p_find, int *r_col = nullptr, bool p_selectable = false); diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 55529517f1..fa98a10a26 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -1210,7 +1210,7 @@ void CanvasItem::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask"); ADD_GROUP("Texture", "texture_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Aniso.,Linear Mipmap Aniso."), "set_texture_filter", "get_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat"); ADD_GROUP("Material", ""); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index f861e3064c..b94a818b06 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -3608,7 +3608,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold"); ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw"); ADD_GROUP("Canvas Items", "canvas_item_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapLinear,MipmapNearest"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat"); ADD_GROUP("Audio Listener", "audio_listener_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d"); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index e8157c7165..86c7bda2b3 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -2519,7 +2519,7 @@ void BaseMaterial3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_world_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_WORLD_TRIPLANAR); ADD_GROUP("Sampling", "texture_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Aniso.,Linear Mipmap Aniso."), "set_texture_filter", "get_texture_filter"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "texture_repeat"), "set_flag", "get_flag", FLAG_USE_TEXTURE_REPEAT); ADD_GROUP("Shadows", ""); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 2de0549e8d..d86c44a206 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -93,10 +93,14 @@ public: DeviceFamily device_family = DEVICE_UNKNOWN; uint32_t version_major = 1.0; uint32_t version_minor = 0.0; + // subgroup capabilities uint32_t subgroup_size = 0; uint32_t subgroup_in_shaders = 0; // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc. uint32_t subgroup_operations = 0; // Set flags, using SubgroupOperations + + // features + bool supports_multiview = false; // If true this device supports multiview options }; typedef Vector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities); diff --git a/tests/test_string.h b/tests/test_string.h index 94d14517ae..486c17dbbd 100644 --- a/tests/test_string.h +++ b/tests/test_string.h @@ -860,10 +860,10 @@ TEST_CASE("[String] match") { } TEST_CASE("[String] IPVX address to string") { - IP_Address ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); - IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, true); - IP_Address ip2("fe80::52e5:49ff:fe93:1baf"); - IP_Address ip3("::ffff:192.168.0.1"); + IPAddress ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + IPAddress ip(0x0123, 0x4567, 0x89ab, 0xcdef, true); + IPAddress ip2("fe80::52e5:49ff:fe93:1baf"); + IPAddress ip3("::ffff:192.168.0.1"); String ip4 = "192.168.0.1"; CHECK(ip4.is_valid_ip_address()); diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp index 189de6cc1f..fd7968204b 100644 --- a/thirdparty/enet/godot.cpp +++ b/thirdparty/enet/godot.cpp @@ -45,10 +45,10 @@ /// Abstract ENet interface for UDP/DTLS. class ENetGodotSocket { public: - virtual Error bind(IP_Address p_ip, uint16_t p_port) = 0; - virtual Error get_socket_address(IP_Address *r_ip, uint16_t *r_port) = 0; - virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0; - virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) = 0; + virtual Error bind(IPAddress p_ip, uint16_t p_port) = 0; + virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) = 0; + virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) = 0; + virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port) = 0; virtual int set_option(ENetSocketOption p_option, int p_value) = 0; virtual void close() = 0; virtual void set_refuse_new_connections(bool p_enable) {} /* Only used by dtls server */ @@ -65,7 +65,7 @@ class ENetUDP : public ENetGodotSocket { private: Ref<NetSocket> sock; - IP_Address local_address; + IPAddress local_address; bool bound = false; public: @@ -79,21 +79,21 @@ public: sock->close(); } - Error bind(IP_Address p_ip, uint16_t p_port) { + Error bind(IPAddress p_ip, uint16_t p_port) { local_address = p_ip; bound = true; return sock->bind(p_ip, p_port); } - Error get_socket_address(IP_Address *r_ip, uint16_t *r_port) { + Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) { return sock->get_socket_address(r_ip, r_port); } - Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) { + Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) { return sock->sendto(p_buffer, p_len, r_sent, p_ip, p_port); } - Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) { + Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port) { Error err = sock->poll(NetSocket::POLL_TYPE_IN, 0); if (err != OK) { return err; @@ -157,7 +157,7 @@ class ENetDTLSClient : public ENetGodotSocket { bool verify = false; String for_hostname; Ref<X509Certificate> cert; - IP_Address local_address; + IPAddress local_address; public: ENetDTLSClient(ENetUDP *p_base, Ref<X509Certificate> p_cert, bool p_verify, String p_for_hostname) { @@ -178,12 +178,12 @@ public: close(); } - Error bind(IP_Address p_ip, uint16_t p_port) { + Error bind(IPAddress p_ip, uint16_t p_port) { local_address = p_ip; return udp->bind(p_port, p_ip); } - Error get_socket_address(IP_Address *r_ip, uint16_t *r_port) { + Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) { if (!udp->is_bound()) { return ERR_UNCONFIGURED; } @@ -192,7 +192,7 @@ public: return OK; } - Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) { + Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) { if (!connected) { udp->connect_to_host(p_ip, p_port); dtls->connect_to_peer(udp, verify, for_hostname, cert); @@ -208,7 +208,7 @@ public: return dtls->put_packet(p_buffer, p_len); } - Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) { + Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port) { dtls->poll(); if (dtls->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING) { return ERR_BUSY; @@ -250,7 +250,7 @@ class ENetDTLSServer : public ENetGodotSocket { Ref<UDPServer> udp_server; Map<String, Ref<PacketPeerDTLS>> peers; int last_service = 0; - IP_Address local_address; + IPAddress local_address; public: ENetDTLSServer(ENetUDP *p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert) { @@ -273,12 +273,12 @@ public: udp_server->set_max_pending_connections(p_refuse ? 0 : 16); } - Error bind(IP_Address p_ip, uint16_t p_port) { + Error bind(IPAddress p_ip, uint16_t p_port) { local_address = p_ip; return udp_server->listen(p_port, p_ip); } - Error get_socket_address(IP_Address *r_ip, uint16_t *r_port) { + Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) { if (!udp_server->is_listening()) { return ERR_UNCONFIGURED; } @@ -287,7 +287,7 @@ public: return OK; } - Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) { + Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) { String key = String(p_ip) + ":" + itos(p_port); ERR_FAIL_COND_V(!peers.has(key), ERR_UNAVAILABLE); Ref<PacketPeerDTLS> peer = peers[key]; @@ -302,12 +302,12 @@ public: return err; } - Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) { + Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port) { udp_server->poll(); // TODO limits? Maybe we can better enforce allowed connections! if (udp_server->is_connection_available()) { Ref<PacketPeerUDP> udp = udp_server->take_connection(); - IP_Address peer_ip = udp->get_packet_address(); + IPAddress peer_ip = udp->get_packet_address(); int peer_port = udp->get_packet_port(); Ref<PacketPeerDTLS> peer = server->take_connection(udp); PacketPeerDTLS::Status status = peer->get_status(); @@ -397,7 +397,7 @@ void enet_time_set(enet_uint32 newTimeBase) { } int enet_address_set_host(ENetAddress *address, const char *name) { - IP_Address ip = IP::get_singleton()->resolve_hostname(name); + IPAddress ip = IP::get_singleton()->resolve_hostname(name); ERR_FAIL_COND_V(!ip.is_valid(), -1); enet_address_set_ip(address, ip.get_ipv6(), 16); @@ -442,9 +442,9 @@ void enet_host_refuse_new_connections(ENetHost *host, int p_refuse) { } int enet_socket_bind(ENetSocket socket, const ENetAddress *address) { - IP_Address ip; + IPAddress ip; if (address->wildcard) { - ip = IP_Address("*"); + ip = IPAddress("*"); } else { ip.set_ipv6(address->host); } @@ -466,7 +466,7 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu ERR_FAIL_COND_V(address == nullptr, -1); ENetGodotSocket *sock = (ENetGodotSocket *)socket; - IP_Address dest; + IPAddress dest; Error err; size_t i = 0; @@ -508,7 +508,7 @@ int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buf ENetGodotSocket *sock = (ENetGodotSocket *)socket; int read; - IP_Address ip; + IPAddress ip; Error err = sock->recvfrom((uint8_t *)buffers[0].data, buffers[0].dataLength, read, ip, address->port); if (err == ERR_BUSY) { @@ -525,7 +525,7 @@ int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buf } int enet_socket_get_address (ENetSocket socket, ENetAddress * address) { - IP_Address ip; + IPAddress ip; uint16_t port; ENetGodotSocket *sock = (ENetGodotSocket *)socket; |