diff options
60 files changed, 966 insertions, 378 deletions
diff --git a/SConstruct b/SConstruct index aab605cdcb..365463ebad 100644 --- a/SConstruct +++ b/SConstruct @@ -61,10 +61,12 @@ platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False)) if (os.name=="posix"): pass elif (os.name=="nt"): - if (not methods.msvc_is_detected() or platform_arg=="android"): + if ( os.getenv("VCINSTALLDIR")==None or platform_arg=="android"): custom_tools=['mingw'] env_base=Environment(tools=custom_tools); +if 'TERM' in os.environ: + env_base['ENV']['TERM'] = os.environ['TERM'] env_base.AppendENVPath('PATH', os.getenv('PATH')) env_base.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH')) env_base.global_defaults=global_defaults @@ -137,13 +139,13 @@ opts.Add('glew','GLEW library for the gl_context (system/builtin)','builtin') opts.Add('xaudio2','XAudio2 audio driver (yes/no)','no') opts.Add("CXX", "C++ Compiler") opts.Add("CC", "C Compiler") -opts.Add("CCFLAGS", "Custom flags for the C++ compiler"); +opts.Add("CCFLAGS", "Custom flags for the C/C++ compiler"); opts.Add("CFLAGS", "Custom flags for the C compiler"); opts.Add("LINKFLAGS", "Custom flags for the linker"); opts.Add('unix_global_settings_path', 'unix-specific path to system-wide settings. Currently only used by templates.','') opts.Add('disable_3d', 'Disable 3D nodes for smaller executable (yes/no)', "no") opts.Add('disable_advanced_gui', 'Disable advance 3D gui nodes and behaviors (yes/no)', "no") -opts.Add('colored', 'Enable colored output for the compilation (yes/no)', 'no') +opts.Add('verbose', 'Enable verbose output for the compilation (yes/no)', 'yes') opts.Add('deprecated','Enable deprecated features (yes/no)','yes') opts.Add('extra_suffix', 'Custom extra suffix added to the base filename of all generated binary files.', '') opts.Add('vsproj', 'Generate Visual Studio Project. (yes/no)', 'no') @@ -262,6 +264,8 @@ if selected_platform in platform_list: sys.exit(255) suffix+=".opt" + env.Append(CCFLAGS=['-DNDEBUG']); + elif (env["target"]=="release_debug"): if (env["tools"]=="yes"): suffix+=".opt.tools" @@ -330,8 +334,8 @@ if selected_platform in platform_list: if (env['xml']=='yes'): env.Append(CPPFLAGS=['-DXML_ENABLED']) - if (env['colored']=='yes'): - methods.colored(sys,env) + if (env['verbose']=='no'): + methods.no_verbose(sys,env) Export('env') @@ -379,9 +383,9 @@ if selected_platform in platform_list: release_variants = ['release|Win32']+['release|x64'] release_debug_variants = ['release_debug|Win32']+['release_debug|x64'] variants = debug_variants + release_variants + release_debug_variants - debug_targets = ['Debug']+['Debug'] - release_targets = ['Release']+['Release'] - release_debug_targets = ['ReleaseDebug']+['ReleaseDebug'] + debug_targets = ['bin\\godot.windows.tools.32.exe']+['bin\\godot.windows.tools.64.exe'] + release_targets = ['bin\\godot.windows.opt.32.exe']+['bin\\godot.windows.opt.64.exe'] + release_debug_targets = ['bin\\godot.windows.opt.tools.32.exe']+['bin\\godot.windows.opt.tools.64.exe'] targets = debug_targets + release_targets + release_debug_targets msvproj = env.MSVSProject(target = ['#godot' + env['MSVSPROJECTSUFFIX'] ], incs = env.vs_incs, diff --git a/bin/tests/test_string.cpp b/bin/tests/test_string.cpp index be37ce118f..2e8f5c3494 100644 --- a/bin/tests/test_string.cpp +++ b/bin/tests/test_string.cpp @@ -32,6 +32,7 @@ #include <stdio.h> #include "os/os.h" #include "drivers/nrex/regex.h" +#include "core/io/ip_address.h" #include "test_string.h" @@ -843,6 +844,62 @@ bool test_28() { return state; } +bool test_29() { + + bool error = false; + bool state = true; + bool success = false; + + IP_Address ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + OS::get_singleton()->print("ip0 is %ls\n", String(ip0).c_str()); + + IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, IP_Address::TYPE_IPV6); + OS::get_singleton()->print("ip6 is %ls\n", String(ip).c_str()); + + IP_Address ip2("fe80::52e5:49ff:fe93:1baf"); + OS::get_singleton()->print("ip6 is %ls\n", String(ip2).c_str()); + + IP_Address ip3("::ffff:192.168.0.1"); + OS::get_singleton()->print("ip6 is %ls\n", String(ip3).c_str()); + + String ip4 = "192.168.0.1"; + success = ip4.is_valid_ip_address(); + OS::get_singleton()->print("Is valid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip4 = "192.368.0.1"; + success = (!ip4.is_valid_ip_address()); + OS::get_singleton()->print("Is invalid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + String ip6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; + success = ip6.is_valid_ip_address(); + OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip6 = "2001:0db8:85j3:0000:0000:8a2e:0370:7334"; + success = (!ip6.is_valid_ip_address()); + OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip6 = "2001:0db8:85f345:0000:0000:8a2e:0370:7334"; + success = (!ip6.is_valid_ip_address()); + OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip6 = "2001:0db8::0:8a2e:370:7334"; + success = (ip6.is_valid_ip_address()); + OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip6 = "::ffff:192.168.0.1"; + success = (ip6.is_valid_ip_address()); + OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + return state; +}; + typedef bool (*TestFunc)(void); TestFunc test_funcs[] = { @@ -875,6 +932,7 @@ TestFunc test_funcs[] = { test_26, test_27, test_28, + test_29, 0 }; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 2a831dd992..e3289b452c 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -29,8 +29,9 @@ #include "http_client.h" #include "io/stream_peer_ssl.h" +VARIANT_ENUM_CAST(IP_Address::AddrType); -Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host){ +Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host, IP_Address::AddrType p_addr_type){ close(); conn_port=p_port; @@ -62,7 +63,7 @@ Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_ve status=STATUS_CONNECTING; } else { //is hostname - resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host); + resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host, p_addr_type); status=STATUS_RESOLVING; } @@ -635,7 +636,7 @@ Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received) void HTTPClient::_bind_methods() { - ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true),DEFVAL(IP_Address::TYPE_ANY)); ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); ObjectTypeDB::bind_method(_MD("get_connection:StreamPeer"),&HTTPClient::get_connection); ObjectTypeDB::bind_method(_MD("request_raw","method","url","headers","body"),&HTTPClient::request_raw); diff --git a/core/io/http_client.h b/core/io/http_client.h index 32d2e72101..ba464c34c7 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -165,7 +165,7 @@ public: //Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request - Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true); + Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true, IP_Address::AddrType p_addr_type = IP_Address::TYPE_ANY); void set_connection(const Ref<StreamPeer>& p_connection); Ref<StreamPeer> get_connection() const; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index a77aace07f..4ee1b281c4 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -32,6 +32,7 @@ #include "hash_map.h" VARIANT_ENUM_CAST(IP::ResolverStatus); +VARIANT_ENUM_CAST(IP_Address::AddrType); /************* RESOLVER ******************/ @@ -43,10 +44,12 @@ struct _IP_ResolverPrivate { volatile IP::ResolverStatus status; IP_Address response; String hostname; + IP_Address::AddrType type; void clear() { status = IP::RESOLVER_STATUS_NONE; response = IP_Address(); + type = IP_Address::TYPE_NONE; hostname=""; }; @@ -78,9 +81,9 @@ struct _IP_ResolverPrivate { if (queue[i].status!=IP::RESOLVER_STATUS_WAITING) continue; - queue[i].response=IP::get_singleton()->resolve_hostname(queue[i].hostname); + queue[i].response=IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type); - if (queue[i].response.host==0) + if (queue[i].response.type==IP_Address::TYPE_NONE) queue[i].status=IP::RESOLVER_STATUS_ERROR; else queue[i].status=IP::RESOLVER_STATUS_DONE; @@ -109,21 +112,23 @@ struct _IP_ResolverPrivate { -IP_Address IP::resolve_hostname(const String& p_hostname) { +IP_Address IP::resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) { - GLOBAL_LOCK_FUNCTION + GLOBAL_LOCK_FUNCTION; if (resolver->cache.has(p_hostname)) - return resolver->cache[p_hostname]; + if (resolver->cache[p_hostname].type & p_type != 0) + return resolver->cache[p_hostname]; + // requested type is different from type in cache. continue resolution, if successful it'll overwrite cache - IP_Address res = _resolve_hostname(p_hostname); + IP_Address res = _resolve_hostname(p_hostname, p_type); resolver->cache[p_hostname]=res; return res; } -IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname) { +IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP_Address::AddrType p_type) { - GLOBAL_LOCK_FUNCTION + GLOBAL_LOCK_FUNCTION; ResolverID id = resolver->find_empty_id(); @@ -133,7 +138,8 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname) { } resolver->queue[id].hostname=p_hostname; - if (resolver->cache.has(p_hostname)) { + resolver->queue[id].type = p_type; + if (resolver->cache.has(p_hostname) && (resolver->cache[p_hostname].type & p_type) != 0) { resolver->queue[id].response=resolver->cache[p_hostname]; resolver->queue[id].status=IP::RESOLVER_STATUS_DONE; } else { @@ -145,10 +151,6 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname) { resolver->resolve_queues(); } - - - - return id; } @@ -187,6 +189,14 @@ void IP::erase_resolve_item(ResolverID p_id) { } +void IP::clear_cache(const String &p_hostname) { + + if (p_hostname.empty()) { + resolver->cache.clear(); + } else { + resolver->cache.erase(p_hostname); + } +}; Array IP::_get_local_addresses() const { @@ -208,6 +218,7 @@ void IP::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_resolve_item_address","id"),&IP::get_resolve_item_address); ObjectTypeDB::bind_method(_MD("erase_resolve_item","id"),&IP::erase_resolve_item); ObjectTypeDB::bind_method(_MD("get_local_addresses"),&IP::_get_local_addresses); + ObjectTypeDB::bind_method(_MD("clear_cache"),&IP::clear_cache, DEFVAL("")); BIND_CONSTANT( RESOLVER_STATUS_NONE ); BIND_CONSTANT( RESOLVER_STATUS_WAITING ); diff --git a/core/io/ip.h b/core/io/ip.h index 38c86e7ba3..742dd0e740 100644 --- a/core/io/ip.h +++ b/core/io/ip.h @@ -48,6 +48,14 @@ public: RESOLVER_STATUS_ERROR, }; + enum AddressType { + + ADDRESS_IPV4 = 1, + ADDRESS_IPV6 = 2, + + ADDRESS_ANY = 3, + }; + enum { RESOLVER_MAX_QUERIES = 32, RESOLVER_INVALID_ID=-1 @@ -65,7 +73,7 @@ protected: static IP*singleton; static void _bind_methods(); - virtual IP_Address _resolve_hostname(const String& p_hostname)=0; + virtual IP_Address _resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY)=0; Array _get_local_addresses() const; static IP* (*_create)(); @@ -73,14 +81,16 @@ public: - IP_Address resolve_hostname(const String& p_hostname); + IP_Address resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY); // async resolver hostname - ResolverID resolve_hostname_queue_item(const String& p_hostname); + ResolverID resolve_hostname_queue_item(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::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=0; void erase_resolve_item(ResolverID p_id); + void clear_cache(const String& p_hostname = ""); + static IP* get_singleton(); static IP* create(); diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 7a51bce7c6..9887cd132b 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -32,29 +32,191 @@ IP_Address::operator Variant() const { return operator String(); }*/ + +#include <string.h> +#include <stdio.h> + IP_Address::operator String() const { - return itos(field[0])+"."+itos(field[1])+"."+itos(field[2])+"."+itos(field[3]); + if (type == TYPE_NONE) + return "0.0.0.0"; + if (type == TYPE_IPV4) + return itos(field8[0])+"."+itos(field8[1])+"."+itos(field8[2])+"."+itos(field8[3]); + else { + String ret; + for (int i=0; i<8; i++) { + if (i > 0) + ret = ret + ":"; + uint16_t num = (field8[i*2] << 8) + field8[i*2+1]; + ret = ret + String::num_int64(num, 16); + }; + + return ret; + }; } -IP_Address::IP_Address(const String& p_string) { +static void _parse_hex(const String& p_string, int p_start, uint8_t* p_dst) { + + uint16_t ret = 0; + for (int i=p_start; i<p_start + 4; i++) { + + if (i >= p_string.length()) { + break; + }; + + int n = 0; + CharType c = p_string[i]; + if (c >= '0' && c <= '9') { + + n = c - '0'; + } else if (c >= 'a' && c <= 'f') { + n = 10 + (c - 'a'); + } else if (c >= 'A' && c <= 'F') { + n = 10 + (c - 'A'); + } else if (c == ':') { + break; + } else { + ERR_EXPLAIN("Invalid character in ipv6 address: " + p_string); + ERR_FAIL(); + }; + ret = ret << 4; + ret += n; + }; + + p_dst[0] = ret >> 8; + p_dst[1] = ret & 0xff; +}; + +void IP_Address::_parse_ipv6(const String& p_string) { + + static const int parts_total = 8; + int parts[parts_total] = {0}; + int parts_count = 0; + bool part_found = false; + bool part_skip = false; + bool part_ipv4 = false; + int parts_idx = 0; + + for (int i=0; i<p_string.length(); i++) { + + CharType c = p_string[i]; + if (c == ':') { + + if (i == 0) { + continue; // next must be a ":" + }; + if (!part_found) { + part_skip = true; + parts[parts_idx++] = -1; + }; + part_found = false; + } else if (c == '.') { + + part_ipv4 = true; + + } else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { + if (!part_found) { + parts[parts_idx++] = i; + part_found = true; + ++parts_count; + }; + } else { + + ERR_EXPLAIN("Invalid character in IPv6 address: " + p_string); + ERR_FAIL(); + }; + }; + + int parts_extra = 0; + if (part_skip) { + parts_extra = parts_total - parts_count; + }; + + int idx = 0; + for (int i=0; i<parts_idx; i++) { - host=0; - int slices = p_string.get_slice_count("."); + if (parts[i] == -1) { + + for (int j=0; j<parts_extra; j++) { + field16[idx++] = 0; + }; + continue; + }; + + if (part_ipv4 && i == parts_idx - 1) { + _parse_ipv4(p_string, parts[i], (uint8_t*)&field16[idx]); // should be the last one + } else { + _parse_hex(p_string, parts[i], (uint8_t*)&(field16[idx++])); + }; + }; + +}; + +void IP_Address::_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); + } else { + ip = p_string; + }; + + int slices = ip.get_slice_count("."); if (slices!=4) { - ERR_EXPLAIN("Invalid IP Address String: "+p_string); + ERR_EXPLAIN("Invalid IP Address String: "+ip); ERR_FAIL(); } for(int i=0;i<4;i++) { - - field[i]=p_string.get_slicec('.',i).to_int(); + p_ret[i]=ip.get_slicec('.',i).to_int(); } +}; + +void IP_Address::clear() { + + memset(&field8[0], 0, sizeof(field8)); +}; + +IP_Address::IP_Address(const String& p_string) { + + clear(); + if (p_string.find(":") >= 0) { + + _parse_ipv6(p_string); + type = TYPE_IPV6; + } else { + + _parse_ipv4(p_string, 0, &field8[0]); + type = TYPE_IPV4; + }; } -IP_Address::IP_Address(uint8_t p_a,uint8_t p_b,uint8_t p_c,uint8_t p_d) { +_FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) { + + p_dst[0] = (p_n >> 24) & 0xff; + p_dst[1] = (p_n >> 16) & 0xff; + p_dst[2] = (p_n >> 8) & 0xff; + 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, IP_Address::AddrType p_type) { + + type = p_type; + memset(&field8[0], 0, sizeof(field8)); + if (p_type == TYPE_IPV4) { + field8[0]=p_a; + field8[1]=p_b; + field8[2]=p_c; + field8[3]=p_d; + } else if (type == TYPE_IPV6) { + + _32_to_buf(&field8[0], p_a); + _32_to_buf(&field8[4], p_b); + _32_to_buf(&field8[8], p_c); + _32_to_buf(&field8[12], p_d); + } else { + type = TYPE_NONE; + ERR_EXPLAIN("Invalid type specified for IP_Address (use TYPE_IPV4 or TYPE_IPV6"); + ERR_FAIL(); + }; - field[0]=p_a; - field[1]=p_b; - field[2]=p_c; - field[3]=p_d; } diff --git a/core/io/ip_address.h b/core/io/ip_address.h index 1292311729..fe13d70611 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -33,22 +33,48 @@ struct IP_Address { +public: + enum AddrType { + TYPE_NONE = 0, + TYPE_IPV4 = 1, + TYPE_IPV6 = 2, + + TYPE_ANY = 3, + }; + + AddrType type; + union { - uint8_t field[4]; - uint32_t host; + uint8_t field8[16]; + uint16_t field16[8]; + uint32_t field32[4]; }; +protected: + void _parse_ipv6(const String& p_string); + void _parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret); + +public: //operator Variant() const; bool operator==(const IP_Address& p_ip) const { - return host==p_ip.host; + for (int i=0; i<4; i++) + if (field32[i] != p_ip.field32[i]) + return false; + return true; } bool operator!=(const IP_Address& p_ip) const { - return host!=p_ip.host; + for (int i=0; i<4; i++) + if (field32[i] != p_ip.field32[i]) + return true; + return false; } + + void clear(); + operator String() const; IP_Address(const String& p_string); - IP_Address(uint8_t p_a,uint8_t p_b,uint8_t p_c,uint8_t p_d); - IP_Address() { host=0; } + IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, AddrType p_type=TYPE_IPV4); + IP_Address() { clear(); type=TYPE_NONE; } }; diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index efc619e414..018dc77d91 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -29,14 +29,9 @@ #include "packet_peer_udp.h" #include "io/ip.h" - PacketPeerUDP* (*PacketPeerUDP::_create)()=NULL; -int PacketPeerUDP::_get_packet_address() const { - - IP_Address ip = get_packet_address(); - return ip.host; -} +VARIANT_ENUM_CAST(IP_Address::AddrType); String PacketPeerUDP::_get_packet_ip() const { @@ -65,7 +60,7 @@ void PacketPeerUDP::_bind_methods() { ObjectTypeDB::bind_method(_MD("wait:Error"),&PacketPeerUDP::wait); ObjectTypeDB::bind_method(_MD("is_listening"),&PacketPeerUDP::is_listening); ObjectTypeDB::bind_method(_MD("get_packet_ip"),&PacketPeerUDP::_get_packet_ip); - ObjectTypeDB::bind_method(_MD("get_packet_address"),&PacketPeerUDP::_get_packet_address); + //ObjectTypeDB::bind_method(_MD("get_packet_address"),&PacketPeerUDP::_get_packet_address); ObjectTypeDB::bind_method(_MD("get_packet_port"),&PacketPeerUDP::get_packet_port); ObjectTypeDB::bind_method(_MD("set_send_address","host","port"),&PacketPeerUDP::_set_send_address); diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 70d92834fc..c0806a9e6a 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -40,14 +40,13 @@ protected: static PacketPeerUDP* (*_create)(); static void _bind_methods(); - int _get_packet_address() const; String _get_packet_ip() const; virtual Error _set_send_address(const String& p_address,int p_port); public: - virtual Error listen(int p_port,int p_recv_buffer_size=65536)=0; + virtual Error listen(int p_port, IP_Address::AddrType p_address_type = IP_Address::TYPE_IPV4, int p_recv_buffer_size=65536)=0; virtual void close()=0; virtual Error wait()=0; virtual bool is_listening() const=0; diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 274d20a48a..53d6e900f3 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -30,6 +30,8 @@ TCP_Server* (*TCP_Server::_create)()=NULL; +VARIANT_ENUM_CAST(IP_Address::AddrType); + Ref<TCP_Server> TCP_Server::create_ref() { if (!_create) @@ -44,19 +46,19 @@ TCP_Server* TCP_Server::create() { return _create(); } -Error TCP_Server::_listen(uint16_t p_port,DVector<String> p_accepted_hosts) { +Error TCP_Server::_listen(uint16_t p_port, IP_Address::AddrType p_type, DVector<String> p_accepted_hosts) { List<String> hosts; for(int i=0;i<p_accepted_hosts.size();i++) hosts.push_back(p_accepted_hosts.get(i)); - return listen(p_port,hosts.size()?&hosts:NULL); + return listen(p_port,p_type, hosts.size()?&hosts:NULL); } void TCP_Server::_bind_methods() { - ObjectTypeDB::bind_method(_MD("listen","port","accepted_hosts"),&TCP_Server::_listen,DEFVAL(DVector<String>())); + ObjectTypeDB::bind_method(_MD("listen","port","accepted_hosts"),&TCP_Server::_listen,DEFVAL(IP_Address::TYPE_IPV4), DEFVAL(DVector<String>())); ObjectTypeDB::bind_method(_MD("is_connection_available"),&TCP_Server::is_connection_available); ObjectTypeDB::bind_method(_MD("take_connection"),&TCP_Server::take_connection); ObjectTypeDB::bind_method(_MD("stop"),&TCP_Server::stop); diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index 512a7e640a..883a3ef2f6 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -41,11 +41,11 @@ protected: static TCP_Server* (*_create)(); //bind helper - Error _listen(uint16_t p_port,DVector<String> p_accepted_hosts=DVector<String>()); + Error _listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4 ,DVector<String> p_accepted_hosts=DVector<String>()); static void _bind_methods(); public: - virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL)=0; + virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4, const List<String> *p_accepted_hosts=NULL)=0; virtual bool is_connection_available() const=0; virtual Ref<StreamPeerTCP> take_connection()=0; diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 64615fe6b4..46c0218707 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -41,37 +41,16 @@ static uint32_t Q[4096]; #endif uint32_t Math::rand_from_seed(uint32_t *seed) { - -#if 1 - uint32_t k; - uint32_t s = (*seed); - if (s == 0) - s = 0x12345987; - k = s / 127773; - s = 16807 * (s - k * 127773) - 2836 * k; -// if (s < 0) -// s += 2147483647; - (*seed) = s; - return (s & Math::RANDOM_MAX); -#else - *seed = *seed * 1103515245 + 12345; - return (*seed % ((unsigned int)RANDOM_MAX + 1)); -#endif + // Xorshift31 PRNG + if ( *seed == 0 ) *seed = Math::RANDOM_MAX; + (*seed) ^= (*seed) << 13; + (*seed) ^= (*seed) >> 17; + (*seed) ^= (*seed) << 5; + return (*seed) & Math::RANDOM_MAX; } void Math::seed(uint32_t x) { -#if 0 - int i; - - Q[0] = x; - Q[1] = x + PHI; - Q[2] = x + PHI + PHI; - - for (i = 3; i < 4096; i++) - Q[i] = Q[i - 3] ^ Q[i - 2] ^ PHI ^ i; -#else default_seed=x; -#endif } void Math::randomize() { @@ -82,12 +61,12 @@ void Math::randomize() { uint32_t Math::rand() { - return rand_from_seed(&default_seed)&0x7FFFFFFF; + return rand_from_seed(&default_seed); } double Math::randf() { - return (double)rand() / (double)RANDOM_MAX; + return (double)rand() / (double)Math::RANDOM_MAX; } double Math::sin(double p_x) { diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index 9982767be1..7350be824a 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -50,7 +50,8 @@ bool InputEvent::operator==(const InputEvent &p_event) const { case MOUSE_MOTION: return mouse_motion.x == p_event.mouse_motion.x && mouse_motion.y == p_event.mouse_motion.y - && mouse_motion.relative_x == p_event.mouse_motion.relative_y + && mouse_motion.relative_x == p_event.mouse_motion.relative_x + && mouse_motion.relative_y == p_event.mouse_motion.relative_y && mouse_motion.button_mask == p_event.mouse_motion.button_mask && key.mod == p_event.key.mod; case MOUSE_BUTTON: diff --git a/core/translation.cpp b/core/translation.cpp index 4592d00598..4d81073fe6 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -779,6 +779,11 @@ Vector<String> TranslationServer::get_all_locale_names(){ } +static String get_trimmed_locale(const String& p_locale) { + + return p_locale.substr(0,2); +} + static bool is_valid_locale(const String& p_locale) { const char **ptr=locale_list; @@ -839,9 +844,20 @@ void Translation::_set_messages(const DVector<String>& p_messages){ void Translation::set_locale(const String& p_locale) { - ERR_EXPLAIN("Invalid Locale: "+p_locale); - ERR_FAIL_COND(!is_valid_locale(p_locale)); - locale=p_locale; + // replaces '-' with '_' for macOS Sierra-style locales + String univ_locale = p_locale.replace("-", "_"); + + if(!is_valid_locale(univ_locale)) { + String trimmed_locale = get_trimmed_locale(univ_locale); + + ERR_EXPLAIN("Invalid Locale: "+trimmed_locale); + ERR_FAIL_COND(!is_valid_locale(trimmed_locale)); + + locale=trimmed_locale; + } + else { + locale=univ_locale; + } } void Translation::add_message( const StringName& p_src_text, const StringName& p_xlated_text ) { @@ -906,9 +922,20 @@ Translation::Translation() { void TranslationServer::set_locale(const String& p_locale) { - ERR_EXPLAIN("Invalid Locale: "+p_locale); - ERR_FAIL_COND(!is_valid_locale(p_locale)); - locale=p_locale; + // replaces '-' with '_' for macOS Sierra-style locales + String univ_locale = p_locale.replace("-", "_"); + + if(!is_valid_locale(univ_locale)) { + String trimmed_locale = get_trimmed_locale(univ_locale); + + ERR_EXPLAIN("Invalid Locale: "+trimmed_locale); + ERR_FAIL_COND(!is_valid_locale(trimmed_locale)); + + locale=trimmed_locale; + } + else { + locale=univ_locale; + } } String TranslationServer::get_locale() const { diff --git a/core/ustring.cpp b/core/ustring.cpp index 2e907381f7..f9c10615b3 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -1543,11 +1543,11 @@ String::String(const StrRange& p_range) { copy_from(p_range.c_str,p_range.len); } -int String::hex_to_int() const { +int String::hex_to_int(bool p_with_prefix) const { int l = length(); - if (l<3) - return 0; + if (p_with_prefix && l<3) + return 0; const CharType *s=ptr(); @@ -1556,15 +1556,16 @@ int String::hex_to_int() const { if (sign<0) { s++; l--; - if (l<2) + if (p_with_prefix && l<2) return 0; } - if (s[0]!='0' || s[1]!='x') - return 0; - - s+=2; - l-=2; + if (p_with_prefix) { + if (s[0]!='0' || s[1]!='x') + return 0; + s+=2; + l-=2; + }; int hex=0; @@ -3510,6 +3511,36 @@ bool String::is_valid_integer() const { } +bool String::is_valid_hex_number(bool p_with_prefix) const { + + int from = 0; + int len = length(); + + if (len!=1 && (operator[](0)=='+' || operator[](0)=='-')) + from++; + + if (p_with_prefix) { + + if (len < 2) + return false; + if (operator[](from) != '0' || operator[](from+1) != 'x') { + return false; + }; + from += 2; + }; + + for (int i=from; i<len; i++) { + + CharType c = operator[](i); + if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) + continue; + return false; + }; + + return true; +}; + + bool String::is_valid_float() const { int len = length(); @@ -3646,20 +3677,41 @@ bool String::is_valid_html_color() const { } + bool String::is_valid_ip_address() const { - Vector<String> ip = split("."); - if (ip.size()!=4) - return false; - for(int i=0;i<ip.size();i++) { + if (find(":") >= 0) { - String n = ip[i]; - if (!n.is_valid_integer()) - return false; - int val = n.to_int(); - if (val<0 || val>255) + Vector<String> ip = split(":"); + for (int i=0; i<ip.size(); i++) { + + String n = ip[i]; + if (n.empty()) + continue; + if (n.is_valid_hex_number(false)) { + int nint = n.hex_to_int(false); + if (nint < 0 || nint > 0xffff) + return false; + continue; + }; + if (!n.is_valid_ip_address()) + return false; + }; + + } else { + Vector<String> ip = split("."); + if (ip.size()!=4) return false; - } + for(int i=0;i<ip.size();i++) { + + String n = ip[i]; + if (!n.is_valid_integer()) + return false; + int val = n.to_int(); + if (val<0 || val>255) + return false; + } + }; return true; } diff --git a/core/ustring.h b/core/ustring.h index 09d13a9e64..452f252857 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -144,7 +144,7 @@ public: bool is_numeric() const; double to_double() const; float to_float() const; - int hex_to_int() const; + int hex_to_int(bool p_with_prefix = true) const; int to_int() const; int64_t to_int64() const; @@ -226,6 +226,7 @@ public: bool is_valid_identifier() const; bool is_valid_integer() const; bool is_valid_float() const; + bool is_valid_hex_number(bool p_with_prefix) const; bool is_valid_html_color() const; bool is_valid_ip_address() const; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 51cd4c2399..9b6fa27cf4 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -1820,6 +1820,11 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl _VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_NEAREST",Image::INTERPOLATE_NEAREST); _VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_BILINEAR",Image::INTERPOLATE_BILINEAR); _VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_CUBIC",Image::INTERPOLATE_CUBIC); + + _VariantCall::add_constant(Variant::INT, "IP_TYPE_NONE", IP_Address::TYPE_NONE); + _VariantCall::add_constant(Variant::INT, "IP_TYPE_IPV4", IP_Address::TYPE_IPV4); + _VariantCall::add_constant(Variant::INT, "IP_TYPE_IPV6", IP_Address::TYPE_IPV6); + _VariantCall::add_constant(Variant::INT, "IP_TYPE_ANY", IP_Address::TYPE_ANY); } void unregister_variant_methods() { diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 4e0ba53f48..5eb021f6c0 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -31871,6 +31871,8 @@ RayCast can ignore some objects by adding them to the exception list via [code]add_exception[/code], setting proper filtering with layers, or by filtering object types with type masks. Only enabled raycasts will be able to query the space and report collisions! + + RayCast calculates intersection every fixed frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between fixed frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast. </description> <methods> <method name="add_exception"> @@ -31891,6 +31893,11 @@ Removes all collision exception for this ray. </description> </method> + <method name="force_raycast_update"> + <description> + Updates the collision information in case if this object's properties changed during the current frame (for example position, rotation or the cast_point). Note, [code]set_enabled[/code] is not required for this to work. + </description> + </method> <method name="get_cast_to" qualifiers="const"> <return type="Vector3"> </return> @@ -32009,6 +32016,8 @@ RayCast2D can ignore some objects by adding them to the exception list via [code]add_exception[/code], setting proper filtering with layers, or by filtering object types with type masks. Only enabled raycasts will be able to query the space and report collisions! + + RayCast2D calculates intersection every fixed frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between fixed frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast. </description> <methods> <method name="add_exception"> @@ -32029,6 +32038,11 @@ Removes all collision exception for this ray. </description> </method> + <method name="force_raycast_update"> + <description> + Updates the collision information in case if this object's properties changed during the current frame (for example position, rotation or the cast_point). Note, [code]set_enabled[/code] is not required for this to work. + </description> + </method> <method name="get_cast_to" qualifiers="const"> <return type="Vector2"> </return> diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 08a8c19583..d6d1be3395 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -30,6 +30,7 @@ #if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) +#include <string.h> #ifdef WINDOWS_ENABLED #ifdef WINRT_ENABLED @@ -62,16 +63,51 @@ #endif #endif -IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { +static IP_Address _sockaddr2ip(struct sockaddr* p_addr) { - struct hostent *he; - if ((he=gethostbyname(p_hostname.utf8().get_data())) == NULL) { // get the host info - ERR_PRINT("gethostbyname failed!"); - return IP_Address(); - } IP_Address ip; + if (p_addr->sa_family == AF_INET) { + struct sockaddr_in* addr = (struct sockaddr_in*)p_addr; + ip.field32[0] = *((unsigned long*)&addr->sin_addr); + ip.type = IP_Address::TYPE_IPV4; + } else { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + for (int i=0; i<16; i++) + ip.field8[i] = addr6->sin6_addr.s6_addr[i]; + ip.type = IP_Address::TYPE_IPV6; + }; + + return ip; +}; + +IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) { - ip.host= *((unsigned long*)he->h_addr); + struct addrinfo hints; + struct addrinfo* result; + + memset(&hints, 0, sizeof(struct addrinfo)); + if (p_type == IP_Address::TYPE_IPV4) { + hints.ai_family = AF_INET; + } else if (p_type == IP_Address::TYPE_IPV6) { + hints.ai_family = AF_INET6; + } else { + hints.ai_family = AF_UNSPEC; + }; + + int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result); + if (s != 0) { + ERR_PRINT("getaddrinfo failed!"); + return IP_Address(); + }; + + if (result == NULL || result->ai_addr == NULL) { + ERR_PRINT("Invalid response from getaddrinfo"); + return IP_Address(); + }; + + IP_Address ip = _sockaddr2ip(result->ai_addr); + + freeaddrinfo(result); return ip; @@ -90,10 +126,9 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { for (int i = 0; i < hostnames->Size; i++) { - if (hostnames->GetAt(i)->Type == HostNameType::Ipv4 && hostnames->GetAt(i)->IPInformation != nullptr) { + if (hostnames->GetAt(i)->Type == HostNameType::Ipv4 || hostnames->GetAt(i)->Type == HostNameType::Ipv6 && hostnames->GetAt(i)->IPInformation != nullptr) { r_addresses->push_back(IP_Address(String(hostnames->GetAt(i)->CanonicalName->Data()))); - } } @@ -108,7 +143,7 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { while (true) { addrs = (IP_ADAPTER_ADDRESSES*)memalloc(buf_size); - int err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST | + int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, @@ -134,14 +169,23 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress; while (address != NULL) { - char addr_chr[INET_ADDRSTRLEN]; - SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr); - IP_Address ip; - ip.host= *((unsigned long*)&ipv4->sin_addr); + if (address->Address.lpSockaddr->sa_family == AF_INET) { + + SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr); + + ip.field32[0] = *((unsigned long*)&ipv4->sin_addr); + ip.type = IP_Address::TYPE_IPV4; + } else { // ipv6 + + SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr); + for (int i=0; i<16; i++) { + ip.field8[i] = ipv6->sin6_addr.s6_addr[i]; + }; + ip.type = IP_Address::TYPE_IPV6; + }; - //inet_ntop(AF_INET, &ipv4->sin_addr, addr_chr, INET_ADDRSTRLEN); r_addresses->push_back(ip); @@ -167,20 +211,9 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { if (!ifa->ifa_addr) continue; - if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4 - // is a valid IP4 Address - IP_Address ip; - ip.host= *((unsigned long*)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr); - - r_addresses->push_back(ip); - }/* else if (ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6 - // is a valid IP6 Address - tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; - char addressBuffer[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); - printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); - } */ + IP_Address ip = _sockaddr2ip(ifa->ifa_addr); + r_addresses->push_back(ip); } if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct); diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index c0034c9a3a..d198a330e7 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -36,7 +36,7 @@ class IP_Unix : public IP { OBJ_TYPE(IP_Unix, IP); - virtual IP_Address _resolve_hostname(const String& p_hostname); + virtual IP_Address _resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type); static IP* _create_unix(); public: diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 0201a85651..0b172b6a51 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -54,6 +54,7 @@ #include <arpa/inet.h> #endif +#include "drivers/unix/socket_helpers.h" int PacketPeerUDPPosix::get_available_packet_count() const { @@ -73,7 +74,15 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size return ERR_UNAVAILABLE; uint32_t size; - rb.read((uint8_t*)&packet_ip.host,4,true); + uint8_t type; + rb.read(&type, 1, true); + if (type == IP_Address::TYPE_IPV4) { + rb.read((uint8_t*)&packet_ip.field8,4,true); + packet_ip.type = IP_Address::TYPE_IPV4; + } else { + rb.read((uint8_t*)&packet_ip.field8,16,true); + packet_ip.type = IP_Address::TYPE_IPV6; + }; rb.read((uint8_t*)&packet_port,4,true); rb.read((uint8_t*)&size,4,true); rb.read(packet_buffer,size,true); @@ -85,17 +94,17 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size } Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ - int sock = _get_socket(); + ERR_FAIL_COND_V(peer_addr.type == IP_Address::TYPE_NONE, ERR_UNCONFIGURED); + + int sock = _get_socket(peer_addr.type); ERR_FAIL_COND_V( sock == -1, FAILED ); - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(peer_port); - addr.sin_addr = *((struct in_addr*)&peer_addr.host); + struct sockaddr_storage addr; + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); errno = 0; int err; - while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, addr_size)) != p_buffer_size) { if (errno != EAGAIN) { return FAILED; @@ -110,17 +119,19 @@ int PacketPeerUDPPosix::get_max_packet_size() const{ return 512; // uhm maybe not } -Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size){ +Error PacketPeerUDPPosix::listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size) { + + ERR_FAIL_COND_V(p_address_type != IP_Address::TYPE_IPV4 && p_address_type != IP_Address::TYPE_IPV6, ERR_INVALID_PARAMETER); close(); - int sock = _get_socket(); + int sock = _get_socket(p_address_type); if (sock == -1 ) return ERR_CANT_CREATE; - sockaddr_in addr = {0}; - addr.sin_family = AF_INET; - addr.sin_port = htons(p_port); - addr.sin_addr.s_addr = INADDR_ANY; - if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + + sockaddr_storage addr = {0}; + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); + + if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); return ERR_UNAVAILABLE; } @@ -145,16 +156,41 @@ Error PacketPeerUDPPosix::wait() { Error PacketPeerUDPPosix::_poll(bool p_wait) { - struct sockaddr_in from = {0}; - socklen_t len = sizeof(struct sockaddr_in); + struct sockaddr_storage from = {0}; + socklen_t len = sizeof(struct sockaddr_storage); int ret; while ( (ret = recvfrom(sockfd, recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-12, 0)), p_wait?0:MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) { - rb.write((uint8_t*)&from.sin_addr, 4); - uint32_t port = ntohs(from.sin_port); + + uint32_t port = 0; + + if (from.ss_family == AF_INET) { + uint8_t type = (uint8_t)IP_Address::TYPE_IPV4; + rb.write(&type, 1); + struct sockaddr_in* sin_from = (struct sockaddr_in*)&from; + rb.write((uint8_t*)&sin_from->sin_addr, 4); + port = ntohs(sin_from->sin_port); + + } else if (from.ss_family == AF_INET6) { + + uint8_t type = (uint8_t)IP_Address::TYPE_IPV6; + rb.write(&type, 1); + + struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from; + rb.write((uint8_t*)&s6_from->sin6_addr, 16); + + port = ntohs(s6_from->sin6_port); + + } else { + // WARN_PRINT("Ignoring packet with unknown address family"); + uint8_t type = (uint8_t)IP_Address::TYPE_NONE; + rb.write(&type, 1); + }; + rb.write((uint8_t*)&port, 4); rb.write((uint8_t*)&ret, 4); rb.write(recv_buffer, ret); - len = sizeof(struct sockaddr_in); + + len = sizeof(struct sockaddr_storage); ++queue_count; }; @@ -182,12 +218,14 @@ int PacketPeerUDPPosix::get_packet_port() const{ return packet_port; } -int PacketPeerUDPPosix::_get_socket() { +int PacketPeerUDPPosix::_get_socket(IP_Address::AddrType p_type) { if (sockfd != -1) return sockfd; - sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + + sockfd = socket(family, SOCK_DGRAM, IPPROTO_UDP); ERR_FAIL_COND_V( sockfd == -1, -1 ); //fcntl(sockfd, F_SETFL, O_NONBLOCK); diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h index a11282e5d6..13b6969e53 100644 --- a/drivers/unix/packet_peer_udp_posix.h +++ b/drivers/unix/packet_peer_udp_posix.h @@ -44,15 +44,15 @@ class PacketPeerUDPPosix : public PacketPeerUDP { mutable RingBuffer<uint8_t> rb; uint8_t recv_buffer[PACKET_BUFFER_SIZE]; mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; - IP_Address packet_ip; - int packet_port; + mutable IP_Address packet_ip; + mutable int packet_port; mutable int queue_count; int sockfd; IP_Address peer_addr; int peer_port; - _FORCE_INLINE_ int _get_socket(); + _FORCE_INLINE_ int _get_socket(IP_Address::AddrType p_type); static PacketPeerUDP* _create(); virtual Error _poll(bool p_block); @@ -65,7 +65,7 @@ public: virtual int get_max_packet_size() const; - virtual Error listen(int p_port,int p_recv_buffer_size=65536); + virtual Error listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size=65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h new file mode 100644 index 0000000000..4ee40e3d3d --- /dev/null +++ b/drivers/unix/socket_helpers.h @@ -0,0 +1,70 @@ +#ifndef SOCKET_HELPERS_H +#define SOCKET_HELPERS_H + +#include <string.h> + +// helpers for sockaddr -> IP_Address and back, should work for posix and winsock. All implementations should use this + +static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port) { + + memset(p_addr, 0, sizeof(struct sockaddr_storage)); + if (p_ip.type == IP_Address::TYPE_IPV6) { + + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(p_port); + copymem(&addr6->sin6_addr.s6_addr, p_ip.field8, 16); + return sizeof(sockaddr_in6); + + } else { + + struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; + addr4->sin_family = AF_INET; // host byte order + addr4->sin_port = htons(p_port); // short, network byte order + addr4->sin_addr = *((struct in_addr*)&p_ip.field32[0]); + return sizeof(sockaddr_in); + }; +}; + +static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP_Address::AddrType p_address_type, const List<String> *p_accepted_hosts) { + + memset(p_addr, 0, sizeof(struct sockaddr_storage)); + if (p_address_type == IP_Address::TYPE_IPV4) { + struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(p_port); + addr4->sin_addr.s_addr = INADDR_ANY; // TODO: use accepted hosts list + return sizeof(sockaddr_in); + } else { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(p_port); + addr6->sin6_addr = in6addr_any; // TODO: use accepted hosts list + return sizeof(sockaddr_in6); + }; +}; + +static void _set_ip_addr_port(IP_Address& r_ip, int& r_port, struct sockaddr_storage* p_addr) { + + if (p_addr->ss_family == AF_INET) { + r_ip.type = IP_Address::TYPE_IPV4; + + struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; + r_ip.field32[0] = (uint32_t)addr4->sin_addr.s_addr; + + r_port = ntohs(addr4->sin_port); + + } else if (p_addr->ss_family == AF_INET6) { + + r_ip.type = IP_Address::TYPE_IPV6; + + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + copymem(&addr6->sin6_addr.s6_addr, r_ip.field8, 16); + + r_port = ntohs(addr6->sin6_port); + }; +}; + + +#endif diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 45a4b934c1..f2915b0a16 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -61,13 +61,7 @@ #define MSG_NOSIGNAL SO_NOSIGPIPE #endif -static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) { - - their_addr.sin_family = AF_INET; // host byte order - their_addr.sin_port = htons(p_port); // short, network byte order - their_addr.sin_addr = *((struct in_addr*)&p_host.host); - memset(&(their_addr.sin_zero), '\0', 8); -}; +#include "drivers/unix/socket_helpers.h" StreamPeerTCP* StreamPeerTCPPosix::_create() { @@ -103,9 +97,10 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { _block(sockfd, false, true); }; - struct sockaddr_in their_addr; - set_addr_in(their_addr, peer_host, peer_port); - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) { + struct sockaddr_storage their_addr; + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port); + + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1) { if (errno == EISCONN) { status = STATUS_CONNECTED; @@ -140,9 +135,10 @@ void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port) Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { - ERR_FAIL_COND_V( p_host.host == 0, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER); - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + int family = p_host.type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + if ((sockfd = socket(family, SOCK_STREAM, 0)) == -1) { ERR_PRINT("Socket creation failed!"); disconnect(); //perror("socket"); @@ -156,11 +152,11 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { ioctl(sockfd, FIONBIO, &bval); #endif - struct sockaddr_in their_addr; - set_addr_in(their_addr, p_host, p_port); + struct sockaddr_storage their_addr; + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port); errno = 0; - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1 && errno != EINPROGRESS) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1 && errno != EINPROGRESS) { ERR_PRINT("Connection to remote host failed!"); disconnect(); diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index c67bb51334..05b739804c 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -55,6 +55,9 @@ #include <netinet/in.h> #include <sys/socket.h> #include <assert.h> + +#include "drivers/unix/socket_helpers.h" + TCP_Server* TCPServerPosix::_create() { return memnew(TCPServerPosix); @@ -65,10 +68,11 @@ void TCPServerPosix::make_default() { TCP_Server::_create = TCPServerPosix::_create; }; -Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_hosts) { +Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const List<String> *p_accepted_hosts) { int sockfd; - sockfd = socket(AF_INET, SOCK_STREAM, 0); + int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + sockfd = socket(family, SOCK_STREAM, 0); ERR_FAIL_COND_V(sockfd == -1, FAILED); #ifndef NO_FCNTL fcntl(sockfd, F_SETFL, O_NONBLOCK); @@ -82,13 +86,12 @@ Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_host WARN_PRINT("REUSEADDR failed!") } - struct sockaddr_in my_addr; - my_addr.sin_family = AF_INET; // host byte order - my_addr.sin_port = htons(p_port); // short, network byte order - my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts - memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); + struct sockaddr_storage addr; + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, p_accepted_hosts); + + // automatically fill with my IP TODO: use p_accepted_hosts - if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != -1) { + if (bind(sockfd, (struct sockaddr *)&addr, addr_size) != -1) { if (::listen(sockfd, 1) == -1) { @@ -136,9 +139,9 @@ Ref<StreamPeerTCP> TCPServerPosix::take_connection() { return Ref<StreamPeerTCP>(); }; - struct sockaddr_in their_addr; - socklen_t sin_size = sizeof(their_addr); - int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size); + struct sockaddr_storage their_addr; + socklen_t size = sizeof(their_addr); + int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &size); ERR_FAIL_COND_V(fd == -1, Ref<StreamPeerTCP>()); #ifndef NO_FCNTL fcntl(fd, F_SETFL, O_NONBLOCK); @@ -149,8 +152,11 @@ Ref<StreamPeerTCP> TCPServerPosix::take_connection() { Ref<StreamPeerTCPPosix> conn = memnew(StreamPeerTCPPosix); IP_Address ip; - ip.host = (uint32_t)their_addr.sin_addr.s_addr; - conn->set_socket(fd, ip, ntohs(their_addr.sin_port)); + + int port; + _set_ip_addr_port(ip, port, &their_addr); + + conn->set_socket(fd, ip, port); return conn; }; diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h index 570bcaab12..134ec494cb 100644 --- a/drivers/unix/tcp_server_posix.h +++ b/drivers/unix/tcp_server_posix.h @@ -40,7 +40,7 @@ class TCPServerPosix : public TCP_Server { public: - virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4, const List<String> *p_accepted_hosts=NULL); virtual bool is_connection_available() const; virtual Ref<StreamPeerTCP> take_connection(); diff --git a/methods.py b/methods.py index c4951c69bd..bd5409e3d4 100755 --- a/methods.py +++ b/methods.py @@ -1416,7 +1416,7 @@ def save_active_platforms(apnames,ap): logow.write(str) -def colored(sys,env): +def no_verbose(sys,env): #If the output is not a terminal, do nothing if not sys.stdout.isatty(): @@ -1516,11 +1516,6 @@ def detect_visual_c_compiler_version(tools_env): return vc_chosen_compiler_str -def msvc_is_detected() : - # looks for VisualStudio env variable - # or for Visual C++ Build Tools (which is a standalone MSVC) - return os.getenv("VSINSTALLDIR") or os.getenv("VS100COMNTOOLS") or os.getenv("VS110COMNTOOLS") or os.getenv("VS120COMNTOOLS") or os.getenv("VS140COMNTOOLS"); - def precious_program(env, program, sources, **args): program = env.ProgramOriginal(program, sources, **args) diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index b4dfa9c62e..a82283591d 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -77,6 +77,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port, int p_in_bandwidth, int p_out_bandwidth){ ERR_FAIL_COND_V(active,ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(p_ip.type != IP_Address::TYPE_IPV4, ERR_INVALID_PARAMETER); host = enet_host_create (NULL /* create a client host */, 1 /* only allow 1 outgoing connection */, @@ -90,7 +91,7 @@ Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port _setup_compressor(); ENetAddress address; - address.host=p_ip.host; + address.host=p_ip.field32[0]; address.port=p_port; //enet_address_set_host (& address, "localhost"); @@ -149,7 +150,8 @@ void NetworkedMultiplayerENet::poll(){ } IP_Address ip; - ip.host=event.peer -> address.host; + ip.type = IP_Address::TYPE_IPV4; + ip.field32[0]=event.peer -> address.host; int *new_id = memnew( int ); *new_id = event.data; @@ -683,5 +685,6 @@ NetworkedMultiplayerENet::~NetworkedMultiplayerENet(){ // sets IP for ENet to bind when using create_server // if no IP is set, then ENet bind to ENET_HOST_ANY void NetworkedMultiplayerENet::set_bind_ip(const IP_Address& p_ip){ - bind_ip=p_ip.host; + ERR_FAIL_COND(p_ip.type != IP_Address::TYPE_IPV4); + bind_ip=p_ip.field32[0]; } diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index 2e2cbe7b29..b75b13551e 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -1005,12 +1005,12 @@ Error GDCompiler::_parse_block(CodeGen& codegen,const GDParser::BlockNode *p_blo switch(s->type) { case GDParser::Node::TYPE_NEWLINE: { - +#ifdef DEBUG_ENABLED const GDParser::NewLineNode *nl = static_cast<const GDParser::NewLineNode*>(s); codegen.opcodes.push_back(GDFunction::OPCODE_LINE); codegen.opcodes.push_back(nl->line); codegen.current_line=nl->line; - +#endif } break; case GDParser::Node::TYPE_CONTROL_FLOW: { // try subblocks @@ -1201,8 +1201,10 @@ Error GDCompiler::_parse_block(CodeGen& codegen,const GDParser::BlockNode *p_blo codegen.opcodes.push_back(ret); } break; case GDParser::Node::TYPE_BREAKPOINT: { +#ifdef DEBUG_ENABLED // try subblocks codegen.opcodes.push_back(GDFunction::OPCODE_BREAKPOINT); +#endif } break; case GDParser::Node::TYPE_LOCAL_VAR: { diff --git a/modules/openssl/SCsub b/modules/openssl/SCsub index 3cc6f21bd2..2327cf483c 100644 --- a/modules/openssl/SCsub +++ b/modules/openssl/SCsub @@ -671,7 +671,7 @@ if (env["openssl"] != "system"): # builtin # Workaround for compilation error with GCC/Clang when -Werror is too greedy (GH-4517) import os import methods - if not (os.name=="nt" and methods.msvc_is_detected()): # not Windows and not MSVC + if not (os.name=="nt" and os.getenv("VCINSTALLDIR")): # not Windows and not MSVC env_openssl.Append(CFLAGS = ["-Wno-error=implicit-function-declaration"]) diff --git a/platform/android/detect.py b/platform/android/detect.py index acf4ce412a..842036f986 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -131,7 +131,7 @@ def configure(env): gcc_path=gcc_path+"/darwin-x86_64/bin" env['SHLINKFLAGS'][1] = '-shared' env['SHLIBSUFFIX'] = '.so' - elif (os.platform.startswith('win')): + elif (sys.platform.startswith('win')): if (platform.machine().endswith('64')): gcc_path=gcc_path+"/windows-x86_64/bin" else: diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index de57d770c4..f934916aa2 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -195,8 +195,8 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t>& p_html, const St } CharString cs = strnew.utf8(); - p_html.resize(cs.size()); - for(int i=9;i<cs.size();i++) { + p_html.resize(cs.length()); + for(int i=9;i<cs.length();i++) { p_html[i]=cs[i]; } } diff --git a/platform/osx/detect.py b/platform/osx/detect.py index f8b2153aee..4e772e37eb 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -91,9 +91,6 @@ def configure(env): env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) env["CC"]="clang" env["LD"]="clang++" - if (env["colored"]=="yes"): - if sys.stdout.isatty(): - env.Append(CPPFLAGS=["-fcolor-diagnostics"]) import methods diff --git a/platform/server/detect.py b/platform/server/detect.py index 2f6fb00e0d..ce14100fd0 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -38,9 +38,6 @@ def configure(env): env["CC"]="clang" env["CXX"]="clang++" env["LD"]="clang++" - if (env["colored"]=="yes"): - if sys.stdout.isatty(): - env.Append(CXXFLAGS=["-fcolor-diagnostics"]) is64=sys.maxsize > 2**32 diff --git a/platform/windows/detect.py b/platform/windows/detect.py index a5b26930be..7ae0100762 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -1,16 +1,11 @@ # -# tested on | Windows native | Linux cross-compilation -# ----------------------------+-------------------+--------------------------- -# MSVS C++ 2010 Express | WORKS | n/a +# tested on | Windows native | Linux cross-compilation +# ----------------------------+-------------------+--------------------------- # Visual C++ Build Tools 2015 | WORKS | n/a -# Mingw-w64 | WORKS | WORKS -# Mingw-w32 | WORKS | WORKS -# MinGW | WORKS | untested -# -##### -# Notes about MSVS C++ : -# -# - MSVC2010-Express compiles to 32bits only. +# MSVS C++ 2010 Express | WORKS | n/a +# Mingw-w64 | WORKS | WORKS +# Mingw-w32 | WORKS | WORKS +# MinGW | WORKS | untested # ##### # Note about Visual C++ Build Tools : @@ -19,6 +14,11 @@ # http://landinghub.visualstudio.com/visual-cpp-build-tools # ##### +# Notes about MSVS C++ : +# +# - MSVC2010-Express compiles to 32bits only. +# +##### # Notes about Mingw-w64 and Mingw-w32 under Windows : # # - both can be installed using the official installer : @@ -109,7 +109,7 @@ def can_build(): if (os.name=="nt"): #building natively on windows! - if ( methods.msvc_is_detected() ): + if ( os.getenv("VCINSTALLDIR") ): return True else: print("\nMSVC not detected, attempting Mingw.") @@ -204,7 +204,7 @@ def configure(env): env.Append(CPPPATH=['#platform/windows']) env['is_mingw']=False - if (os.name=="nt" and methods.msvc_is_detected() ): + if (os.name=="nt" and os.getenv("VCINSTALLDIR") ): #build using visual studio env['ENV']['TMP'] = os.environ['TMP'] env.Append(CPPPATH=['#platform/windows/include']) diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 38e738a414..286f5fb0b7 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1366,13 +1366,16 @@ void OS_Windows::set_mouse_mode(MouseMode p_mode) { POINT pos = { (int) center.x, (int) center.y }; ClientToScreen(hWnd, &pos); SetCursorPos(pos.x, pos.y); - ShowCursor(false); } else { - ShowCursor(true); ReleaseCapture(); ClipCursor(NULL); } + if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) { + hCursor = SetCursor(NULL); + } else { + SetCursor(hCursor); + } } OS_Windows::MouseMode OS_Windows::get_mouse_mode() const{ diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 2c79365c08..b4cd60979c 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -29,6 +29,9 @@ #include "packet_peer_udp_winsock.h" #include <winsock2.h> +#include <ws2tcpip.h> + +#include "drivers/unix/socket_helpers.h" int PacketPeerUDPWinsock::get_available_packet_count() const { @@ -48,7 +51,15 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si return ERR_UNAVAILABLE; uint32_t size; - rb.read((uint8_t*)&packet_ip.host,4,true); + uint8_t type; + rb.read(&type, 1, true); + if (type == IP_Address::TYPE_IPV4) { + rb.read((uint8_t*)&packet_ip.field8,4,true); + packet_ip.type = IP_Address::TYPE_IPV4; + } else { + rb.read((uint8_t*)&packet_ip.field8,16,true); + packet_ip.type = IP_Address::TYPE_IPV6; + }; rb.read((uint8_t*)&packet_port,4,true); rb.read((uint8_t*)&size,4,true); rb.read(packet_buffer,size,true); @@ -60,19 +71,16 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si } Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size){ - int sock = _get_socket(); + int sock = _get_socket(peer_addr.type); ERR_FAIL_COND_V( sock == -1, FAILED ); - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(peer_port); - addr.sin_addr = *((struct in_addr*)&peer_addr.host); - + struct sockaddr_storage addr; + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); _set_blocking(true); errno = 0; int err; - while ( (err = sendto(sock, (const char*)p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + while ( (err = sendto(sock, (const char*)p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, addr_size)) != p_buffer_size) { if (WSAGetLastError() != WSAEWOULDBLOCK) { return FAILED; @@ -104,17 +112,17 @@ void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) { }; } -Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size){ +Error PacketPeerUDPWinsock::listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size) { close(); - int sock = _get_socket(); + int sock = _get_socket(p_address_type); if (sock == -1 ) return ERR_CANT_CREATE; - sockaddr_in addr = {0}; - addr.sin_family = AF_INET; - addr.sin_port = htons(p_port); - addr.sin_addr.s_addr = INADDR_ANY; - if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + + struct sockaddr_storage addr = {0}; + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); + + if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); return ERR_UNAVAILABLE; } @@ -146,17 +154,41 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) { _set_blocking(p_wait); - struct sockaddr_in from = {0}; - int len = sizeof(struct sockaddr_in); + struct sockaddr_storage from = {0}; + int len = sizeof(struct sockaddr_storage); int ret; while ( (ret = recvfrom(sockfd, (char*)recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-12, 0)), 0, (struct sockaddr*)&from, &len)) > 0) { - rb.write((uint8_t*)&from.sin_addr, 4); - uint32_t port = ntohs(from.sin_port); + + uint32_t port = 0; + + if (from.ss_family == AF_INET) { + uint8_t type = (uint8_t)IP_Address::TYPE_IPV4; + rb.write(&type, 1); + struct sockaddr_in* sin_from = (struct sockaddr_in*)&from; + rb.write((uint8_t*)&sin_from->sin_addr, 4); + port = ntohs(sin_from->sin_port); + + } else if (from.ss_family == AF_INET6) { + + uint8_t type = (uint8_t)IP_Address::TYPE_IPV6; + rb.write(&type, 1); + + struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from; + rb.write((uint8_t*)&s6_from->sin6_addr, 16); + + port = ntohs(s6_from->sin6_port); + + } else { + // WARN_PRINT("Ignoring packet with unknown address family"); + uint8_t type = (uint8_t)IP_Address::TYPE_NONE; + rb.write(&type, 1); + }; + rb.write((uint8_t*)&port, 4); rb.write((uint8_t*)&ret, 4); rb.write(recv_buffer, ret); - len = sizeof(struct sockaddr_in); + len = sizeof(struct sockaddr_storage); ++queue_count; }; @@ -202,12 +234,14 @@ int PacketPeerUDPWinsock::get_packet_port() const{ return packet_port; } -int PacketPeerUDPWinsock::_get_socket() { +int PacketPeerUDPWinsock::_get_socket(IP_Address::AddrType p_type) { if (sockfd != -1) return sockfd; - sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + + sockfd = socket(family, SOCK_DGRAM, IPPROTO_UDP); ERR_FAIL_COND_V( sockfd == -1, -1 ); //fcntl(sockfd, F_SETFL, O_NONBLOCK); diff --git a/platform/windows/packet_peer_udp_winsock.h b/platform/windows/packet_peer_udp_winsock.h index b24dbac592..9837ef6621 100644 --- a/platform/windows/packet_peer_udp_winsock.h +++ b/platform/windows/packet_peer_udp_winsock.h @@ -42,15 +42,15 @@ class PacketPeerUDPWinsock : public PacketPeerUDP { mutable RingBuffer<uint8_t> rb; uint8_t recv_buffer[PACKET_BUFFER_SIZE]; mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; - IP_Address packet_ip; - int packet_port; + mutable IP_Address packet_ip; + mutable int packet_port; mutable int queue_count; int sockfd; IP_Address peer_addr; int peer_port; - _FORCE_INLINE_ int _get_socket(); + _FORCE_INLINE_ int _get_socket(IP_Address::AddrType p_type); static PacketPeerUDP* _create(); @@ -67,7 +67,7 @@ public: virtual int get_max_packet_size() const; - virtual Error listen(int p_port,int p_recv_buffer_size=65536); + virtual Error listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size=65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index fcf0cb1640..b511e38ecb 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -31,16 +31,11 @@ #include "stream_peer_winsock.h" #include <winsock2.h> +#include <ws2tcpip.h> -int winsock_refcount = 0; - -static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) { +#include "drivers/unix/socket_helpers.h" - their_addr.sin_family = AF_INET; // host byte order - their_addr.sin_port = htons(p_port); // short, network byte order - their_addr.sin_addr = *((struct in_addr*)&p_host.host); - memset(&(their_addr.sin_zero), '\0', 8); -}; +int winsock_refcount = 0; StreamPeerTCP* StreamPeerWinsock::_create() { @@ -92,10 +87,10 @@ Error StreamPeerWinsock::_poll_connection(bool p_block) const { _block(sockfd, false, true); }; - struct sockaddr_in their_addr; - set_addr_in(their_addr, peer_host, peer_port); + struct sockaddr_storage their_addr; + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port); - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) { int err = WSAGetLastError(); if (err == WSAEISCONN) { @@ -299,9 +294,10 @@ void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port) Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { - ERR_FAIL_COND_V( p_host.host == 0, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER); - if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { + int family = p_host.type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + if ((sockfd = socket(family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { ERR_PRINT("Socket creation failed!"); disconnect(); //perror("socket"); @@ -315,10 +311,10 @@ Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { return FAILED; }; - struct sockaddr_in their_addr; - set_addr_in(their_addr, p_host, p_port); + struct sockaddr_storage their_addr; + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port); - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { ERR_PRINT("Connection to remote host failed!"); diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp index dd1cf43f3b..1aedc52bb9 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -31,6 +31,9 @@ #include "stream_peer_winsock.h" #include <winsock2.h> +#include <ws2tcpip.h> + +#include "drivers/unix/socket_helpers.h" extern int winsock_refcount; @@ -60,7 +63,7 @@ void TCPServerWinsock::cleanup() { }; -Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_hosts) { +Error TCPServerWinsock::listen(uint16_t p_port, IP_Address::AddrType p_type,const List<String> *p_accepted_hosts) { int sockfd; sockfd = socket(AF_INET, SOCK_STREAM, 0); @@ -73,11 +76,8 @@ Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_ho return FAILED; }; - struct sockaddr_in my_addr; - my_addr.sin_family = AF_INET; // host byte order - my_addr.sin_port = htons(p_port); // short, network byte order - my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts - memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); + struct sockaddr_storage my_addr; + size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, p_type, p_accepted_hosts); int reuse=1; if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { @@ -86,7 +86,7 @@ Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_ho } - if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != SOCKET_ERROR) { + if (bind(sockfd, (struct sockaddr *)&my_addr, addr_size) != SOCKET_ERROR) { if (::listen(sockfd, SOMAXCONN) == SOCKET_ERROR) { @@ -140,16 +140,17 @@ Ref<StreamPeerTCP> TCPServerWinsock::take_connection() { return NULL; }; - struct sockaddr_in their_addr; + struct sockaddr_storage their_addr; int sin_size = sizeof(their_addr); int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size); ERR_FAIL_COND_V(fd == INVALID_SOCKET, NULL); Ref<StreamPeerWinsock> conn = memnew(StreamPeerWinsock); IP_Address ip; - ip.host = (uint32_t)their_addr.sin_addr.s_addr; + int port; + _set_ip_addr_port(ip, port, &their_addr); - conn->set_socket(fd, ip, ntohs(their_addr.sin_port)); + conn->set_socket(fd, ip, port); return conn; }; diff --git a/platform/windows/tcp_server_winsock.h b/platform/windows/tcp_server_winsock.h index bd6a05c74d..94601a2e12 100644 --- a/platform/windows/tcp_server_winsock.h +++ b/platform/windows/tcp_server_winsock.h @@ -39,7 +39,7 @@ class TCPServerWinsock : public TCP_Server { public: - virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4,const List<String> *p_accepted_hosts=NULL); virtual bool is_connection_available() const; virtual Ref<StreamPeerTCP> take_connection(); diff --git a/platform/x11/detect.py b/platform/x11/detect.py index eb71ac7409..917a8a27d7 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -94,10 +94,6 @@ def configure(env): env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) env.extra_suffix=".llvm" - if (env["colored"]=="yes"): - if sys.stdout.isatty(): - env.Append(CXXFLAGS=["-fcolor-diagnostics"]) - if (env["use_sanitizer"]=="yes"): env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer']) env.Append(LINKFLAGS=['-fsanitize=address']) diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index b5d62adfb4..bd7f4faae5 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -187,39 +187,44 @@ void RayCast2D::_notification(int p_what) { if (!enabled) break; + _update_raycast_state(); - Ref<World2D> w2d = get_world_2d(); - ERR_BREAK( w2d.is_null() ); - - Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space()); - ERR_BREAK( !dss ); - - Matrix32 gt = get_global_transform(); + } break; + } +} - Vector2 to = cast_to; - if (to==Vector2()) - to=Vector2(0,0.01); +void RayCast2D::_update_raycast_state() { + Ref<World2D> w2d = get_world_2d(); + ERR_FAIL_COND( w2d.is_null() ); - Physics2DDirectSpaceState::RayResult rr; + Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space()); + ERR_FAIL_COND( !dss ); - if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask,type_mask)) { + Matrix32 gt = get_global_transform(); - collided=true; - against=rr.collider_id; - collision_point=rr.position; - collision_normal=rr.normal; - against_shape=rr.shape; - } else { - collided=false; - } + Vector2 to = cast_to; + if (to==Vector2()) + to=Vector2(0,0.01); + Physics2DDirectSpaceState::RayResult rr; + if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask,type_mask)) { - } break; + collided=true; + against=rr.collider_id; + collision_point=rr.position; + collision_normal=rr.normal; + against_shape=rr.shape; + } else { + collided=false; } } +void RayCast2D::force_raycast_update() { + _update_raycast_state(); +} + void RayCast2D::add_exception_rid(const RID& p_rid) { exclude.insert(p_rid); @@ -265,6 +270,7 @@ void RayCast2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_cast_to"),&RayCast2D::get_cast_to); ObjectTypeDB::bind_method(_MD("is_colliding"),&RayCast2D::is_colliding); + ObjectTypeDB::bind_method(_MD("force_raycast_update"),&RayCast2D::force_raycast_update); ObjectTypeDB::bind_method(_MD("get_collider"),&RayCast2D::get_collider); ObjectTypeDB::bind_method(_MD("get_collider_shape"),&RayCast2D::get_collider_shape); diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index e1caa8b63e..9bdcc2e199 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -52,6 +52,7 @@ class RayCast2D : public Node2D { protected: void _notification(int p_what); + void _update_raycast_state(); static void _bind_methods(); public: @@ -70,6 +71,8 @@ public: void set_exclude_parent_body(bool p_exclude_parent_body); bool get_exclude_parent_body() const; + void force_raycast_update(); + bool is_colliding() const; Object *get_collider() const; int get_collider_shape() const; diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index 1acda8d1f8..2b8df8265e 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -134,39 +134,44 @@ void RayCast::_notification(int p_what) { if (!enabled) break; + _update_raycast_state(); - Ref<World> w3d = get_world(); - ERR_BREAK( w3d.is_null() ); - - PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space()); - ERR_BREAK( !dss ); - - Transform gt = get_global_transform(); + } break; + } +} - Vector3 to = cast_to; - if (to==Vector3()) - to=Vector3(0,0.01,0); +void RayCast::_update_raycast_state(){ + Ref<World> w3d = get_world(); + ERR_FAIL_COND( w3d.is_null() ); - PhysicsDirectSpaceState::RayResult rr; + PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space()); + ERR_FAIL_COND( !dss ); - if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude, layer_mask, type_mask)) { + Transform gt = get_global_transform(); - collided=true; - against=rr.collider_id; - collision_point=rr.position; - collision_normal=rr.normal; - against_shape=rr.shape; - } else { - collided=false; - } + Vector3 to = cast_to; + if (to==Vector3()) + to=Vector3(0,0.01,0); + PhysicsDirectSpaceState::RayResult rr; + if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude, layer_mask, type_mask)) { - } break; + collided=true; + against=rr.collider_id; + collision_point=rr.position; + collision_normal=rr.normal; + against_shape=rr.shape; + } else { + collided=false; } } +void RayCast::force_raycast_update() { + _update_raycast_state(); +} + void RayCast::add_exception_rid(const RID& p_rid) { exclude.insert(p_rid); @@ -212,6 +217,7 @@ void RayCast::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_cast_to"),&RayCast::get_cast_to); ObjectTypeDB::bind_method(_MD("is_colliding"),&RayCast::is_colliding); + ObjectTypeDB::bind_method(_MD("force_raycast_update"),&RayCast::force_raycast_update); ObjectTypeDB::bind_method(_MD("get_collider"),&RayCast::get_collider); ObjectTypeDB::bind_method(_MD("get_collider_shape"),&RayCast::get_collider_shape); diff --git a/scene/3d/ray_cast.h b/scene/3d/ray_cast.h index 4f6514e61b..47553f08ed 100644 --- a/scene/3d/ray_cast.h +++ b/scene/3d/ray_cast.h @@ -53,6 +53,7 @@ class RayCast : public Spatial { protected: void _notification(int p_what); + void _update_raycast_state(); static void _bind_methods(); public: @@ -68,6 +69,7 @@ public: void set_type_mask(uint32_t p_mask); uint32_t get_type_mask() const; + void force_raycast_update(); bool is_colliding() const; Object *get_collider() const; int get_collider_shape() const; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 6b43425edc..f942f15ed0 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -186,15 +186,17 @@ void FileDialog::_action_pressed() { hide(); }else if (mode==MODE_OPEN_ANY || mode==MODE_OPEN_DIR) { - String path=dir_access->get_current_dir(); - /*if (tree->get_selected()) { - Dictionary d = tree->get_selected()->get_metadata(0); + + path=path.replace("\\","/"); + + if (TreeItem* item = tree->get_selected()) { + Dictionary d = item->get_metadata(0); if (d["dir"]) { - path=path+"/"+String(d["name"]); + path=path.plus_file(d["name"]); } - }*/ - path=path.replace("\\","/"); + } + emit_signal("dir_selected",path); hide(); } @@ -348,18 +350,18 @@ void FileDialog::update_file_list() { files.sort_custom<NoCaseComparator>(); while(!dirs.empty()) { + String& dir_name = dirs.front()->get(); + TreeItem *ti=tree->create_item(root); + ti->set_text(0,dir_name+"/"); + ti->set_icon(0,folder); - if (dirs.front()->get()!=".") { - TreeItem *ti=tree->create_item(root); - ti->set_text(0,dirs.front()->get()+"/"); - ti->set_icon(0,folder); - Dictionary d; - d["name"]=dirs.front()->get(); - d["dir"]=true; - ti->set_metadata(0,d); - } - dirs.pop_front(); + Dictionary d; + d["name"]=dir_name; + d["dir"]=true; + + ti->set_metadata(0,d); + dirs.pop_front(); } dirs.clear(); diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 8d228ad859..1df0aafb23 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -7612,6 +7612,11 @@ void VisualServerRaster::set_default_clear_color(const Color& p_color) { clear_color=p_color; } +Color VisualServerRaster::get_default_clear_color() const { + + return clear_color; +} + void VisualServerRaster::set_boot_image(const Image& p_image, const Color& p_color,bool p_scale) { if (p_image.empty()) diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 496820f4a8..1f22e31ab0 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1283,6 +1283,7 @@ public: virtual void set_boot_image(const Image& p_image, const Color& p_color, bool p_scale); virtual void set_default_clear_color(const Color& p_color); + virtual Color get_default_clear_color() const; VisualServerRaster(Rasterizer *p_rasterizer); ~VisualServerRaster(); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index b4e374dd6f..f0fe80d100 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -718,6 +718,7 @@ public: FUNC3(set_boot_image,const Image& , const Color&,bool ); FUNC1(set_default_clear_color,const Color& ); + FUNC0RC(Color,get_default_clear_color ); FUNC0R(RID,get_test_cube ); diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index dfa0c91c7f..6099a86b96 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -564,6 +564,7 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("free_rid"),&VisualServer::free); ObjectTypeDB::bind_method(_MD("set_default_clear_color"),&VisualServer::set_default_clear_color); + ObjectTypeDB::bind_method(_MD("get_default_clear_color"),&VisualServer::get_default_clear_color); ObjectTypeDB::bind_method(_MD("get_render_info"),&VisualServer::get_render_info); diff --git a/servers/visual_server.h b/servers/visual_server.h index 2f3d8371f6..844da2d245 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -1181,6 +1181,7 @@ public: virtual void set_boot_image(const Image& p_image, const Color& p_color,bool p_scale)=0; virtual void set_default_clear_color(const Color& p_color)=0; + virtual Color get_default_clear_color() const=0; enum Features { FEATURE_SHADERS, diff --git a/tools/editor/editor_file_dialog.cpp b/tools/editor/editor_file_dialog.cpp index b8abd1d32c..90289a275e 100644 --- a/tools/editor/editor_file_dialog.cpp +++ b/tools/editor/editor_file_dialog.cpp @@ -336,15 +336,21 @@ void EditorFileDialog::_action_pressed() { hide(); }else if (mode==MODE_OPEN_ANY || mode==MODE_OPEN_DIR) { - String path=dir_access->get_current_dir(); - /*if (tree->get_selected()) { - Dictionary d = tree->get_selected()->get_metadata(0); - if (d["dir"]) { - path=path+"/"+String(d["name"]); - } - }*/ + path=path.replace("\\","/"); + + for(int i=0;i<item_list->get_item_count();i++) { + if (item_list->is_selected(i)) { + Dictionary d=item_list->get_item_metadata(i); + if (d["dir"]) { + path=path.plus_file(d["name"]); + + break; + } + } + } + _save_to_recent(); emit_signal("dir_selected",path); hide(); @@ -571,25 +577,26 @@ void EditorFileDialog::update_file_list() { files.sort_custom<NoCaseComparator>(); while(!dirs.empty()) { + const String& dir_name=dirs.front()->get(); - if (dirs.front()->get()!=".") { - item_list->add_item(dirs.front()->get()+"/"); - if (display_mode==DISPLAY_THUMBNAILS) { + item_list->add_item(dir_name+"/"); - item_list->set_item_icon(item_list->get_item_count()-1,folder_thumbnail); - } else { + if (display_mode==DISPLAY_THUMBNAILS) { - item_list->set_item_icon(item_list->get_item_count()-1,folder); - } + item_list->set_item_icon(item_list->get_item_count()-1,folder_thumbnail); + } else { - Dictionary d; - d["name"]=dirs.front()->get(); - d["path"]=String(); - d["dir"]=true; - item_list->set_item_metadata( item_list->get_item_count() -1, d); + item_list->set_item_icon(item_list->get_item_count()-1,folder); } - dirs.pop_front(); + Dictionary d; + d["name"]=dir_name; + d["path"]=String(); + d["dir"]=true; + + item_list->set_item_metadata( item_list->get_item_count() -1, d); + + dirs.pop_front(); } dirs.clear(); diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index bdbf20e348..f5741c4a9e 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -1026,6 +1026,34 @@ void EditorSettings::set_optimize_save(bool p_optimize) { optimize_save=p_optimize; } +String EditorSettings::get_last_selected_language() +{ + Ref<ConfigFile> cf = memnew( ConfigFile ); + String path = get_project_settings_path().plus_file("project_metadata.cfg"); + Error err = cf->load(path); + if (err != OK) { + WARN_PRINTS("Can't load config file: " + path); + return ""; + } + Variant last_selected_language = cf->get_value("script_setup", "last_selected_language"); + if (last_selected_language.get_type() != Variant::STRING) + return ""; + return static_cast<String>(last_selected_language); +} + +void EditorSettings::set_last_selected_language(String p_language) +{ + Ref<ConfigFile> cf = memnew( ConfigFile ); + String path = get_project_settings_path().plus_file("project_metadata.cfg"); + Error err = cf->load(path); + if (err != OK) { + WARN_PRINTS("Can't load config file: " + path); + return; + } + cf->set_value("script_setup", "last_selected_language", p_language); + cf->save(path); +} + void EditorSettings::_bind_methods() { ObjectTypeDB::bind_method(_MD("erase","property"),&EditorSettings::erase); diff --git a/tools/editor/editor_settings.h b/tools/editor/editor_settings.h index 2a7d3bb4f0..a976602304 100644 --- a/tools/editor/editor_settings.h +++ b/tools/editor/editor_settings.h @@ -160,6 +160,9 @@ public: void set_optimize_save(bool p_optimize); + String get_last_selected_language(); + void set_last_selected_language(String p_language); + EditorSettings(); ~EditorSettings(); diff --git a/tools/editor/filesystem_dock.cpp b/tools/editor/filesystem_dock.cpp index 8a94c6e340..5b1e80fc3b 100644 --- a/tools/editor/filesystem_dock.cpp +++ b/tools/editor/filesystem_dock.cpp @@ -234,13 +234,6 @@ void FileSystemDock::_dir_selected() { button_favorite->set_pressed(found); - if (ti->get_parent() && ti->get_parent()->get_parent()==tree->get_root() && !ti->get_parent()->get_prev()) { - - //a favorite!!! - } else { - - - } if (!split_mode) { _open_pressed(); //go directly to dir diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index 3cd6d8336a..99c50efd2f 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -1620,6 +1620,7 @@ void ScriptEditor::apply_scripts() const { void ScriptEditor::_editor_play() { debugger->start(); + debug_menu->get_popup()->grab_focus(); debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true ); debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), true ); debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), false ); diff --git a/tools/editor/script_create_dialog.cpp b/tools/editor/script_create_dialog.cpp index 749198314a..62d5c7cd84 100644 --- a/tools/editor/script_create_dialog.cpp +++ b/tools/editor/script_create_dialog.cpp @@ -121,6 +121,8 @@ void ScriptCreateDialog::ok_pressed() { Ref<Script> scr = ScriptServer::get_language( language_menu->get_selected() )->get_template(cname,parent_name->get_text()); //scr->set_source_code(text); + String selected_language = language_menu->get_item_text(language_menu->get_selected()); + editor_settings->set_last_selected_language(selected_language); if (cname!="") scr->set_name(cname); @@ -330,7 +332,17 @@ ScriptCreateDialog::ScriptCreateDialog() { language_menu->add_item(ScriptServer::get_language(i)->get_name()); } - language_menu->select(0); + editor_settings = EditorSettings::get_singleton(); + String last_selected_language = editor_settings->get_last_selected_language(); + if (last_selected_language != "") + for (int i = 0; i < language_menu->get_item_count(); i++) + if (language_menu->get_item_text(i) == last_selected_language) + { + language_menu->select(i); + break; + } + else language_menu->select(0); + language_menu->connect("item_selected",this,"_lang_changed"); //parent_name->set_text(); diff --git a/tools/editor/script_create_dialog.h b/tools/editor/script_create_dialog.h index 181989402e..c71ea16d39 100644 --- a/tools/editor/script_create_dialog.h +++ b/tools/editor/script_create_dialog.h @@ -33,6 +33,7 @@ #include "scene/gui/line_edit.h" #include "scene/gui/option_button.h" #include "tools/editor/editor_file_dialog.h" +#include "tools/editor/editor_settings.h" #include "scene/gui/check_button.h" class ScriptCreateDialog : public ConfirmationDialog { @@ -50,6 +51,7 @@ class ScriptCreateDialog : public ConfirmationDialog { AcceptDialog *alert; bool path_valid; String initial_bp; + EditorSettings *editor_settings; void _path_changed(const String& p_path=String()); |