예제 #1
0
void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {

	ERR_EXPLAIN("Invalid packet received. Size too small.");
	ERR_FAIL_COND(p_packet_len < 5);
	int id = decode_uint32(&p_packet[1]);

	String paths;
	paths.parse_utf8((const char *)&p_packet[5], p_packet_len - 5);

	NodePath path = paths;

	if (!path_get_cache.has(p_from)) {
		path_get_cache[p_from] = PathGetCache();
	}

	PathGetCache::NodeInfo ni;
	ni.path = path;
	ni.instance = 0;

	path_get_cache[p_from].nodes[id] = ni;

	// Encode path to send ack.
	CharString pname = String(path).utf8();
	int len = encode_cstring(pname.get_data(), NULL);

	Vector<uint8_t> packet;

	packet.resize(1 + len);
	packet.write[0] = NETWORK_COMMAND_CONFIRM_PATH;
	encode_cstring(pname.get_data(), &packet.write[1]);

	network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
	network_peer->set_target_peer(p_from);
	network_peer->put_packet(packet.ptr(), packet.size());
}
예제 #2
0
void FileAccessCompressed::close(){

	if (!f)
		return;


	if (writing) {
		//save block table and all compressed blocks

		CharString mgc = magic.utf8();
		f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //write header 4
		f->store_32(cmode); //write compression mode 4
		f->store_32(block_size); //write block size 4
		f->store_32(write_max); //max amount of data written 4
		int bc=(write_max/block_size)+1;

		for(int i=0;i<bc;i++) {
			f->store_32(0); //compressed sizes, will update later
		}


		Vector<int> block_sizes;
		for(int i=0;i<bc;i++) {

			int bl = i==(bc-1) ? write_max % block_size : block_size;
			uint8_t *bp = &write_ptr[i*block_size];

			Vector<uint8_t> cblock;
			cblock.resize(Compression::get_max_compressed_buffer_size(bl,cmode));
			int s = Compression::compress(cblock.ptr(),bp,bl,cmode);

			f->store_buffer(cblock.ptr(),s);
			block_sizes.push_back(s);
		}

		f->seek(16); //ok write block sizes
		for(int i=0;i<bc;i++)
			f->store_32(block_sizes[i]);
		f->seek_end();
		f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //magic at the end too

		buffer.clear();

	} else {


		comp_buffer.clear();
		buffer.clear();
		read_blocks.clear();
	}

	memdelete(f);
	f=NULL;

}
예제 #3
0
bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int p_target) {
	bool has_all_peers = true;
	List<int> peers_to_add; // If one is missing, take note to add it.

	for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {

		if (p_target < 0 && E->get() == -p_target)
			continue; // Continue, excluded.

		if (p_target > 0 && E->get() != p_target)
			continue; // Continue, not for this peer.

		Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get());

		if (!F || !F->get()) {
			// Path was not cached, or was cached but is unconfirmed.
			if (!F) {
				// Not cached at all, take note.
				peers_to_add.push_back(E->get());
			}

			has_all_peers = false;
		}
	}

	// Those that need to be added, send a message for this.

	for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) {

		// Encode function name.
		CharString pname = String(p_path).utf8();
		int len = encode_cstring(pname.get_data(), NULL);

		Vector<uint8_t> packet;

		packet.resize(1 + 4 + len);
		packet.write[0] = NETWORK_COMMAND_SIMPLIFY_PATH;
		encode_uint32(psc->id, &packet.write[1]);
		encode_cstring(pname.get_data(), &packet.write[5]);

		network_peer->set_target_peer(E->get()); // To all of you.
		network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
		network_peer->put_packet(packet.ptr(), packet.size());

		psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed.
	}

	return has_all_peers;
}
예제 #4
0
String FileAccess::get_line() const {

	CharString line;

	CharType c = get_8();

	while (!eof_reached()) {

		if (c == '\n' || c == '\0') {
			line.push_back(0);
			return String::utf8(line.get_data());
		} else if (c != '\r')
			line.push_back(c);

		c = get_8();
	}
	line.push_back(0);
	return String::utf8(line.get_data());
}
예제 #5
0
Variant _Marshalls::base64_to_variant(const String& p_str) {

    int strlen = p_str.length();
    CharString cstr = p_str.ascii();

    DVector<uint8_t> buf;
    buf.resize(strlen / 4 * 3 + 1);
    DVector<uint8_t>::Write w = buf.write();

    int len = base64_decode((char*)(&w[0]), (char*)cstr.get_data(), strlen);

    Variant v;
    Error err = decode_variant(v, &w[0], len);
    ERR_FAIL_COND_V( err!=OK, Variant() );

    return v;
};
예제 #6
0
파일: file_access.cpp 프로젝트: 93i/godot
String FileAccess::get_token() const {

	CharString token;

	CharType c = get_8();

	while (!eof_reached()) {

		if (c <= ' ') {
			if (token.length())
				break;
		} else {
			token += c;
		}
		c = get_8();
	}

	return String::utf8(token.get_data());
}
예제 #7
0
String FileAccess::get_token() const {

	CharString token;

	CharType c = get_8();

	while (!eof_reached()) {

		if (c <= ' ') {
			if (!token.empty())
				break;
		} else {
			token.push_back(c);
		}
		c = get_8();
	}

	token.push_back(0);
	return String::utf8(token.get_data());
}
예제 #8
0
StringName PHashTranslation::get_message(const StringName& p_src_text) const {

	int htsize = hash_table.size();

	if (htsize==0)
		return StringName();

	CharString str = p_src_text.operator String().utf8();
	uint32_t h = hash(0,str.get_data());


	DVector<int>::Read htr =  hash_table.read();
	const uint32_t *htptr = (const uint32_t*)&htr[0];
	DVector<int>::Read btr =  bucket_table.read();
	const uint32_t *btptr = (const uint32_t*)&btr[0];
	DVector<uint8_t>::Read sr = strings.read();
	const char *sptr= (const char*)&sr[0];

	uint32_t p = htptr[ h % htsize];

	//print_line("String: "+p_src_text.operator String());
	//print_line("Hash: "+itos(p));

	if (p==0xFFFFFFFF) {
//		print_line("GETMSG: Nothing!");
		return StringName(); //nothing
	}

	const Bucket &bucket = *(const Bucket*)&btptr[p];

	h = hash(bucket.func,str.get_data());

	int idx=-1;

	for(int i=0;i<bucket.size;i++) {

		if (bucket.elem[i].key==h) {

			idx=i;
			break;
		}

	}

	//print_line("bucket pos: "+itos(idx));
	if (idx==-1) {
//		print_line("GETMSG: Not in Bucket!");
		return StringName();
	}

	if (bucket.elem[idx].comp_size == bucket.elem[idx].uncomp_size) {

		String rstr;
		rstr.parse_utf8(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].uncomp_size );
//		print_line("Uncompressed, size: "+itos(bucket.elem[idx].comp_size));
//		print_line("Return: "+rstr);

		return rstr;
	} else {

		CharString uncomp;
		uncomp.resize( bucket.elem[idx].uncomp_size+1 );
		smaz_decompress(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].comp_size,uncomp.ptr(),bucket.elem[idx].uncomp_size );
		String rstr;
		rstr.parse_utf8(uncomp.get_data());
