mirror of
https://github.com/godotengine/godot
synced 2024-09-05 21:50:24 +00:00
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.
This commit is contained in:
parent
d02953c596
commit
abbea4d945
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
demos/misc/udp_chat/chat.gd
Normal file
72
demos/misc/udp_chat/chat.gd
Normal file
|
@ -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
Normal file
BIN
demos/misc/udp_chat/chat.scn
Normal file
Binary file not shown.
5
demos/misc/udp_chat/engine.cfg
Normal file
5
demos/misc/udp_chat/engine.cfg
Normal file
|
@ -0,0 +1,5 @@
|
|||
[application]
|
||||
|
||||
name="UDP Chat"
|
||||
main_scene="res://chat.scn"
|
||||
icon="res://icon.png"
|
BIN
demos/misc/udp_chat/icon.png
Normal file
BIN
demos/misc/udp_chat/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ERR_FAIL_COND_V(img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER);
|
||||
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(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;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -112,6 +112,8 @@ public:
|
|||
void set_enable_monitoring(bool p_enable);
|
||||
bool is_monitoring_enabled() const;
|
||||
|
||||
Array get_overlapping_bodies() const;
|
||||
|
||||
|
||||
Area();
|
||||
~Area();
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue