Explorar el Código

UDP Fixes
-=-=-=-=-

Curse the day I decided to port UDP code, as it ended up
being two nights of work. At least It's done now (I hope).

-Fixed UDP Support, API seems stable
-Added UDP Chat demo (chat that can lose your packets, heh)
-Added helpers to areas and bodies to get list of collided bodies and contained bodies.
-Sped up screen/viewport capture code.
-Added code to save an image as PNG
-Small fix so scripts register their singletons after modules did.

Juan Linietsky hace 11 años
padre
commit
abbea4d945

+ 9 - 0
core/image.cpp

@@ -34,6 +34,7 @@
 #include "print_string.h"
 #include <stdio.h>
 
+SavePNGFunc Image::save_png_func = NULL;
 
 void Image::_put_pixel(int p_x,int p_y, const BColor& p_color, unsigned char *p_data) {
 
@@ -1200,6 +1201,14 @@ Error Image::load(const String& p_path) {
 	return ImageLoader::load_image(p_path, this);
 }
 
+Error Image::save_png(const String& p_path) {
+
+	if (save_png_func == NULL)
+		return ERR_UNAVAILABLE;
+
+	return save_png_func(p_path, *this);
+};
+
 bool Image::operator==(const Image& p_image) const {
 
 	if (data.size() == 0 && p_image.data.size() == 0)

+ 5 - 0
core/image.h

@@ -40,7 +40,9 @@
  * Images can be loaded from a file, or registered into the Render object as textures.
 */
 
+class Image;
 
+typedef Error (*SavePNGFunc)(const String &p_path, Image& p_img);
 
 class Image {
 
@@ -50,6 +52,8 @@ class Image {
 	};
 public:
 
+	static SavePNGFunc save_png_func;
+
 	enum Format {
 		FORMAT_GRAYSCALE, ///< one byte per pixel, 0-255 
 		FORMAT_INTENSITY, ///< one byte per pixel, 0-255 
@@ -278,6 +282,7 @@ public:
 	DVector<uint8_t> get_data() const;
 	
 	Error load(const String& p_path);
+	Error save_png(const String& p_path);
 	
 	/** 
 	 * create an empty image

+ 6 - 0
core/io/ip_address.h

@@ -39,6 +39,12 @@ struct IP_Address {
 	};
 
 	//operator Variant() const;
+	bool operator==(const IP_Address& p_ip) const {
+		return host==p_ip.host;
+	}
+	bool operator!=(const IP_Address& p_ip) const {
+		return host!=p_ip.host;
+	}
 	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);

+ 17 - 3
core/io/packet_peer_udp.cpp

@@ -1,5 +1,5 @@
 #include "packet_peer_udp.h"
-
+#include "io/ip.h"
 
 
 PacketPeerUDP* (*PacketPeerUDP::_create)()=NULL;
@@ -15,17 +15,31 @@ String PacketPeerUDP::_get_packet_ip() const {
 	return get_packet_address();
 }
 
+Error PacketPeerUDP::_set_send_address(const String& p_address,int p_port) {
+
+	IP_Address ip;
+	if (p_address.is_valid_ip_address()) {
+		ip=p_address;
+	} else {
+		ip=IP::get_singleton()->resolve_hostname(p_address);
+		if (ip==IP_Address())
+			return ERR_CANT_RESOLVE;
+	}
+
+	set_send_address(ip,p_port);
+	return OK;
+}
 
 void PacketPeerUDP::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("listen:Error","port","recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(65536));
 	ObjectTypeDB::bind_method(_MD("close"),&PacketPeerUDP::close);
-	ObjectTypeDB::bind_method(_MD("poll:Error"),&PacketPeerUDP::poll);
+	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_port"),&PacketPeerUDP::get_packet_port);
-	ObjectTypeDB::bind_method(_MD("set_send_address","address","port"),&PacketPeerUDP::set_send_address);
+	ObjectTypeDB::bind_method(_MD("set_send_address","host","port"),&PacketPeerUDP::_set_send_address);
 
 
 }

+ 3 - 1
core/io/packet_peer_udp.h

@@ -15,11 +15,13 @@ protected:
 	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 void close()=0;
-	virtual Error poll()=0;
+	virtual Error wait()=0;
 	virtual bool is_listening() const=0;
 	virtual IP_Address get_packet_address() const=0;
 	virtual int get_packet_port() const=0;

+ 7 - 0
core/script_language.cpp

@@ -85,6 +85,13 @@ void ScriptServer::register_language(ScriptLanguage *p_language) {
 	_languages[_language_count++]=p_language;
 }
 
+void ScriptServer::init_languages() {
+
+	for(int i=0;i<_language_count;i++) {
+		_languages[i]->init();
+	}
+}
+
 Variant ScriptInstance::call(const StringName& p_method,VARIANT_ARG_DECLARE) {
 
 	VARIANT_ARGPTRS;

+ 2 - 0
core/script_language.h

@@ -54,6 +54,8 @@ public:
 	static int get_language_count();
 	static ScriptLanguage *get_language(int p_idx);
 	static void register_language(ScriptLanguage *p_language);
+
+	static void init_languages();
 };
 
 

+ 2 - 0
core/variant_call.cpp

@@ -544,6 +544,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 	VCALL_PTR0R(Image,get_used_rect);
 	VCALL_PTR3R(Image,brushed);
 	VCALL_PTR1R(Image,load);
+	VCALL_PTR1R(Image,save_png);
 	VCALL_PTR3(Image,brush_transfer);
 	VCALL_PTR1R(Image,get_rect);
 	VCALL_PTR1R(Image,compressed);
@@ -1326,6 +1327,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
 	ADDFUNC4(IMAGE, NIL, Image, put_pixel, INT, "x", INT, "y", COLOR, "color", INT, "mipmap_level", varray(0));
 	ADDFUNC3(IMAGE, IMAGE, Image, brushed, IMAGE, "src", IMAGE, "brush", VECTOR2, "pos", varray(0));
 	ADDFUNC1(IMAGE, INT, Image, load, STRING, "path", varray(0));
+	ADDFUNC1(IMAGE, INT, Image, save_png, STRING, "path", varray(0));
 	ADDFUNC3(IMAGE, NIL, Image, brush_transfer, IMAGE, "src", IMAGE, "brush", VECTOR2, "pos", varray(0));
 	ADDFUNC0(IMAGE, RECT2, Image, get_used_rect, varray(0));
 	ADDFUNC1(IMAGE, IMAGE, Image, get_rect, RECT2, "area", varray(0));

+ 72 - 0
demos/misc/udp_chat/chat.gd

@@ -0,0 +1,72 @@
+
+extends Panel
+
+# Really simple UDP chat client, not intended as a chat example!!
+# (UDP can lose packets and you won't normally find out, so don't do a chat this way)
+# This is just a demo that shows how to use the UDP class.
+
+var udp = PacketPeerUDP.new()
+
+func _process(delta):
+
+	if (not udp.is_listening()):
+		return
+		
+	while(udp.get_available_packet_count()>0):
+		var packet = udp.get_var()
+		if (typeof(packet)==TYPE_STRING):
+				var host = udp.get_packet_ip()
+				var port = udp.get_packet_port()
+				get_node("chat/text").add_text("("+host+":"+str(port)+":) "+packet)
+				get_node("chat/text").newline()
+					
+			
+
+func _ready():
+	# Initalization here
+	get_node("chat").add_style_override("panel",get_stylebox("bg","Tree"))	
+	set_process(true)
+
+
+
+func send_message(text):
+	if (udp.is_listening()):
+		udp.put_var(text)
+	
+
+func _on_connect_toggled( pressed ):
+
+
+	if (pressed):
+		var err = udp.listen( get_node("listen_port").get_val() )
+		if (err!=OK):
+			get_node("status").set_text("Error:\nCan't Listen.")
+			get_node("connect").set_pressed(false)
+		else:
+			get_node("status").set_text("Connected.")
+			get_node("connect").set_text("Disconnect")
+			err = udp.set_send_address(get_node("remote_host").get_text(),get_node("remote_port").get_val())
+			if (err!=OK):
+				get_node("status").set_text("Error:\nCan't Resolve.")
+				get_node("connect").set_pressed(false)
+			else:
+				send_message("* "+get_node("user_name").get_text()+" entered chat.")			
+	else:
+	
+		udp.close()
+		get_node("status").set_text("Disconnected.")
+		get_node("connect").set_text("Connect")
+	
+
+
+
+func _on_entry_line_text_entered( text ):
+	_on_entry_button_pressed();
+
+func _on_entry_button_pressed():
+	var msg = get_node("entry_line").get_text()
+	if (msg==""):
+		return
+	send_message(get_node("user_name").get_text()+"> "+msg)
+	
+	get_node("entry_line").set_text("")

BIN
demos/misc/udp_chat/chat.scn


+ 5 - 0
demos/misc/udp_chat/engine.cfg

@@ -0,0 +1,5 @@
+[application]
+
+name="UDP Chat"
+main_scene="res://chat.scn"
+icon="res://icon.png"

BIN
demos/misc/udp_chat/icon.png


+ 17 - 4
drivers/gles2/rasterizer_gles2.cpp

@@ -4174,7 +4174,7 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) {
 	DVector<uint8_t>::Write w = pixels.write();
 	glPixelStorei(GL_PACK_ALIGNMENT, 4);
 
-	uint64_t time = OS::get_singleton()->get_ticks_usec();
+//	uint64_t time = OS::get_singleton()->get_ticks_usec();
 
 	if (current_rt) {
 #ifdef GLEW_ENABLED
@@ -4185,13 +4185,26 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) {
 		// back?
 		glReadPixels( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height,GL_RGBA,GL_UNSIGNED_BYTE,w.ptr());
 	}
-	printf("readpixels time %i\n", (int)(OS::get_singleton()->get_ticks_usec() - time));
+
+	uint32_t *imgptr = (uint32_t*)w.ptr();
+	for(int y=0;y<(viewport.height/2);y++) {
+
+		uint32_t *ptr1 = &imgptr[y*viewport.width];
+		uint32_t *ptr2 = &imgptr[(viewport.height-y-1)*viewport.width];
+
+		for(int x=0;x<viewport.width;x++) {
+
+			uint32_t tmp = ptr1[x];
+			ptr1[x]=ptr2[x];
+			ptr2[x]=tmp;
+		}
+	}
+
 	w=DVector<uint8_t>::Write();
 
 	r_capture->create(viewport.width,viewport.height,0,Image::FORMAT_RGBA,pixels);
-	r_capture->flip_y();
+	//r_capture->flip_y();
 
-	printf("total time %i\n", (int)(OS::get_singleton()->get_ticks_usec() - time));
 
 #endif
 

+ 60 - 47
drivers/png/resource_saver_png.cpp

@@ -31,6 +31,7 @@
 #include "drivers/png/png.h"
 #include "os/file_access.h"
 #include "globals.h"
+#include "core/image.h"
 
 static void _write_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) {
 
@@ -46,12 +47,56 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t
 	ERR_EXPLAIN("Can't save empty texture as PNG");
 	ERR_FAIL_COND_V(!texture->get_width() || !texture->get_height(),ERR_INVALID_PARAMETER);
 
+
 	Image img = texture->get_data();
-	if (img.get_format() > Image::FORMAT_INDEXED_ALPHA)
-		img.decompress();
 
+	Error err = save_image(p_path, img);
+
+	if (err == OK) {
+
+		bool global_filter = Globals::get_singleton()->get("image_loader/filter");
+		bool global_mipmaps = Globals::get_singleton()->get("image_loader/gen_mipmaps");
+		bool global_repeat = Globals::get_singleton()->get("image_loader/repeat");
+
+		String text;
+
+		if (global_filter!=bool(texture->get_flags()&Texture::FLAG_FILTER)) {
+			text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"filter=true\n":"filter=false\n";
+		}
+		if (global_mipmaps!=bool(texture->get_flags()&Texture::FLAG_MIPMAPS)) {
+			text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"gen_mipmaps=true\n":"gen_mipmaps=false\n";
+		}
+		if (global_repeat!=bool(texture->get_flags()&Texture::FLAG_REPEAT)) {
+			text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"repeat=true\n":"repeat=false\n";
+		}
+		if (bool(texture->get_flags()&Texture::FLAG_ANISOTROPIC_FILTER)) {
+			text+="anisotropic=true\n";
+		}
+		if (bool(texture->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR)) {
+			text+="tolinear=true\n";
+		}
+
+		if (text!="" || FileAccess::exists(p_path+".flags")) {
+
+			FileAccess* f = FileAccess::open(p_path+".flags",FileAccess::WRITE);
+			if (f) {
+
+				f->store_string(text);
+				memdelete(f);
+			}
+		}
+	}
+
+
+	return err;
+};
+
+Error ResourceSaverPNG::save_image(const String &p_path, Image &p_img) {
+
+	if (p_img.get_format() > Image::FORMAT_INDEXED_ALPHA)
+		p_img.decompress();
 
-	ERR_FAIL_COND_V(img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER);
+	ERR_FAIL_COND_V(p_img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER);
 
 	png_structp png_ptr;
 	png_infop info_ptr;
@@ -89,7 +134,7 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t
 	int cs=0;
 
 
-	switch(img.get_format()) {
+	switch(p_img.get_format()) {
 
 		case Image::FORMAT_GRAYSCALE: {
 
@@ -113,14 +158,14 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t
 		} break;
 		default: {
 
-			if (img.detect_alpha()) {
+			if (p_img.detect_alpha()) {
 
-				img.convert(Image::FORMAT_RGBA);
+				p_img.convert(Image::FORMAT_RGBA);
 				pngf=PNG_COLOR_TYPE_RGB_ALPHA;
 				cs=4;
 			} else {
 
-				img.convert(Image::FORMAT_RGB);
+				p_img.convert(Image::FORMAT_RGB);
 				pngf=PNG_COLOR_TYPE_RGB;
 				cs=3;
 			}
@@ -128,8 +173,8 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t
 		}
 	}
 
-	int w = img.get_width();
-	int h = img.get_height();
+	int w = p_img.get_width();
+	int h = p_img.get_height();
 	png_set_IHDR(png_ptr, info_ptr, w,h,
 		     8, pngf, PNG_INTERLACE_NONE,
 		     PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
@@ -144,7 +189,7 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t
 	}
 
 
-	DVector<uint8_t>::Read r = img.get_data().read();
+	DVector<uint8_t>::Read r = p_img.get_data().read();
 
 	row_pointers = (png_bytep*)memalloc(sizeof(png_bytep)*h);
 	for(int i=0;i<h;i++) {
@@ -165,43 +210,6 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t
 	png_write_end(png_ptr, NULL);
 	memdelete(f);
 
-
-	if (true) {
-
-		bool global_filter = Globals::get_singleton()->get("image_loader/filter");
-		bool global_mipmaps = Globals::get_singleton()->get("image_loader/gen_mipmaps");
-		bool global_repeat = Globals::get_singleton()->get("image_loader/repeat");
-
-		String text;
-
-		if (global_filter!=bool(texture->get_flags()&Texture::FLAG_FILTER)) {
-			text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"filter=true\n":"filter=false\n";
-		}
-		if (global_mipmaps!=bool(texture->get_flags()&Texture::FLAG_MIPMAPS)) {
-			text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"gen_mipmaps=true\n":"gen_mipmaps=false\n";
-		}
-		if (global_repeat!=bool(texture->get_flags()&Texture::FLAG_REPEAT)) {
-			text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"repeat=true\n":"repeat=false\n";
-		}
-		if (bool(texture->get_flags()&Texture::FLAG_ANISOTROPIC_FILTER)) {
-			text+="anisotropic=true\n";
-		}
-		if (bool(texture->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR)) {
-			text+="tolinear=true\n";
-		}
-
-		if (text!="" || FileAccess::exists(p_path+".flags")) {
-
-			f = FileAccess::open(p_path+".flags",FileAccess::WRITE);
-			if (f) {
-
-				f->store_string(text);
-				memdelete(f);
-			}
-		}
-	}
-
-
 	/* cleanup heap allocation */
 
 	return OK;
@@ -218,3 +226,8 @@ void ResourceSaverPNG::get_recognized_extensions(const RES& p_resource,List<Stri
 	}
 
 }
+
+ResourceSaverPNG::ResourceSaverPNG() {
+
+	Image::save_png_func = &save_image;
+};

+ 4 - 0
drivers/png/resource_saver_png.h

@@ -6,9 +6,13 @@
 class ResourceSaverPNG : public ResourceFormatSaver {
 public:
 
+	static Error save_image(const String &p_path, Image& p_img);
+
 	virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
 	virtual bool recognize(const RES& p_resource) const;
 	virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
+
+	ResourceSaverPNG();
 };
 
 

+ 14 - 8
drivers/unix/packet_peer_udp_posix.cpp

@@ -25,7 +25,7 @@
 
 int PacketPeerUDPPosix::get_available_packet_count() const {
 
-	Error err = const_cast<PacketPeerUDPPosix*>(this)->poll();
+	Error err = const_cast<PacketPeerUDPPosix*>(this)->_poll(false);
 	if (err!=OK)
 		return 0;
 
@@ -34,16 +34,16 @@ int PacketPeerUDPPosix::get_available_packet_count() const {
 
 Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{
 
-	Error err = const_cast<PacketPeerUDPPosix*>(this)->poll();
+	Error err = const_cast<PacketPeerUDPPosix*>(this)->_poll(false);
 	if (err!=OK)
 		return err;
 	if (queue_count==0)
 		return ERR_UNAVAILABLE;
 
 	uint32_t size;
-	rb.read((uint8_t*)&size,4,true);
 	rb.read((uint8_t*)&packet_ip.host,4,true);
 	rb.read((uint8_t*)&packet_port,4,true);
+	rb.read((uint8_t*)&size,4,true);
 	rb.read(packet_buffer,size,true);
 	--queue_count;
 	*r_buffer=packet_buffer;
@@ -62,6 +62,7 @@ Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){
 
 	errno = 0;
 	int err;
+
 	while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) {
 
 		if (errno != EAGAIN) {
@@ -91,8 +92,8 @@ Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size){
 		close();
 		return ERR_UNAVAILABLE;
 	}
-	printf("UDP Connection listening on port %i\n", p_port);
-	rb.resize(nearest_power_of_2(p_recv_buffer_size));
+	printf("UDP Connection listening on port %i  bufsize %i \n", p_port,p_recv_buffer_size);
+	rb.resize(nearest_shift(p_recv_buffer_size));
 	return OK;
 }
 
@@ -105,18 +106,23 @@ void PacketPeerUDPPosix::close(){
 	queue_count=0;
 }
 
-Error PacketPeerUDPPosix::poll() {
+
+Error PacketPeerUDPPosix::wait() {
+
+	return _poll(true);
+}
+
+Error PacketPeerUDPPosix::_poll(bool p_wait) {
 
 	struct sockaddr_in from = {0};
 	socklen_t len = sizeof(struct sockaddr_in);
 	int ret;
-	while ( (ret = recvfrom(sockfd, recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) {
+	while ( (ret = recvfrom(sockfd, recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), 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);
 		rb.write((uint8_t*)&port, 4);
 		rb.write((uint8_t*)&ret, 4);
 		rb.write(recv_buffer, ret);
-
 		len = sizeof(struct sockaddr_in);
 		++queue_count;
 	};

+ 2 - 1
drivers/unix/packet_peer_udp_posix.h

@@ -27,6 +27,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
 	_FORCE_INLINE_ int _get_socket();
 
 	static PacketPeerUDP* _create();
+	virtual Error _poll(bool p_block);
 
 public:
 
@@ -38,7 +39,7 @@ public:
 
 	virtual Error listen(int p_port,int p_recv_buffer_size=65536);
 	virtual void close();
-	virtual Error poll();
+	virtual Error wait();
 	virtual bool is_listening() const;
 
 	virtual IP_Address get_packet_address() const;

+ 2 - 0
main/main.cpp

@@ -819,6 +819,8 @@ Error Main::setup2() {
 	register_module_types();
 	register_driver_types();
 
+	ScriptServer::init_languages();
+
 	MAIN_PRINT("Main: Load Translations");
 
 	translation_server->setup(); //register translations, load them, etc.

+ 1 - 1
modules/gdscript/register_types.cpp

@@ -125,7 +125,7 @@ void register_gdscript_types() {
 	ObjectTypeDB::register_virtual_type<GDFunctionState>();
 
 	script_language_gd=memnew( GDScriptLanguage );
-	script_language_gd->init();
+	//script_language_gd->init();
 	ScriptServer::register_language(script_language_gd);
 	resource_loader_gd=memnew( ResourceFormatLoaderGDScript );
 	ResourceLoader::add_resource_format_loader(resource_loader_gd);

+ 38 - 5
platform/windows/packet_peer_udp_winsock.cpp

@@ -4,7 +4,7 @@
 
 int PacketPeerUDPWinsock::get_available_packet_count() const {
 
-	Error err = const_cast<PacketPeerUDPWinsock*>(this)->poll();
+	Error err = const_cast<PacketPeerUDPWinsock*>(this)->_poll(false);
 	if (err!=OK)
 		return 0;
 
@@ -13,16 +13,16 @@ int PacketPeerUDPWinsock::get_available_packet_count() const {
 
 Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{
 
-	Error err = const_cast<PacketPeerUDPWinsock*>(this)->poll();
+	Error err = const_cast<PacketPeerUDPWinsock*>(this)->_poll(false);
 	if (err!=OK)
 		return err;
 	if (queue_count==0)
 		return ERR_UNAVAILABLE;
 
 	uint32_t size;
-	rb.read((uint8_t*)&size,4,true);
 	rb.read((uint8_t*)&packet_ip.host,4,true);
 	rb.read((uint8_t*)&packet_port,4,true);
+	rb.read((uint8_t*)&size,4,true);
 	rb.read(packet_buffer,size,true);
 	--queue_count;
 	*r_buffer=packet_buffer;
@@ -39,6 +39,9 @@ Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size
 	addr.sin_port = htons(peer_port);
 	addr.sin_addr = *((struct in_addr*)&peer_addr.host);
 
+
+	_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) {
@@ -56,6 +59,21 @@ int PacketPeerUDPWinsock::get_max_packet_size() const{
 	return 512; // uhm maybe not
 }
 
+
+void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) {
+
+	if (blocking==p_blocking)
+		return;
+
+	blocking=p_blocking;
+	unsigned long par = blocking?0:1;
+	if (ioctlsocket(sockfd, FIONBIO, &par)) {
+		perror("setting non-block mode");
+		//close();
+		//return -1;
+	};
+}
+
 Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size){
 
 	close();
@@ -70,8 +88,11 @@ Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size){
 		close();
 		return ERR_UNAVAILABLE;
 	}
+
+	blocking=true;
+
 	printf("UDP Connection listening on port %i\n", p_port);
-	rb.resize(nearest_power_of_2(p_recv_buffer_size));
+	rb.resize(nearest_shift(p_recv_buffer_size));
 	return OK;
 }
 
@@ -84,7 +105,16 @@ void PacketPeerUDPWinsock::close(){
 	queue_count=0;
 }
 
-Error PacketPeerUDPWinsock::poll() {
+
+Error PacketPeerUDPWinsock::wait() {
+
+	return _poll(true);
+}
+Error PacketPeerUDPWinsock::_poll(bool p_wait) {
+
+
+	_set_blocking(p_wait);
+
 
 	struct sockaddr_in from = {0};
 	int len = sizeof(struct sockaddr_in);
@@ -100,13 +130,16 @@ Error PacketPeerUDPWinsock::poll() {
 		++queue_count;
 	};
 
+
 	if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) ) {
 		close();
 		return FAILED;
 	};
 
+
 	return OK;
 }
+
 bool PacketPeerUDPWinsock::is_listening() const{
 
 	return sockfd!=-1;

+ 6 - 1
platform/windows/packet_peer_udp_winsock.h

@@ -26,6 +26,11 @@ class PacketPeerUDPWinsock : public PacketPeerUDP {
 
 	static PacketPeerUDP* _create();
 
+	bool blocking;
+	void _set_blocking(bool p_blocking);
+
+	Error _poll(bool p_wait);
+
 public:
 
 	virtual int get_available_packet_count() const;
@@ -36,7 +41,7 @@ public:
 
 	virtual Error listen(int p_port,int p_recv_buffer_size=65536);
 	virtual void close();
-	virtual Error poll();
+	virtual Error wait();
 	virtual bool is_listening() const;
 
 	virtual IP_Address get_packet_address() const;

+ 21 - 0
scene/2d/area_2d.cpp

@@ -263,6 +263,25 @@ bool Area2D::is_monitoring_enabled() const {
 	return monitoring;
 }
 
+Array Area2D::get_overlapping_bodies() const {
+
+	ERR_FAIL_COND_V(!monitoring,Array());
+	Array ret;
+	ret.resize(body_map.size());
+	int idx=0;
+	for (const Map<ObjectID,BodyState>::Element *E=body_map.front();E;E=E->next()) {
+		Object *obj = ObjectDB::get_instance(E->key());
+		if (!obj) {
+			ret.resize( ret.size() -1 ); //ops
+		} else {
+			ret[idx++]=obj;
+		}
+
+	}
+
+	return ret;
+}
+
 
 void Area2D::_bind_methods() {
 
@@ -290,6 +309,8 @@ void Area2D::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area2D::set_enable_monitoring);
 	ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area2D::is_monitoring_enabled);
 
+	ObjectTypeDB::bind_method(_MD("get_overlapping_bodies"),&Area2D::get_overlapping_bodies);
+
 	ObjectTypeDB::bind_method(_MD("_body_inout"),&Area2D::_body_inout);
 
 

+ 2 - 0
scene/2d/area_2d.h

@@ -112,6 +112,8 @@ public:
 	void set_enable_monitoring(bool p_enable);
 	bool is_monitoring_enabled() const;
 
+	Array get_overlapping_bodies() const; //function for script
+
 
 	Area2D();
 	~Area2D();

+ 22 - 0
scene/2d/physics_body_2d.cpp

@@ -618,6 +618,26 @@ RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() cons
 }
 
 
+Array RigidBody2D::get_colliding_bodies() const {
+
+	ERR_FAIL_COND_V(!contact_monitor,Array());
+
+	Array ret;
+	ret.resize(contact_monitor->body_map.size());
+	int idx=0;
+	for (const Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
+		Object *obj = ObjectDB::get_instance(E->key());
+		if (!obj) {
+			ret.resize( ret.size() -1 ); //ops
+		} else {
+			ret[idx++]=obj;
+		}
+
+	}
+
+	return ret;
+}
+
 void RigidBody2D::set_contact_monitor(bool p_enabled) {
 
 	if (p_enabled==is_contact_monitor_enabled())
@@ -697,6 +717,8 @@ void RigidBody2D::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("_body_enter_tree"),&RigidBody2D::_body_enter_tree);
 	ObjectTypeDB::bind_method(_MD("_body_exit_tree"),&RigidBody2D::_body_exit_tree);
 
+	ObjectTypeDB::bind_method(_MD("get_colliding_bodies"),&RigidBody2D::get_colliding_bodies);
+
 	BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:Physics2DDirectBodyState")));
 
 	ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),_SCS("set_mode"),_SCS("get_mode"));

+ 2 - 0
scene/2d/physics_body_2d.h

@@ -229,6 +229,8 @@ public:
 	void set_applied_force(const Vector2& p_force);
 	Vector2 get_applied_force() const;
 
+	Array get_colliding_bodies() const; //function for script
+
 	RigidBody2D();
 	~RigidBody2D();
 

+ 20 - 0
scene/3d/area.cpp

@@ -255,6 +255,24 @@ bool Area::is_monitoring_enabled() const {
 }
 
 
+Array Area::get_overlapping_bodies() const {
+
+	ERR_FAIL_COND_V(!monitoring,Array());
+	Array ret;
+	ret.resize(body_map.size());
+	int idx=0;
+	for (const Map<ObjectID,BodyState>::Element *E=body_map.front();E;E=E->next()) {
+		Object *obj = ObjectDB::get_instance(E->key());
+		if (!obj) {
+			ret.resize( ret.size() -1 ); //ops
+		} else {
+			ret[idx++]=obj;
+		}
+
+	}
+
+	return ret;
+}
 
 void Area::_bind_methods() {
 
@@ -283,6 +301,8 @@ void Area::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area::set_enable_monitoring);
 	ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area::is_monitoring_enabled);
 
+	ObjectTypeDB::bind_method(_MD("get_overlapping_bodies"),&Area::get_overlapping_bodies);
+
 	ObjectTypeDB::bind_method(_MD("_body_inout"),&Area::_body_inout);
 
 

+ 2 - 0
scene/3d/area.h

@@ -112,6 +112,8 @@ public:
 	void set_enable_monitoring(bool p_enable);
 	bool is_monitoring_enabled() const;
 
+	Array get_overlapping_bodies() const;
+
 
 	Area();
 	~Area();

+ 23 - 0
scene/3d/physics_body.cpp

@@ -637,6 +637,27 @@ RigidBody::AxisLock RigidBody::get_axis_lock() const {
 }
 
 
+Array RigidBody::get_colliding_bodies() const {
+
+	ERR_FAIL_COND_V(!contact_monitor,Array());
+
+	Array ret;
+	ret.resize(contact_monitor->body_map.size());
+	int idx=0;
+	for (const Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
+		Object *obj = ObjectDB::get_instance(E->key());
+		if (!obj) {
+			ret.resize( ret.size() -1 ); //ops
+		} else {
+			ret[idx++]=obj;
+		}
+
+	}
+
+	return ret;
+}
+
+
 void RigidBody::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("set_mode","mode"),&RigidBody::set_mode);
@@ -688,6 +709,8 @@ void RigidBody::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_axis_lock","axis_lock"),&RigidBody::set_axis_lock);
 	ObjectTypeDB::bind_method(_MD("get_axis_lock"),&RigidBody::get_axis_lock);
 
+	ObjectTypeDB::bind_method(_MD("get_colliding_bodies"),&RigidBody::get_colliding_bodies);
+
 	BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:PhysicsDirectBodyState")));
 
 	ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),_SCS("set_mode"),_SCS("get_mode"));

+ 1 - 0
scene/3d/physics_body.h

@@ -236,6 +236,7 @@ public:
 	void set_axis_lock(AxisLock p_lock);
 	AxisLock get_axis_lock() const;
 
+	Array get_colliding_bodies() const;
 
 	void apply_impulse(const Vector3& p_pos, const Vector3& p_impulse);