//		print_line("Compressed, size: "+itos(bucket.elem[idx].comp_size));
//		print_line("Return: "+rstr);
		return rstr;
	}

}
예제 #9
0
void PHashTranslation::generate(const Ref<Translation> &p_from) {
#ifdef TOOLS_ENABLED
	List<StringName> keys;
	p_from->get_message_list(&keys);

	int size=Math::larger_prime(keys.size());


	print_line("compressing keys: "+itos(keys.size()));
	Vector< Vector< Pair<int,CharString> > > buckets;
	Vector< Map< uint32_t, int > > table;
	Vector< uint32_t > hfunc_table;
	Vector< _PHashTranslationCmp > compressed;

	table.resize(size);
	hfunc_table.resize(size);
	buckets.resize(size);
	compressed.resize(keys.size());

	int idx=0;
	int total_compression_size=0;
	int total_string_size=0;

	for(List<StringName>::Element *E=keys.front();E;E=E->next()) {

		//hash string
		CharString cs = E->get().operator String().utf8();
		uint32_t h = hash(0,cs.get_data());
		Pair<int,CharString> p;
		p.first=idx;
		p.second=cs;
		buckets[h % size].push_back(p);

		//compress string
		CharString src_s = p_from->get_message(E->get()).operator String().utf8();
		_PHashTranslationCmp ps;
		ps.orig_len=src_s.size();
		ps.offset=total_compression_size;

		if (ps.orig_len!=0) {
			CharString dst_s;
			dst_s.resize(src_s.size());
			int ret = smaz_compress(src_s.get_data(),src_s.size(),&dst_s[0],src_s.size());
			if (ret>=src_s.size()) {
				//if compressed is larger than original, just use original
				ps.orig_len=src_s.size();
				ps.compressed=src_s;
			} else {
				dst_s.resize(ret);
				//ps.orig_len=;
				ps.compressed=dst_s;
			}
		} else {
			ps.orig_len=1;
			ps.compressed.resize(1);
			ps.compressed[0]=0;
		}


		compressed[idx]=ps;
		total_compression_size+=ps.compressed.size();
		total_string_size+=src_s.size();
		idx++;
	}

	int bucket_table_size=0;
	print_line("total compressed string size: "+itos(total_compression_size)+" ("+itos(total_string_size)+" uncompressed).");

	for(int i=0;i<size;i++) {

		Vector< Pair<int,CharString> > &b = buckets[i];
		Map< uint32_t, int > &t=table[i];

		if (b.size()==0)
			continue;

		//print_line("bucket: "+itos(i)+" - elements: "+itos(b.size()));

		int d = 1;
		int item =0;

		while(item < b.size()) {

			uint32_t slot = hash(d,b[item].second.get_data());
			if (t.has(slot)) {

				item=0;
				d++;
				t.clear();
			} else {
				t[slot]=b[item].first;
				item++;
			}
		}

		hfunc_table[i]=d;
		bucket_table_size+=2+b.size()*4;

	}


	print_line("bucket table size: "+itos(bucket_table_size*4));
	print_line("hash table size: "+itos(size*4));

	hash_table.resize(size);
	bucket_table.resize(bucket_table_size);

	DVector<int>::Write htwb = hash_table.write();
	DVector<int>::Write btwb = bucket_table.write();

	uint32_t *htw = (uint32_t*)&htwb[0];
	uint32_t *btw = (uint32_t*)&btwb[0];

	int btindex=0;
	int collisions=0;

	for(int i=0;i<size;i++) {

		Map< uint32_t, int > &t=table[i];
		if (t.size()==0) {
			htw[i]=0xFFFFFFFF; //nothing
			continue;
		} else if (t.size()>1) {
			collisions+=t.size()-1;
		}

		htw[i]=btindex;
		btw[btindex++]=t.size();
		btw[btindex++]=hfunc_table[i];

		for( Map< uint32_t, int >::Element *E=t.front();E;E=E->next()) {

			btw[btindex++]=E->key();
			btw[btindex++]=compressed[E->get()].offset;
			btw[btindex++]=compressed[E->get()].compressed.size();
			btw[btindex++]=compressed[E->get()].orig_len;
		}

	}

	print_line("total collisions: "+itos(collisions));

	strings.resize(total_compression_size);
	DVector<uint8_t>::Write cw = strings.write();

	for(int i=0;i<compressed.size();i++) {
		memcpy(&cw[compressed[i].offset],compressed[i].compressed.get_data(),compressed[i].compressed.size());
	}


	ERR_FAIL_COND(btindex!=bucket_table_size);
	set_locale(p_from->get_locale());

#endif
}
예제 #10
0
void StreamPeer::put_utf8_string(const String &p_string) {

	CharString cs = p_string.utf8();
	put_data((const uint8_t *)cs.get_data(), cs.length());
}
예제 #11
0
파일: os_x11.cpp 프로젝트: ScyDev/godot
void OS_X11::process_xevents() {

	//printf("checking events %i\n", XPending(x11_display));

	bool do_mouse_warp=false;

	while (XPending(x11_display) > 0) {
		XEvent event;
		XNextEvent(x11_display, &event);

		switch (event.type) {
		case Expose:
			Main::force_redraw();
			break;

		case NoExpose:
			minimized = true;
			break;

		case VisibilityNotify: {

			XVisibilityEvent * visibility = (XVisibilityEvent *)&event;
			minimized = (visibility->state == VisibilityFullyObscured);

		} break;

		case FocusIn:
			main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
			if (mouse_mode==MOUSE_MODE_CAPTURED) {
				XGrabPointer(x11_display, x11_window, True,
						    ButtonPressMask | ButtonReleaseMask |
						    PointerMotionMask, GrabModeAsync, GrabModeAsync,
						    x11_window, None, CurrentTime);
			}
			break;

		case FocusOut:
			main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
			if (mouse_mode==MOUSE_MODE_CAPTURED) {
				//dear X11, I try, I really try, but you never work, you do whathever you want.
				XUngrabPointer(x11_display, CurrentTime);
			}
			break;

		case ConfigureNotify:
		/* call resizeGLScene only if our window-size changed */
		
			if ((event.xconfigure.width == current_videomode.width) && 
			(event.xconfigure.height == current_videomode.height))
				break;
				
			current_videomode.width=event.xconfigure.width;
			current_videomode.height=event.xconfigure.height;
			break;
		case ButtonPress:
		case ButtonRelease: {
			
			/* exit in case of a mouse button press */
			last_timestamp=event.xbutton.time;
			if (mouse_mode==MOUSE_MODE_CAPTURED) {
				event.xbutton.x=last_mouse_pos.x;
				event.xbutton.y=last_mouse_pos.y;
			}
			
			InputEvent mouse_event;
			mouse_event.ID=++event_id;
			mouse_event.type = InputEvent::MOUSE_BUTTON;
			mouse_event.device=0;
			mouse_event.mouse_button.mod = get_key_modifier_state(event.xbutton.state);
			mouse_event.mouse_button.button_mask = get_mouse_button_state(event.xbutton.state);
			mouse_event.mouse_button.x=event.xbutton.x;
			mouse_event.mouse_button.y=event.xbutton.y;
			mouse_event.mouse_button.global_x=event.xbutton.x;
			mouse_event.mouse_button.global_y=event.xbutton.y;
			mouse_event.mouse_button.button_index=event.xbutton.button;
			if (mouse_event.mouse_button.button_index==2)
				mouse_event.mouse_button.button_index=3;
			else if (mouse_event.mouse_button.button_index==3)
				mouse_event.mouse_button.button_index=2;
				
			mouse_event.mouse_button.pressed=(event.type==ButtonPress);


			if (event.type==ButtonPress && event.xbutton.button==1) {
				
				uint64_t diff = get_ticks_usec()/1000 - last_click_ms;

				if (diff<400 && Point2(last_click_pos).distance_to(Point2(event.xbutton.x,event.xbutton.y))<5) {
					
					last_click_ms=0;
					last_click_pos = Point2(-100,-100);
					mouse_event.mouse_button.doubleclick=true;					
					mouse_event.ID=++event_id;
					
				} else {
					last_click_ms+=diff;	
					last_click_pos = Point2(event.xbutton.x,event.xbutton.y);
				}
			}		

			input->parse_input_event( mouse_event);

			
		} break;	
		case MotionNotify: {
						
			
			last_timestamp=event.xmotion.time;
			
			// Motion is also simple.
			// A little hack is in order
			// to be able to send relative motion events.
			
			Point2i pos( event.xmotion.x, event.xmotion.y );

			if (mouse_mode==MOUSE_MODE_CAPTURED) {
#if 1
				Vector2 c = Point2i(current_videomode.width/2,current_videomode.height/2);
				if (pos==Point2i(current_videomode.width/2,current_videomode.height/2)) {
					//this sucks, it's a hack, etc and is a little inaccurate, etc.
					//but nothing I can do, X11 sucks.

					center=pos;
					break;
				}

				Point2i ncenter = pos;
				pos = last_mouse_pos + ( pos-center );
				center=ncenter;
				do_mouse_warp=true;
#else
				//Dear X11, thanks for making my life miserable

				center.x = current_videomode.width/2;
				center.y = current_videomode.height/2;
				pos = last_mouse_pos + ( pos-center );
				if (pos==last_mouse_pos)
					break;
				XWarpPointer(x11_display, None, x11_window,
					      0,0,0,0, (int)center.x, (int)center.y);
#endif

			}

			
			if (!last_mouse_pos_valid) {
				
				last_mouse_pos=pos;
				last_mouse_pos_valid=true;
			}
			
			Point2i rel = pos - last_mouse_pos;
			
			InputEvent motion_event;
			motion_event.ID=++event_id;
			motion_event.type=InputEvent::MOUSE_MOTION;
			motion_event.device=0;
			
			motion_event.mouse_motion.mod = get_key_modifier_state(event.xmotion.state);
			motion_event.mouse_motion.button_mask = get_mouse_button_state(event.xmotion.state);
			motion_event.mouse_motion.x=pos.x;
			motion_event.mouse_motion.y=pos.y;
			input->set_mouse_pos(pos);
			motion_event.mouse_motion.global_x=pos.x;
			motion_event.mouse_motion.global_y=pos.y;
			motion_event.mouse_motion.speed_x=input->get_mouse_speed().x;
			motion_event.mouse_motion.speed_y=input->get_mouse_speed().y;

			motion_event.mouse_motion.relative_x=rel.x;
			motion_event.mouse_motion.relative_y=rel.y;
						
			last_mouse_pos=pos;
			
			input->parse_input_event( motion_event);
			
		} break;			
		case KeyPress: 
		case KeyRelease: {

			last_timestamp=event.xkey.time;
				
			// key event is a little complex, so
			// it will be handled in it's own function.
			handle_key_event( (XKeyEvent*)&event );
		} break;			
		case SelectionRequest: {

			XSelectionRequestEvent *req;
			XEvent e, respond;
			e = event;

			req=&(e.xselectionrequest);
			if (req->target == XA_STRING || req->target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) ||
				req->target == XInternAtom(x11_display, "UTF8_STRING", 0))
			{
				CharString clip = OS::get_clipboard().utf8();
				XChangeProperty (x11_display,
					req->requestor,
					req->property,
					req->target,
					8,
					PropModeReplace,
					(unsigned char*)clip.get_data(),
					clip.length());
				respond.xselection.property=req->property;
			} else if (req->target == XInternAtom(x11_display, "TARGETS", 0)) {

				Atom data[2];
				data[0] = XInternAtom(x11_display, "UTF8_STRING", 0);
				data[1] = XA_STRING;
				XChangeProperty (x11_display, req->requestor, req->property, req->target,
						 8, PropModeReplace, (unsigned char *) &data,
						 sizeof (data));
				respond.xselection.property=req->property;

			} else {
				printf ("No String %x\n",
					(int)req->target);
				respond.xselection.property= None;
			}
			respond.xselection.type= SelectionNotify;
			respond.xselection.display= req->display;
			respond.xselection.requestor= req->requestor;
			respond.xselection.selection=req->selection;
			respond.xselection.target= req->target;
			respond.xselection.time = req->time;
			XSendEvent (x11_display, req->requestor,0,0,&respond);
			XFlush (x11_display);
		} break;


		case ClientMessage:    
		
			if ((unsigned int)event.xclient.data.l[0]==(unsigned int)wm_delete)
				main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
			break;
		default:
			break;
		}
	}
	
	XFlush(x11_display);

	if (do_mouse_warp) {

		XWarpPointer(x11_display, None, x11_window,
			      0,0,0,0, (int)current_videomode.width/2, (int)current_videomode.height/2);

	}
}
예제 #12
0
void OSIPhone::alert(const String &p_alert, const String &p_title) {

	const CharString utf8_alert = p_alert.utf8();
	const CharString utf8_title = p_title.utf8();
	iOS::alert(utf8_alert.get_data(), utf8_title.get_data());
}
예제 #13
0
void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) {

	if (network_peer.is_null()) {
		ERR_EXPLAIN("Attempt to remote call/set when networking is not active in SceneTree.");
		ERR_FAIL();
	}

	if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING) {
		ERR_EXPLAIN("Attempt to remote call/set when networking is not connected yet in SceneTree.");
		ERR_FAIL();
	}

	if (network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) {
		ERR_EXPLAIN("Attempt to remote call/set when networking is disconnected.");
		ERR_FAIL();
	}

	if (p_argcount > 255) {
		ERR_EXPLAIN("Too many arguments >255.");
		ERR_FAIL();
	}

	if (p_to != 0 && !connected_peers.has(ABS(p_to))) {
		if (p_to == network_peer->get_unique_id()) {
			ERR_EXPLAIN("Attempt to remote call/set yourself! unique ID: " + itos(network_peer->get_unique_id()));
		} else {
			ERR_EXPLAIN("Attempt to remote call unexisting ID: " + itos(p_to));
		}

		ERR_FAIL();
	}

	NodePath from_path = (root_node->get_path()).rel_path_to(p_from->get_path());
	ERR_EXPLAIN("Unable to send RPC. Relative path is empty. THIS IS LIKELY A BUG IN THE ENGINE!");
	ERR_FAIL_COND(from_path.is_empty());

	// See if the path is cached.
	PathSentCache *psc = path_send_cache.getptr(from_path);
	if (!psc) {
		// Path is not cached, create.
		path_send_cache[from_path] = PathSentCache();
		psc = path_send_cache.getptr(from_path);
		psc->id = last_send_cache_id++;
	}

	// Create base packet, lots of hardcode because it must be tight.

	int ofs = 0;

#define MAKE_ROOM(m_amount) \
	if (packet_cache.size() < m_amount) packet_cache.resize(m_amount);

	// Encode type.
	MAKE_ROOM(1);
	packet_cache.write[0] = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL;
	ofs += 1;

	// Encode ID.
	MAKE_ROOM(ofs + 4);
	encode_uint32(psc->id, &(packet_cache.write[ofs]));
	ofs += 4;

	// Encode function name.
	CharString name = String(p_name).utf8();
	int len = encode_cstring(name.get_data(), NULL);
	MAKE_ROOM(ofs + len);
	encode_cstring(name.get_data(), &(packet_cache.write[ofs]));
	ofs += len;

	if (p_set) {
		// Set argument.
		Error err = encode_variant(*p_arg[0], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed());
		ERR_EXPLAIN("Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!");
		ERR_FAIL_COND(err != OK);
		MAKE_ROOM(ofs + len);
		encode_variant(*p_arg[0], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed());
		ofs += len;

	} else {
		// Call arguments.
		MAKE_ROOM(ofs + 1);
		packet_cache.write[ofs] = p_argcount;
		ofs += 1;
		for (int i = 0; i < p_argcount; i++) {
			Error err = encode_variant(*p_arg[i], NULL, len, allow_object_decoding || network_peer->is_object_decoding_allowed());
			ERR_EXPLAIN("Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
			ERR_FAIL_COND(err != OK);
			MAKE_ROOM(ofs + len);
			encode_variant(*p_arg[i], &(packet_cache.write[ofs]), len, allow_object_decoding || network_peer->is_object_decoding_allowed());
			ofs += len;
		}
	}

	// See if all peers have cached path (is so, call can be fast).
	bool has_all_peers = _send_confirm_path(from_path, psc, p_to);

	// Take chance and set transfer mode, since all send methods will use it.
	network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);

	if (has_all_peers) {

		// They all have verified paths, so send fast.
		network_peer->set_target_peer(p_to); // To all of you.
		network_peer->put_packet(packet_cache.ptr(), ofs); // A message with love.
	} else {
		// Not all verified path, so send one by one.

		// Append path at the end, since we will need it for some packets.
		CharString pname = String(from_path).utf8();
		int path_len = encode_cstring(pname.get_data(), NULL);
		MAKE_ROOM(ofs + path_len);
		encode_cstring(pname.get_data(), &(packet_cache.write[ofs]));

		for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) {

			if (p_to < 0 && E->get() == -p_to)
				continue; // Continue, excluded.

			if (p_to > 0 && E->get() != p_to)
				continue; // Continue, not for this peer.

			Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get());
			ERR_CONTINUE(!F); // Should never happen.

			network_peer->set_target_peer(E->get()); // To this one specifically.

			if (F->get()) {
				// This one confirmed path, so use id.
				encode_uint32(psc->id, &(packet_cache.write[1]));
				network_peer->put_packet(packet_cache.ptr(), ofs);
			} else {
				// This one did not confirm path yet, so use entire path (sorry!).
				encode_uint32(0x80000000 | ofs, &(packet_cache.write[1])); // Offset to path and flag.
				network_peer->put_packet(packet_cache.ptr(), ofs + path_len);
			}
		}
	}
}
예제 #14
0
void OS_X11::process_xevents() {

	//printf("checking events %i\n", XPending(x11_display));

	do_mouse_warp=false;

	while (XPending(x11_display) > 0) {
		XEvent event;
		XNextEvent(x11_display, &event);

		switch (event.type) {
		case Expose:
			Main::force_redraw();
			break;

		case NoExpose:
			minimized = true;
			break;

		case VisibilityNotify: {
			XVisibilityEvent * visibility = (XVisibilityEvent *)&event;
			minimized = (visibility->state == VisibilityFullyObscured);
		} break;
		case LeaveNotify: {

			if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED)
				main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
			if (input)
				input->set_mouse_in_window(false);

		} break;
		case EnterNotify: {

			if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED)
				main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
			if (input)
				input->set_mouse_in_window(true);
		} break;
		case FocusIn:
			minimized = false;
#ifdef NEW_WM_API
			if(current_videomode.fullscreen) {
				set_wm_fullscreen(true);
			}
#endif
			main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
			if (mouse_mode==MOUSE_MODE_CAPTURED) {
				XGrabPointer(x11_display, x11_window, True,
						    ButtonPressMask | ButtonReleaseMask |
						    PointerMotionMask, GrabModeAsync, GrabModeAsync,
						    x11_window, None, CurrentTime);
			}
			break;

		case FocusOut:
#ifdef NEW_WM_API
			if(current_videomode.fullscreen) {
				set_wm_fullscreen(false);
				set_window_minimized(true);
			}
#endif
			main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
			if (mouse_mode==MOUSE_MODE_CAPTURED) {
				//dear X11, I try, I really try, but you never work, you do whathever you want.
				XUngrabPointer(x11_display, CurrentTime);
			}
			break;

		case ConfigureNotify:
		/* call resizeGLScene only if our window-size changed */

			if ((event.xconfigure.width == current_videomode.width) &&
			(event.xconfigure.height == current_videomode.height))
				break;

			current_videomode.width=event.xconfigure.width;
			current_videomode.height=event.xconfigure.height;
			break;
		case ButtonPress:
		case ButtonRelease: {

			/* exit in case of a mouse button press */
			last_timestamp=event.xbutton.time;
			if (mouse_mode==MOUSE_MODE_CAPTURED) {
				event.xbutton.x=last_mouse_pos.x;
				event.xbutton.y=last_mouse_pos.y;
			}

			InputEvent mouse_event;
			mouse_event.ID=++event_id;
			mouse_event.type = InputEvent::MOUSE_BUTTON;
			mouse_event.device=0;
			mouse_event.mouse_button.mod = get_key_modifier_state(event.xbutton.state);
			mouse_event.mouse_button.button_mask = get_mouse_button_state(event.xbutton.state);
			mouse_event.mouse_button.x=event.xbutton.x;
			mouse_event.mouse_button.y=event.xbutton.y;
			mouse_event.mouse_button.global_x=event.xbutton.x;
			mouse_event.mouse_button.global_y=event.xbutton.y;
			mouse_event.mouse_button.button_index=event.xbutton.button;
			if (mouse_event.mouse_button.button_index==2)
				mouse_event.mouse_button.button_index=3;
			else if (mouse_event.mouse_button.button_index==3)
				mouse_event.mouse_button.button_index=2;

			mouse_event.mouse_button.pressed=(event.type==ButtonPress);


			if (event.type==ButtonPress && event.xbutton.button==1) {

				uint64_t diff = get_ticks_usec()/1000 - last_click_ms;

				if (diff<400 && Point2(last_click_pos).distance_to(Point2(event.xbutton.x,event.xbutton.y))<5) {

					last_click_ms=0;
					last_click_pos = Point2(-100,-100);
					mouse_event.mouse_button.doubleclick=true;
					mouse_event.ID=++event_id;

				} else {
					last_click_ms+=diff;
					last_click_pos = Point2(event.xbutton.x,event.xbutton.y);
				}
			}

			input->parse_input_event( mouse_event);


		} break;
		case MotionNotify: {

			// F**K YOU X11 API YOU SERIOUSLY GROSS ME OUT
			// YOU ARE AS GROSS AS LOOKING AT A PUTRID PILE
			// OF POOP STICKING OUT OF A CLOGGED TOILET
			// HOW THE F**K I AM SUPPOSED TO KNOW WHICH ONE
			// OF THE MOTION NOTIFY EVENTS IS THE ONE GENERATED
			// BY WARPING THE MOUSE POINTER?
			// YOU ARE FORCING ME TO FILTER ONE BY ONE TO FIND IT
			// PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL
			// MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG.


			while(true) {
				if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) {
					//this is likely the warp event since it was warped here
					center=Vector2(event.xmotion.x,event.xmotion.y);
					break;
				}

				if (XPending(x11_display) > 0) {
					XEvent tevent;
					XPeekEvent(x11_display, &tevent);
					if (tevent.type==MotionNotify) {
						XNextEvent(x11_display,&event);
					} else {
						break;
					}
				} else {
					break;
				}
			}

			last_timestamp=event.xmotion.time;

			// Motion is also simple.
			// A little hack is in order
			// to be able to send relative motion events.
			Point2i pos( event.xmotion.x, event.xmotion.y );

			if (mouse_mode==MOUSE_MODE_CAPTURED) {
#if 1
				//Vector2 c = Point2i(current_videomode.width/2,current_videomode.height/2);
				if (pos==Point2i(current_videomode.width/2,current_videomode.height/2)) {
					//this sucks, it's a hack, etc and is a little inaccurate, etc.
					//but nothing I can do, X11 sucks.

					center=pos;
					break;
				}

				Point2i new_center = pos;
				pos = last_mouse_pos + ( pos - center );
				center=new_center;
				do_mouse_warp=true;
#else
				//Dear X11, thanks for making my life miserable

				center.x = current_videomode.width/2;
				center.y = current_videomode.height/2;
				pos = last_mouse_pos + ( pos-center );
				if (pos==last_mouse_pos)
					break;
				XWarpPointer(x11_display, None, x11_window,
					      0,0,0,0, (int)center.x, (int)center.y);
#endif
			}

			if (!last_mouse_pos_valid) {

				last_mouse_pos=pos;
				last_mouse_pos_valid=true;
			}

			Point2i rel = pos - last_mouse_pos;

#ifdef NEW_WM_API
			if (mouse_mode==MOUSE_MODE_CAPTURED) {
				pos.x = current_videomode.width / 2;
				pos.y = current_videomode.height / 2;
			}
#endif

			InputEvent motion_event;
			motion_event.ID=++event_id;
			motion_event.type=InputEvent::MOUSE_MOTION;
			motion_event.device=0;

			motion_event.mouse_motion.mod = get_key_modifier_state(event.xmotion.state);
			motion_event.mouse_motion.button_mask = get_mouse_button_state(event.xmotion.state);
			motion_event.mouse_motion.x=pos.x;
			motion_event.mouse_motion.y=pos.y;
			input->set_mouse_pos(pos);
			motion_event.mouse_motion.global_x=pos.x;
			motion_event.mouse_motion.global_y=pos.y;
			motion_event.mouse_motion.speed_x=input->get_mouse_speed().x;
			motion_event.mouse_motion.speed_y=input->get_mouse_speed().y;

			motion_event.mouse_motion.relative_x=rel.x;
			motion_event.mouse_motion.relative_y=rel.y;

			last_mouse_pos=pos;

			// printf("rel: %d,%d\n", rel.x, rel.y );

			input->parse_input_event( motion_event);

		} break;
		case KeyPress:
		case KeyRelease: {

			last_timestamp=event.xkey.time;

			// key event is a little complex, so
			// it will be handled in it's own function.
			handle_key_event( (XKeyEvent*)&event );
		} break;
		case SelectionRequest: {

			XSelectionRequestEvent *req;
			XEvent e, respond;
			e = event;

			req=&(e.xselectionrequest);
			if (req->target == XA_STRING || req->target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) ||
				req->target == XInternAtom(x11_display, "UTF8_STRING", 0))
			{
				CharString clip = OS::get_clipboard().utf8();
				XChangeProperty (x11_display,
					req->requestor,
					req->property,
					req->target,
					8,
					PropModeReplace,
					(unsigned char*)clip.get_data(),
					clip.length());
				respond.xselection.property=req->property;
			} else if (req->target == XInternAtom(x11_display, "TARGETS", 0)) {

				Atom data[2];
				data[0] = XInternAtom(x11_display, "UTF8_STRING", 0);
				data[1] = XA_STRING;
				XChangeProperty (x11_display, req->requestor, req->property, req->target,
						 8, PropModeReplace, (unsigned char *) &data,
						 sizeof (data));
				respond.xselection.property=req->property;

			} else {
				printf ("No String %x\n",
					(int)req->target);
				respond.xselection.property= None;
			}
			respond.xselection.type= SelectionNotify;
			respond.xselection.display= req->display;
			respond.xselection.requestor= req->requestor;
			respond.xselection.selection=req->selection;
			respond.xselection.target= req->target;
			respond.xselection.time = req->time;
			XSendEvent (x11_display, req->requestor,0,0,&respond);
			XFlush (x11_display);
		} break;


		case ClientMessage:

			if ((unsigned int)event.xclient.data.l[0]==(unsigned int)wm_delete)
				main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
			break;
		default:
			break;
		}
	}

	XFlush(x11_display);

	if (do_mouse_warp) {

		XWarpPointer(x11_display, None, x11_window,
		 	      0,0,0,0, (int)current_videomode.width/2, (int)current_videomode.height/2);

		/*
		Window root, child;
		int root_x, root_y;
		int win_x, win_y;
		unsigned int mask;
		XQueryPointer( x11_display, x11_window, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask );

		printf("Root: %d,%d\n", root_x, root_y);
		printf("Win: %d,%d\n", win_x, win_y);
		*/
	}
}
Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, const Ref<EditorExportPlatform> &p_platform) {


	Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);

	if (rimd.is_null()) {

		StringName group = EditorImportExport::get_singleton()->image_get_export_group(p_path);

		if (group!=StringName()) {
			//handled by export group
			rimd = Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) );

			int group_format=0;
			float group_lossy_quality=EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(group);
			int group_shrink=EditorImportExport::get_singleton()->image_export_group_get_shrink(group);
			group_shrink*=EditorImportExport::get_singleton()->get_export_image_shrink();

			switch(EditorImportExport::get_singleton()->image_export_group_get_image_action(group)) {
				case EditorImportExport::IMAGE_ACTION_NONE: {

					switch(EditorImportExport::get_singleton()->get_export_image_action()) {
						case EditorImportExport::IMAGE_ACTION_NONE: {

							group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS; //?

						} break; //use default
						case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
							group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
						} break; //use default
						case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
							group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
						} break; //use default
					}

					group_lossy_quality=EditorImportExport::get_singleton()->get_export_image_quality();

				} break; //use default
				case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
					group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
				} break; //use default
				case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
					group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
				} break; //use default
			}


			int flags=0;

			if (Globals::get_singleton()->get("texture_import/filter"))
				flags|=IMAGE_FLAG_FILTER;
			if (!Globals::get_singleton()->get("texture_import/gen_mipmaps"))
				flags|=IMAGE_FLAG_NO_MIPMAPS;
			if (!Globals::get_singleton()->get("texture_import/repeat"))
				flags|=IMAGE_FLAG_REPEAT;

			flags|=IMAGE_FLAG_FIX_BORDER_ALPHA;

			print_line("group format"+itos(group_format));
			rimd->set_option("format",group_format);
			rimd->set_option("flags",flags);
			rimd->set_option("quality",group_lossy_quality);
			rimd->set_option("atlas",false);
			rimd->set_option("shrink",group_shrink);
			rimd->add_source(EditorImportPlugin::validate_source_path(p_path));

		} else if (EditorImportExport::get_singleton()->get_image_formats().has(p_path.extension().to_lower()) && EditorImportExport::get_singleton()->get_export_image_action()!=EditorImportExport::IMAGE_ACTION_NONE) {
			//handled by general image export settings

			rimd = Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) );

			switch(EditorImportExport::get_singleton()->get_export_image_action()) {
				case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: rimd->set_option("format",IMAGE_FORMAT_COMPRESS_DISK_LOSSY); break;
				case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: rimd->set_option("format",IMAGE_FORMAT_COMPRESS_RAM); break;
			}

			int flags=0;

			if (Globals::get_singleton()->get("texture_import/filter"))
				flags|=IMAGE_FLAG_FILTER;
			if (!Globals::get_singleton()->get("texture_import/gen_mipmaps"))
				flags|=IMAGE_FLAG_NO_MIPMAPS;
			if (!Globals::get_singleton()->get("texture_import/repeat"))
				flags|=IMAGE_FLAG_REPEAT;

			flags|=IMAGE_FLAG_FIX_BORDER_ALPHA;

			rimd->set_option("shrink",EditorImportExport::get_singleton()->get_export_image_shrink());
			rimd->set_option("flags",flags);
			rimd->set_option("quality",EditorImportExport::get_singleton()->get_export_image_quality());
			rimd->set_option("atlas",false);
			rimd->add_source(EditorImportPlugin::validate_source_path(p_path));

		} else {
			return Vector<uint8_t>();
		}
	}

	int fmt = rimd->get_option("format");

	if (fmt!=IMAGE_FORMAT_COMPRESS_RAM && fmt!=IMAGE_FORMAT_COMPRESS_DISK_LOSSY)  {
		print_line("no compress ram or lossy");
		return Vector<uint8_t>(); //pointless to do anything, since no need to reconvert
	}

	uint32_t flags = rimd->get_option("flags");
	uint8_t shrink = rimd->has_option("shrink") ? rimd->get_option("shrink"): Variant(1);
	uint8_t format = rimd->get_option("format");
	uint8_t comp = (format==EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM)?uint8_t(p_platform->get_image_compression()):uint8_t(255);

	MD5_CTX ctx;
	uint8_t f4[4];
	encode_uint32(flags,&f4[0]);
	MD5Init(&ctx);
	String gp = Globals::get_singleton()->globalize_path(p_path);
	CharString cs = gp.utf8();
	MD5Update(&ctx,(unsigned char*)cs.get_data(),cs.length());
	MD5Update(&ctx,f4,4);
	MD5Update(&ctx,&format,1);
	MD5Update(&ctx,&comp,1);
	MD5Update(&ctx,&shrink,1);
	MD5Final(&ctx);

	uint64_t sd=0;
	String smd5;

	String md5 = String::md5(ctx.digest);

	String tmp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/");

	bool valid=false;
	{
		//if existing, make sure it's valid
		FileAccessRef f = FileAccess::open(tmp_path+"imgexp-"+md5+".txt",FileAccess::READ);
		if (f) {

			uint64_t d = f->get_line().strip_edges().to_int64();
			sd = FileAccess::get_modified_time(p_path);

			if (d==sd) {
				valid=true;
			} else {
				String cmd5 = f->get_line().strip_edges();
				smd5 = FileAccess::get_md5(p_path);
				if (cmd5==smd5) {
					valid=true;
				}
			}


		}
	}

	if (!valid) {
		//cache failed, convert
		Error err = import2(tmp_path+"imgexp-"+md5+".tex",rimd,p_platform->get_image_compression(),true);
		ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
		FileAccessRef f = FileAccess::open(tmp_path+"imgexp-"+md5+".txt",FileAccess::WRITE);

		if (sd==0)
			sd = FileAccess::get_modified_time(p_path);
		if (smd5==String())
			smd5 = FileAccess::get_md5(p_path);

		f->store_line(String::num(sd));
		f->store_line(smd5);
		f->store_line(gp); //source path for reference
	}


	Vector<uint8_t> ret;
	FileAccessRef f = FileAccess::open(tmp_path+"imgexp-"+md5+".tex",FileAccess::READ);
	ERR_FAIL_COND_V(!f,ret);

	ret.resize(f->get_len());
	f->get_buffer(ret.ptr(),ret.size());

	return ret;
}