Example #1
0
bool GridMap::_set(const StringName &p_name, const Variant &p_value) {

	String name = p_name;

	if (name == "theme") {

		set_theme(p_value);
	} else if (name == "cell_size") {
		if (p_value.get_type() == Variant::INT || p_value.get_type() == Variant::REAL) {
			//compatibility
			float cs = p_value;
			set_cell_size(Vector3(cs, cs, cs));
		} else {
			set_cell_size(p_value);
		}
	} else if (name == "cell_octant_size") {
		set_octant_size(p_value);
	} else if (name == "cell_center_x") {
		set_center_x(p_value);
	} else if (name == "cell_center_y") {
		set_center_y(p_value);
	} else if (name == "cell_center_z") {
		set_center_z(p_value);
	} else if (name == "cell_scale") {
		set_cell_scale(p_value);
		/*	} else if (name=="cells") {
		PoolVector<int> cells = p_value;
		int amount=cells.size();
		PoolVector<int>::Read r = cells.read();
		ERR_FAIL_COND_V(amount&1,false); // not even
		cell_map.clear();
		for(int i=0;i<amount/3;i++) {


			IndexKey ik;
			ik.key=decode_uint64(&r[i*3]);
			Cell cell;
			cell.cell=uint32_t(r[i*+1]);
			cell_map[ik]=cell;

		}
		_recreate_octant_data();*/
	} else if (name == "data") {

		Dictionary d = p_value;

		if (d.has("cells")) {

			PoolVector<int> cells = d["cells"];
			int amount = cells.size();
			PoolVector<int>::Read r = cells.read();
			ERR_FAIL_COND_V(amount % 3, false); // not even
			cell_map.clear();
			for (int i = 0; i < amount / 3; i++) {

				IndexKey ik;
				ik.key = decode_uint64((const uint8_t *)&r[i * 3]);
				Cell cell;
				cell.cell = decode_uint32((const uint8_t *)&r[i * 3 + 2]);
				cell_map[ik] = cell;
			}
		}
		_recreate_octant_data();

	} else
		return false;

	return true;
}
Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) {

	Ref<Sample> smp =p_from;
	ERR_FAIL_COND_V(smp.is_null(),Ref<Texture>());


	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
	thumbnail_size*=EDSCALE;
	PoolVector<uint8_t> img;
	int w = thumbnail_size;
	int h = thumbnail_size;
	img.resize(w*h*3);

	PoolVector<uint8_t>::Write imgdata = img.write();
	uint8_t * imgw = imgdata.ptr();
	PoolVector<uint8_t> data = smp->get_data();
	PoolVector<uint8_t>::Read sampledata = data.read();
	const uint8_t *sdata=sampledata.ptr();

	bool stereo = smp->is_stereo();
	bool _16=smp->get_format()==Sample::FORMAT_PCM16;
	int len = smp->get_length();

	if (len<1)
		return Ref<Texture>();

	if (smp->get_format()==Sample::FORMAT_IMA_ADPCM) {

		struct IMA_ADPCM_State {

			int16_t step_index;
			int32_t predictor;
			/* values at loop point */
			int16_t loop_step_index;
			int32_t loop_predictor;
			int32_t last_nibble;
			int32_t loop_pos;
			int32_t window_ofs;
			const uint8_t *ptr;
		} ima_adpcm;

		ima_adpcm.step_index=0;
		ima_adpcm.predictor=0;
		ima_adpcm.loop_step_index=0;
		ima_adpcm.loop_predictor=0;
		ima_adpcm.last_nibble=-1;
		ima_adpcm.loop_pos=0x7FFFFFFF;
		ima_adpcm.window_ofs=0;
		ima_adpcm.ptr=NULL;


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

			float max[2]={-1e10,-1e10};
			float min[2]={1e10,1e10};
			int from = i*len/w;
			int to = (i+1)*len/w;
			if (to>=len)
				to=len-1;

			for(int j=from;j<to;j++) {

				while(j>ima_adpcm.last_nibble) {

					static const int16_t _ima_adpcm_step_table[89] = {
						7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
						19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
						50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
						130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
						337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
						876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
						2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
						5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
						15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
					};

					static const int8_t _ima_adpcm_index_table[16] = {
						-1, -1, -1, -1, 2, 4, 6, 8,
						-1, -1, -1, -1, 2, 4, 6, 8
					};

					int16_t nibble,diff,step;

					ima_adpcm.last_nibble++;
					const uint8_t *src_ptr=sdata;

					int ofs = ima_adpcm.last_nibble>>1;

					if (stereo)
						ofs*=2;


					nibble = (ima_adpcm.last_nibble&1)?
							(src_ptr[ofs]>>4):(src_ptr[ofs]&0xF);
					step=_ima_adpcm_step_table[ima_adpcm.step_index];

					ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
					if (ima_adpcm.step_index<0)
						ima_adpcm.step_index=0;
					if (ima_adpcm.step_index>88)
						ima_adpcm.step_index=88;

					diff = step >> 3 ;
					if (nibble & 1)
						diff += step >> 2 ;
					if (nibble & 2)
						diff += step >> 1 ;
					if (nibble & 4)
						diff += step ;
					if (nibble & 8)
						diff = -diff ;

					ima_adpcm.predictor+=diff;
					if (ima_adpcm.predictor<-0x8000)
						ima_adpcm.predictor=-0x8000;
					else if (ima_adpcm.predictor>0x7FFF)
						ima_adpcm.predictor=0x7FFF;


					/* store loop if there */
					if (ima_adpcm.last_nibble==ima_adpcm.loop_pos) {

						ima_adpcm.loop_step_index = ima_adpcm.step_index;
						ima_adpcm.loop_predictor = ima_adpcm.predictor;
					}

				}

				float v=ima_adpcm.predictor/32767.0;
				if (v>max[0])
					max[0]=v;
				if (v<min[0])
					min[0]=v;
			}
			max[0]*=0.8;
			min[0]*=0.8;

			for(int j=0;j<h;j++) {
				float v = (j/(float)h) * 2.0 - 1.0;
				uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3];
				if (v>min[0] && v<max[0]) {
					imgofs[0]=255;
					imgofs[1]=150;
					imgofs[2]=80;
				} else {
					imgofs[0]=0;
					imgofs[1]=0;
					imgofs[2]=0;
				}
			}
		}
	} else {
		for(int i=0;i<w;i++) {
Example #3
0
	virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {

		print_line("attempt to call " + String(p_method));

		r_error.error = Variant::CallError::CALL_OK;

		Map<StringName, MethodData>::Element *E = method_map.find(p_method);
		if (!E) {

			print_line("no exists");
			r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
			return Variant();
		}

		int ac = E->get().argtypes.size();
		if (ac < p_argcount) {

			print_line("fewargs");
			r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
			r_error.argument = ac;
			return Variant();
		}

		if (ac > p_argcount) {

			print_line("manyargs");
			r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
			r_error.argument = ac;
			return Variant();
		}

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

			if (!Variant::can_convert(p_args[i]->get_type(), E->get().argtypes[i])) {

				r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
				r_error.argument = i;
				r_error.expected = E->get().argtypes[i];
			}
		}

		jvalue *v = NULL;

		if (p_argcount) {

			v = (jvalue *)alloca(sizeof(jvalue) * p_argcount);
		}

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

			switch (E->get().argtypes[i]) {

				case Variant::BOOL: {

					v[i].z = *p_args[i];
				} break;
				case Variant::INT: {

					v[i].i = *p_args[i];
				} break;
				case Variant::REAL: {

					v[i].f = *p_args[i];
				} break;
				case Variant::STRING: {

					String s = *p_args[i];
					jstring jStr = env->NewStringUTF(s.utf8().get_data());
					v[i].l = jStr;
				} break;
				case Variant::STRING_ARRAY: {

					PoolVector<String> sarray = *p_args[i];
					jobjectArray arr = env->NewObjectArray(sarray.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));

					for (int j = 0; j < sarray.size(); j++) {

						env->SetObjectArrayElement(arr, j, env->NewStringUTF(sarray[i].utf8().get_data()));
					}
					v[i].l = arr;

				} break;
				case Variant::INT_ARRAY: {

					PoolVector<int> array = *p_args[i];
					jintArray arr = env->NewIntArray(array.size());
					PoolVector<int>::Read r = array.read();
					env->SetIntArrayRegion(arr, 0, array.size(), r.ptr());
					v[i].l = arr;

				} break;
				case Variant::REAL_ARRAY: {

					PoolVector<float> array = *p_args[i];
					jfloatArray arr = env->NewFloatArray(array.size());
					PoolVector<float>::Read r = array.read();
					env->SetFloatArrayRegion(arr, 0, array.size(), r.ptr());
					v[i].l = arr;

				} break;
				default: {

					ERR_FAIL_V(Variant());
				} break;
			}
		}

		print_line("calling method!!");

		Variant ret;

		switch (E->get().ret_type) {

			case Variant::NIL: {

				print_line("call void");
				env->CallVoidMethodA(instance, E->get().method, v);
			} break;
			case Variant::BOOL: {

				ret = env->CallBooleanMethodA(instance, E->get().method, v);
				print_line("call bool");
			} break;
			case Variant::INT: {

				ret = env->CallIntMethodA(instance, E->get().method, v);
				print_line("call int");
			} break;
			case Variant::REAL: {

				ret = env->CallFloatMethodA(instance, E->get().method, v);
			} break;
			case Variant::STRING: {

				jobject o = env->CallObjectMethodA(instance, E->get().method, v);
				String singname = env->GetStringUTFChars((jstring)o, NULL);
			} break;
			case Variant::STRING_ARRAY: {

				jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance, E->get().method, v);

				int stringCount = env->GetArrayLength(arr);
				PoolVector<String> sarr;

				for (int i = 0; i < stringCount; i++) {
					jstring string = (jstring)env->GetObjectArrayElement(arr, i);
					const char *rawString = env->GetStringUTFChars(string, 0);
					sarr.push_back(String(rawString));
				}

				ret = sarr;

			} break;
			case Variant::INT_ARRAY: {

				jintArray arr = (jintArray)env->CallObjectMethodA(instance, E->get().method, v);

				int fCount = env->GetArrayLength(arr);
				PoolVector<int> sarr;
				sarr.resize(fCount);

				PoolVector<int>::Write w = sarr.write();
				env->GetIntArrayRegion(arr, 0, fCount, w.ptr());
				w = PoolVector<int>::Write();
				ret = sarr;
			} break;
			case Variant::REAL_ARRAY: {

				jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance, E->get().method, v);

				int fCount = env->GetArrayLength(arr);
				PoolVector<float> sarr;
				sarr.resize(fCount);

				PoolVector<float>::Write w = sarr.write();
				env->GetFloatArrayRegion(arr, 0, fCount, w.ptr());
				w = PoolVector<float>::Write();
				ret = sarr;
			} break;
			default: {

				print_line("failure..");
				ERR_FAIL_V(Variant());
			} break;
		}

		print_line("success");

		return ret;
	}
Example #4
0
void TriangleMesh::create(const PoolVector<Vector3> &p_faces) {

	valid = false;

	int fc = p_faces.size();
	ERR_FAIL_COND(!fc || ((fc % 3) != 0));
	fc /= 3;
	triangles.resize(fc);

	bvh.resize(fc * 3); //will never be larger than this (todo make better)
	PoolVector<BVH>::Write bw = bvh.write();

	{

		//create faces and indices and base bvh
		//except for the Set for repeated triangles, everything
		//goes in-place.

		PoolVector<Vector3>::Read r = p_faces.read();
		PoolVector<Triangle>::Write w = triangles.write();
		Map<Vector3, int> db;

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

			Triangle &f = w[i];
			const Vector3 *v = &r[i * 3];

			for (int j = 0; j < 3; j++) {

				int vidx = -1;
				Vector3 vs = v[j].snapped(Vector3(0.0001, 0.0001, 0.0001));
				Map<Vector3, int>::Element *E = db.find(vs);
				if (E) {
					vidx = E->get();
				} else {
					vidx = db.size();
					db[vs] = vidx;
				}

				f.indices[j] = vidx;
				if (j == 0)
					bw[i].aabb.position = vs;
				else
					bw[i].aabb.expand_to(vs);
			}

			f.normal = Face3(r[i * 3 + 0], r[i * 3 + 1], r[i * 3 + 2]).get_plane().get_normal();

			bw[i].left = -1;
			bw[i].right = -1;
			bw[i].face_index = i;
			bw[i].center = bw[i].aabb.position + bw[i].aabb.size * 0.5;
		}

		vertices.resize(db.size());
		PoolVector<Vector3>::Write vw = vertices.write();
		for (Map<Vector3, int>::Element *E = db.front(); E; E = E->next()) {
			vw[E->get()] = E->key();
		}
	}

	PoolVector<BVH *> bwptrs;
	bwptrs.resize(fc);
	PoolVector<BVH *>::Write bwp = bwptrs.write();
	for (int i = 0; i < fc; i++) {

		bwp[i] = &bw[i];
	}

	max_depth = 0;
	int max_alloc = fc;
	_create_bvh(bw.ptr(), bwp.ptr(), 0, fc, 1, max_depth, max_alloc);

	bw = PoolVector<BVH>::Write(); //clearup
	bvh.resize(max_alloc); //resize back

	valid = true;
}
Example #5
0
Ref<Mesh> NavigationMesh::get_debug_mesh() {

	if (debug_mesh.is_valid())
		return debug_mesh;

	PoolVector<Vector3> vertices = get_vertices();
	PoolVector<Vector3>::Read vr = vertices.read();
	List<Face3> faces;
	for (int i = 0; i < get_polygon_count(); i++) {
		Vector<int> p = get_polygon(i);

		for (int j = 2; j < p.size(); j++) {
			Face3 f;
			f.vertex[0] = vr[p[0]];
			f.vertex[1] = vr[p[j - 1]];
			f.vertex[2] = vr[p[j]];

			faces.push_back(f);
		}
	}

	Map<_EdgeKey, bool> edge_map;
	PoolVector<Vector3> tmeshfaces;
	tmeshfaces.resize(faces.size() * 3);

	{
		PoolVector<Vector3>::Write tw = tmeshfaces.write();
		int tidx = 0;

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

			const Face3 &f = E->get();

			for (int j = 0; j < 3; j++) {

				tw[tidx++] = f.vertex[j];
				_EdgeKey ek;
				ek.from = f.vertex[j].snapped(CMP_EPSILON);
				ek.to = f.vertex[(j + 1) % 3].snapped(CMP_EPSILON);
				if (ek.from < ek.to)
					SWAP(ek.from, ek.to);

				Map<_EdgeKey, bool>::Element *E = edge_map.find(ek);

				if (E) {

					E->get() = false;

				} else {

					edge_map[ek] = true;
				}
			}
		}
	}
	List<Vector3> lines;

	for (Map<_EdgeKey, bool>::Element *E = edge_map.front(); E; E = E->next()) {

		if (E->get()) {
			lines.push_back(E->key().from);
			lines.push_back(E->key().to);
		}
	}

	PoolVector<Vector3> varr;
	varr.resize(lines.size());
	{
		PoolVector<Vector3>::Write w = varr.write();
		int idx = 0;
		for (List<Vector3>::Element *E = lines.front(); E; E = E->next()) {
			w[idx++] = E->get();
		}
	}

	debug_mesh = Ref<Mesh>(memnew(Mesh));

	Array arr;
	arr.resize(Mesh::ARRAY_MAX);
	arr[Mesh::ARRAY_VERTEX] = varr;

	debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr);

	return debug_mesh;
}
Example #6
0
void Navigation2D::_navpoly_link(int p_id) {

	ERR_FAIL_COND(!navpoly_map.has(p_id));
	NavMesh &nm = navpoly_map[p_id];
	ERR_FAIL_COND(nm.linked);

	PoolVector<Vector2> vertices = nm.navpoly->get_vertices();
	int len = vertices.size();
	if (len == 0)
		return;

	PoolVector<Vector2>::Read r = vertices.read();

	for (int i = 0; i < nm.navpoly->get_polygon_count(); i++) {

		//build

		List<Polygon>::Element *P = nm.polygons.push_back(Polygon());
		Polygon &p = P->get();
		p.owner = &nm;

		Vector<int> poly = nm.navpoly->get_polygon(i);
		int plen = poly.size();
		const int *indices = poly.ptr();
		bool valid = true;
		p.edges.resize(plen);

		Vector2 center;
		float sum = 0;

		for (int j = 0; j < plen; j++) {

			int idx = indices[j];
			if (idx < 0 || idx >= len) {
				valid = false;
				break;
			}

			Polygon::Edge e;
			Vector2 ep = nm.xform.xform(r[idx]);
			center += ep;
			e.point = _get_point(ep);
			p.edges[j] = e;

			int idxn = indices[(j + 1) % plen];
			if (idxn < 0 || idxn >= len) {
				valid = false;
				break;
			}

			Vector2 epn = nm.xform.xform(r[idxn]);

			sum += (epn.x - ep.x) * (epn.y + ep.y);
		}

		p.clockwise = sum > 0;

		if (!valid) {
			nm.polygons.pop_back();
			ERR_CONTINUE(!valid);
			continue;
		}

		p.center = center / plen;

		//connect

		for (int j = 0; j < plen; j++) {

			int next = (j + 1) % plen;
			EdgeKey ek(p.edges[j].point, p.edges[next].point);

			Map<EdgeKey, Connection>::Element *C = connections.find(ek);
			if (!C) {

				Connection c;
				c.A = &p;
				c.A_edge = j;
				c.B = NULL;
				c.B_edge = -1;
				connections[ek] = c;
			} else {

				if (C->get().B != NULL) {
					ConnectionPending pending;
					pending.polygon = &p;
					pending.edge = j;
					p.edges[j].P = C->get().pending.push_back(pending);
					continue;
					//print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b));
				}

				C->get().B = &p;
				C->get().B_edge = j;
				C->get().A->edges[C->get().A_edge].C = &p;
				C->get().A->edges[C->get().A_edge].C_edge = j;
				p.edges[j].C = C->get().A;
				p.edges[j].C_edge = C->get().A_edge;
				//connection successful.
			}
		}
	}

	nm.linked = true;
}
Example #7
0
void GIProbe::_plot_mesh(const Transform& p_xform, Ref<Mesh>& p_mesh, Baker *p_baker, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material) {


	for(int i=0;i<p_mesh->get_surface_count();i++) {

		if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES)
			continue; //only triangles

		Ref<Material> src_material;

		if (p_override_material.is_valid()) {
			src_material=p_override_material;
		} else if (i<p_materials.size() && p_materials[i].is_valid()) {
			src_material=p_materials[i];
		} else {
			src_material=p_mesh->surface_get_material(i);
		}
		Baker::MaterialCache material = _get_material_cache(src_material,p_baker);

		Array a = p_mesh->surface_get_arrays(i);


		PoolVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
		PoolVector<Vector3>::Read vr=vertices.read();
		PoolVector<Vector2> uv = a[Mesh::ARRAY_TEX_UV];
		PoolVector<Vector2>::Read uvr;
		PoolVector<int> index = a[Mesh::ARRAY_INDEX];

		bool read_uv=false;

		if (uv.size()) {

			uvr=uv.read();
			read_uv=true;
		}

		if (index.size()) {

			int facecount = index.size()/3;
			PoolVector<int>::Read ir=index.read();

			for(int j=0;j<facecount;j++) {

				Vector3 vtxs[3];
				Vector2 uvs[3];

				for(int k=0;k<3;k++) {
					vtxs[k]=p_xform.xform(vr[ir[j*3+k]]);
				}

				if (read_uv) {
					for(int k=0;k<3;k++) {
						uvs[k]=uvr[ir[j*3+k]];
					}
				}

				//test against original bounds
				if (!fast_tri_box_overlap(-extents,extents*2,vtxs))
					continue;
				//plot
				_plot_face(0,0,0,0,0,vtxs,uvs,material,p_baker->po2_bounds,p_baker);
			}



		} else {

			int facecount = vertices.size()/3;

			for(int j=0;j<facecount;j++) {

				Vector3 vtxs[3];
				Vector2 uvs[3];

				for(int k=0;k<3;k++) {
					vtxs[k]=p_xform.xform(vr[j*3+k]);
				}

				if (read_uv) {
					for(int k=0;k<3;k++) {
						uvs[k]=uvr[j*3+k];
					}
				}

				//test against original bounds
				if (!fast_tri_box_overlap(-extents,extents*2,vtxs))
					continue;
				//plot face
				_plot_face(0,0,0,0,0,vtxs,uvs,material,p_baker->po2_bounds,p_baker);
			}

		}
	}
}
Example #8
0
Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) {

	ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
	ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER);
	ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
	ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);

	String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
	if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) {
		// Don't append the standard ports
		request += "Host: " + conn_host + "\r\n";
	} else {
		request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
	}
	bool add_clen = p_body.size() > 0;
	bool add_uagent = true;
	bool add_accept = true;
	for (int i = 0; i < p_headers.size(); i++) {
		request += p_headers[i] + "\r\n";
		if (add_clen && p_headers[i].findn("Content-Length:") == 0) {
			add_clen = false;
		}
		if (add_uagent && p_headers[i].findn("User-Agent:") == 0) {
			add_uagent = false;
		}
		if (add_accept && p_headers[i].findn("Accept:") == 0) {
			add_accept = false;
		}
	}
	if (add_clen) {
		request += "Content-Length: " + itos(p_body.size()) + "\r\n";
		// Should it add utf8 encoding?
	}
	if (add_uagent) {
		request += "User-Agent: GodotEngine/" + String(VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")\r\n";
	}
	if (add_accept) {
		request += "Accept: */*\r\n";
	}
	request += "\r\n";
	CharString cs = request.utf8();

	PoolVector<uint8_t> data;
	data.resize(cs.length());
	{
		PoolVector<uint8_t>::Write data_write = data.write();
		for (int i = 0; i < cs.length(); i++) {
			data_write[i] = cs[i];
		}
	}

	data.append_array(p_body);

	PoolVector<uint8_t>::Read r = data.read();
	Error err = connection->put_data(&r[0], data.size());

	if (err) {
		close();
		status = STATUS_CONNECTION_ERROR;
		return err;
	}

	status = STATUS_REQUESTING;

	return OK;
}
Example #9
0
Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays) {

	Vector<SurfaceTool::Vertex> ret;

	PoolVector<Vector3> varr = p_arrays[VS::ARRAY_VERTEX];
	PoolVector<Vector3> narr = p_arrays[VS::ARRAY_NORMAL];
	PoolVector<float> tarr = p_arrays[VS::ARRAY_TANGENT];
	PoolVector<Color> carr = p_arrays[VS::ARRAY_COLOR];
	PoolVector<Vector2> uvarr = p_arrays[VS::ARRAY_TEX_UV];
	PoolVector<Vector2> uv2arr = p_arrays[VS::ARRAY_TEX_UV2];
	PoolVector<int> barr = p_arrays[VS::ARRAY_BONES];
	PoolVector<float> warr = p_arrays[VS::ARRAY_WEIGHTS];

	int vc = varr.size();

	if (vc == 0)
		return ret;
	int lformat = 0;

	PoolVector<Vector3>::Read rv;
	if (varr.size()) {
		lformat |= VS::ARRAY_FORMAT_VERTEX;
		rv = varr.read();
	}
	PoolVector<Vector3>::Read rn;
	if (narr.size()) {
		lformat |= VS::ARRAY_FORMAT_NORMAL;
		rn = narr.read();
	}
	PoolVector<float>::Read rt;
	if (tarr.size()) {
		lformat |= VS::ARRAY_FORMAT_TANGENT;
		rt = tarr.read();
	}
	PoolVector<Color>::Read rc;
	if (carr.size()) {
		lformat |= VS::ARRAY_FORMAT_COLOR;
		rc = carr.read();
	}

	PoolVector<Vector2>::Read ruv;
	if (uvarr.size()) {
		lformat |= VS::ARRAY_FORMAT_TEX_UV;
		ruv = uvarr.read();
	}

	PoolVector<Vector2>::Read ruv2;
	if (uv2arr.size()) {
		lformat |= VS::ARRAY_FORMAT_TEX_UV2;
		ruv2 = uv2arr.read();
	}

	PoolVector<int>::Read rb;
	if (barr.size()) {
		lformat |= VS::ARRAY_FORMAT_BONES;
		rb = barr.read();
	}

	PoolVector<float>::Read rw;
	if (warr.size()) {
		lformat |= VS::ARRAY_FORMAT_WEIGHTS;
		rw = warr.read();
	}

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

		Vertex v;
		if (lformat & VS::ARRAY_FORMAT_VERTEX)
			v.vertex = varr[i];
		if (lformat & VS::ARRAY_FORMAT_NORMAL)
			v.normal = narr[i];
		if (lformat & VS::ARRAY_FORMAT_TANGENT) {
			Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]);
			v.tangent = p.normal;
			v.binormal = p.normal.cross(v.tangent).normalized() * p.d;
		}
		if (lformat & VS::ARRAY_FORMAT_COLOR)
			v.color = carr[i];
		if (lformat & VS::ARRAY_FORMAT_TEX_UV)
			v.uv = uvarr[i];
		if (lformat & VS::ARRAY_FORMAT_TEX_UV2)
			v.uv2 = uv2arr[i];
		if (lformat & VS::ARRAY_FORMAT_BONES) {
			Vector<int> b;
			b.resize(4);
			b.write[0] = barr[i * 4 + 0];
			b.write[1] = barr[i * 4 + 1];
			b.write[2] = barr[i * 4 + 2];
			b.write[3] = barr[i * 4 + 3];
			v.bones = b;
		}
		if (lformat & VS::ARRAY_FORMAT_WEIGHTS) {
			Vector<float> w;
			w.resize(4);
			w.write[0] = warr[i * 4 + 0];
			w.write[1] = warr[i * 4 + 1];
			w.write[2] = warr[i * 4 + 2];
			w.write[3] = warr[i * 4 + 3];
			v.weights = w;
		}

		ret.push_back(v);
	}

	return ret;
}
Example #10
0
PoolVector<PoolVector<Face3> > Geometry::separate_objects(PoolVector<Face3> p_array) {

	PoolVector<PoolVector<Face3> > objects;

	int len = p_array.size();

	PoolVector<Face3>::Read r = p_array.read();

	const Face3 *arrayptr = r.ptr();

	PoolVector<_FaceClassify> fc;

	fc.resize(len);

	PoolVector<_FaceClassify>::Write fcw = fc.write();

	_FaceClassify *_fcptr = fcw.ptr();

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

		_fcptr[i].face = arrayptr[i];
	}

	bool error = _connect_faces(_fcptr, len, -1);

	if (error) {

		ERR_FAIL_COND_V(error, PoolVector<PoolVector<Face3> >()); // invalid geometry
	}

	/* group connected faces in separate objects */

	int group = 0;
	for (int i = 0; i < len; i++) {

		if (!_fcptr[i].valid)
			continue;
		if (_group_face(_fcptr, len, i, group)) {
			group++;
		}
	}

	/* group connected faces in separate objects */

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

		_fcptr[i].face = arrayptr[i];
	}

	if (group >= 0) {

		objects.resize(group);
		PoolVector<PoolVector<Face3> >::Write obw = objects.write();
		PoolVector<Face3> *group_faces = obw.ptr();

		for (int i = 0; i < len; i++) {
			if (!_fcptr[i].valid)
				continue;
			if (_fcptr[i].group >= 0 && _fcptr[i].group < group) {

				group_faces[_fcptr[i].group].push_back(_fcptr[i].face);
			}
		}
	}

	return objects;
}
Example #11
0
PoolVector<Face3> Geometry::wrap_geometry(PoolVector<Face3> p_array, real_t *p_error) {

#define _MIN_SIZE 1.0
#define _MAX_LENGTH 20

	int face_count = p_array.size();
	PoolVector<Face3>::Read facesr = p_array.read();
	const Face3 *faces = facesr.ptr();

	Rect3 global_aabb;

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

		if (i == 0) {

			global_aabb = faces[i].get_aabb();
		} else {

			global_aabb.merge_with(faces[i].get_aabb());
		}
	}

	global_aabb.grow_by(0.01); // avoid numerical error

	// determine amount of cells in grid axis
	int div_x, div_y, div_z;

	if (global_aabb.size.x / _MIN_SIZE < _MAX_LENGTH)
		div_x = (int)(global_aabb.size.x / _MIN_SIZE) + 1;
	else
		div_x = _MAX_LENGTH;

	if (global_aabb.size.y / _MIN_SIZE < _MAX_LENGTH)
		div_y = (int)(global_aabb.size.y / _MIN_SIZE) + 1;
	else
		div_y = _MAX_LENGTH;

	if (global_aabb.size.z / _MIN_SIZE < _MAX_LENGTH)
		div_z = (int)(global_aabb.size.z / _MIN_SIZE) + 1;
	else
		div_z = _MAX_LENGTH;

	Vector3 voxelsize = global_aabb.size;
	voxelsize.x /= div_x;
	voxelsize.y /= div_y;
	voxelsize.z /= div_z;

	// create and initialize cells to zero
	//print_line("Wrapper: Initializing Cells");

	uint8_t ***cell_status = memnew_arr(uint8_t **, div_x);
	for (int i = 0; i < div_x; i++) {

		cell_status[i] = memnew_arr(uint8_t *, div_y);

		for (int j = 0; j < div_y; j++) {

			cell_status[i][j] = memnew_arr(uint8_t, div_z);

			for (int k = 0; k < div_z; k++) {

				cell_status[i][j][k] = 0;
			}
		}
	}

	// plot faces into cells
	//print_line("Wrapper (1/6): Plotting Faces");

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

		Face3 f = faces[i];
		for (int j = 0; j < 3; j++) {

			f.vertex[j] -= global_aabb.pos;
		}
		_plot_face(cell_status, 0, 0, 0, div_x, div_y, div_z, voxelsize, f);
	}

	// determine which cells connect to the outside by traversing the outside and recursively flood-fill marking

	//print_line("Wrapper (2/6): Flood Filling");

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

		for (int j = 0; j < div_y; j++) {

			_mark_outside(cell_status, i, j, 0, div_x, div_y, div_z);
			_mark_outside(cell_status, i, j, div_z - 1, div_x, div_y, div_z);
		}
	}

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

		for (int j = 0; j < div_y; j++) {

			_mark_outside(cell_status, 0, j, i, div_x, div_y, div_z);
			_mark_outside(cell_status, div_x - 1, j, i, div_x, div_y, div_z);
		}
	}

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

		for (int j = 0; j < div_z; j++) {

			_mark_outside(cell_status, i, 0, j, div_x, div_y, div_z);
			_mark_outside(cell_status, i, div_y - 1, j, div_x, div_y, div_z);
		}
	}

	// build faces for the inside-outside cell divisors

	//print_line("Wrapper (3/6): Building Faces");

	PoolVector<Face3> wrapped_faces;

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

		for (int j = 0; j < div_y; j++) {

			for (int k = 0; k < div_z; k++) {

				_build_faces(cell_status, i, j, k, div_x, div_y, div_z, wrapped_faces);
			}
		}
	}

	//print_line("Wrapper (4/6): Transforming Back Vertices");

	// transform face vertices to global coords

	int wrapped_faces_count = wrapped_faces.size();
	PoolVector<Face3>::Write wrapped_facesw = wrapped_faces.write();
	Face3 *wrapped_faces_ptr = wrapped_facesw.ptr();

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

		for (int j = 0; j < 3; j++) {

			Vector3 &v = wrapped_faces_ptr[i].vertex[j];
			v = v * voxelsize;
			v += global_aabb.pos;
		}
	}

	// clean up grid
	//print_line("Wrapper (5/6): Grid Cleanup");

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

		for (int j = 0; j < div_y; j++) {

			memdelete_arr(cell_status[i][j]);
		}

		memdelete_arr(cell_status[i]);
	}

	memdelete_arr(cell_status);
	if (p_error)
		*p_error = voxelsize.length();

	//print_line("Wrapper (6/6): Finished.");
	return wrapped_faces;
}
Example #12
0
Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &flags, Ref<Image> &image, int p_size_limit) {

	ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER);

	FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
	ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);

	uint8_t header[4];
	f->get_buffer(header, 4);
	if (header[0] != 'G' || header[1] != 'D' || header[2] != 'S' || header[3] != 'T') {
		memdelete(f);
		ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'D' || header[2] != 'S' || header[3] != 'T', ERR_FILE_CORRUPT);
	}

	tw = f->get_32();
	th = f->get_32();
	flags = f->get_32(); //texture flags!
	uint32_t df = f->get_32(); //data format

/*
	print_line("width: " + itos(tw));
	print_line("height: " + itos(th));
	print_line("flags: " + itos(flags));
	print_line("df: " + itos(df));
	*/
#ifdef TOOLS_ENABLED

	if (request_3d_callback && df & FORMAT_BIT_DETECT_3D) {
		//print_line("request detect 3D at " + p_path);
		VS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this);
	} else {
		//print_line("not requesting detect 3D at " + p_path);
		VS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL);
	}

	if (request_srgb_callback && df & FORMAT_BIT_DETECT_SRGB) {
		//print_line("request detect srgb at " + p_path);
		VS::get_singleton()->texture_set_detect_srgb_callback(texture, _requested_srgb, this);
	} else {
		//print_line("not requesting detect srgb at " + p_path);
		VS::get_singleton()->texture_set_detect_srgb_callback(texture, NULL, NULL);
	}

	if (request_srgb_callback && df & FORMAT_BIT_DETECT_NORMAL) {
		//print_line("request detect srgb at " + p_path);
		VS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this);
	} else {
		//print_line("not requesting detect normal at " + p_path);
		VS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL);
	}
#endif
	if (!(df & FORMAT_BIT_STREAM)) {
		p_size_limit = 0;
	}

	if (df & FORMAT_BIT_LOSSLESS || df & FORMAT_BIT_LOSSY) {
		//look for a PNG or WEBP file inside

		int sw = tw;
		int sh = th;

		uint32_t mipmaps = f->get_32();
		uint32_t size = f->get_32();

		//print_line("mipmaps: " + itos(mipmaps));

		while (mipmaps > 1 && p_size_limit > 0 && (sw > p_size_limit || sh > p_size_limit)) {

			f->seek(f->get_position() + size);
			mipmaps = f->get_32();
			size = f->get_32();

			sw = MAX(sw >> 1, 1);
			sh = MAX(sh >> 1, 1);
			mipmaps--;
		}

		//mipmaps need to be read independently, they will be later combined
		Vector<Ref<Image> > mipmap_images;
		int total_size = 0;

		for (uint32_t i = 0; i < mipmaps; i++) {

			if (i) {
				size = f->get_32();
			}

			PoolVector<uint8_t> pv;
			pv.resize(size);
			{
				PoolVector<uint8_t>::Write w = pv.write();
				f->get_buffer(w.ptr(), size);
			}

			Ref<Image> img;
			if (df & FORMAT_BIT_LOSSLESS) {
				img = Image::lossless_unpacker(pv);
			} else {
				img = Image::lossy_unpacker(pv);
			}

			if (img.is_null() || img->empty()) {
				memdelete(f);
				ERR_FAIL_COND_V(img.is_null() || img->empty(), ERR_FILE_CORRUPT);
			}

			total_size += img->get_data().size();

			mipmap_images.push_back(img);
		}

		//print_line("mipmap read total: " + itos(mipmap_images.size()));

		memdelete(f); //no longer needed

		if (mipmap_images.size() == 1) {

			image = mipmap_images[0];
			return OK;

		} else {
			PoolVector<uint8_t> img_data;
			img_data.resize(total_size);

			{
				PoolVector<uint8_t>::Write w = img_data.write();

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

					PoolVector<uint8_t> id = mipmap_images[i]->get_data();
					int len = id.size();
					PoolVector<uint8_t>::Read r = id.read();
					copymem(&w[ofs], r.ptr(), len);
					ofs += len;
				}
			}

			image->create(sw, sh, true, mipmap_images[0]->get_format(), img_data);
			return OK;
		}

	} else {
Example #13
0
bool GridMap::_set(const StringName &p_name, const Variant &p_value) {

	String name = p_name;

	if (name == "theme") {

		set_theme(p_value);
	} else if (name == "cell_size") {
		set_cell_size(p_value);
	} else if (name == "cell_octant_size") {
		set_octant_size(p_value);
	} else if (name == "cell_center_x") {
		set_center_x(p_value);
	} else if (name == "cell_center_y") {
		set_center_y(p_value);
	} else if (name == "cell_center_z") {
		set_center_z(p_value);
	} else if (name == "cell_scale") {
		set_cell_scale(p_value);
		/*	} else if (name=="cells") {
		PoolVector<int> cells = p_value;
		int amount=cells.size();
		PoolVector<int>::Read r = cells.read();
		ERR_FAIL_COND_V(amount&1,false); // not even
		cell_map.clear();
		for(int i=0;i<amount/3;i++) {


			IndexKey ik;
			ik.key=decode_uint64(&r[i*3]);
			Cell cell;
			cell.cell=uint32_t(r[i*+1]);
			cell_map[ik]=cell;

		}
		_recreate_octant_data();*/
	} else if (name == "data") {

		Dictionary d = p_value;

		if (d.has("cells")) {

			PoolVector<int> cells = d["cells"];
			int amount = cells.size();
			PoolVector<int>::Read r = cells.read();
			ERR_FAIL_COND_V(amount % 3, false); // not even
			cell_map.clear();
			for (int i = 0; i < amount / 3; i++) {

				IndexKey ik;
				ik.key = decode_uint64((const uint8_t *)&r[i * 3]);
				Cell cell;
				cell.cell = decode_uint32((const uint8_t *)&r[i * 3 + 2]);
				cell_map[ik] = cell;
			}
		}
		_recreate_octant_data();

	} else if (name.begins_with("areas/")) {
		int which = name.get_slicec('/', 1).to_int();
		String what = name.get_slicec('/', 2);
		if (what == "bounds") {
			ERR_FAIL_COND_V(area_map.has(which), false);
			create_area(which, p_value);
			return true;
		}

		ERR_FAIL_COND_V(!area_map.has(which), false);

		if (what == "name")
			area_set_name(which, p_value);
		else if (what == "disable_distance")
			area_set_portal_disable_distance(which, p_value);
		else if (what == "exterior_portal")
			area_set_portal_disable_color(which, p_value);
		else
			return false;
	} else
		return false;

	return true;
}
Example #14
0
Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
	AudioStreamSample::Format dst_format = format;
	bool stereo = true; //forcing mono is not implemented

	PoolVector<uint8_t> dst_data;

	if (dst_format == AudioStreamSample::FORMAT_8_BITS) {
		int data_size = current_instance->recording_data.size();
		dst_data.resize(data_size);
		PoolVector<uint8_t>::Write w = dst_data.write();

		for (int i = 0; i < data_size; i++) {
			int8_t v = CLAMP(current_instance->recording_data[i] * 128, -128, 127);
			w[i] = v;
		}
	} else if (dst_format == AudioStreamSample::FORMAT_16_BITS) {
		int data_size = current_instance->recording_data.size();
		dst_data.resize(data_size * 2);
		PoolVector<uint8_t>::Write w = dst_data.write();

		for (int i = 0; i < data_size; i++) {
			int16_t v = CLAMP(current_instance->recording_data[i] * 32768, -32768, 32767);
			encode_uint16(v, &w[i * 2]);
		}
	} else if (dst_format == AudioStreamSample::FORMAT_IMA_ADPCM) {
		//byte interleave
		Vector<float> left;
		Vector<float> right;

		int tframes = current_instance->recording_data.size() / 2;
		left.resize(tframes);
		right.resize(tframes);

		for (int i = 0; i < tframes; i++) {
			left.set(i, current_instance->recording_data[i * 2 + 0]);
			right.set(i, current_instance->recording_data[i * 2 + 1]);
		}

		PoolVector<uint8_t> bleft;
		PoolVector<uint8_t> bright;

		ResourceImporterWAV::_compress_ima_adpcm(left, bleft);
		ResourceImporterWAV::_compress_ima_adpcm(right, bright);

		int dl = bleft.size();
		dst_data.resize(dl * 2);

		PoolVector<uint8_t>::Write w = dst_data.write();
		PoolVector<uint8_t>::Read rl = bleft.read();
		PoolVector<uint8_t>::Read rr = bright.read();

		for (int i = 0; i < dl; i++) {
			w[i * 2 + 0] = rl[i];
			w[i * 2 + 1] = rr[i];
		}
	} else {
		ERR_PRINT("Format not implemented.");
	}

	Ref<AudioStreamSample> sample;
	sample.instance();
	sample->set_data(dst_data);
	sample->set_format(dst_format);
	sample->set_mix_rate(AudioServer::get_singleton()->get_mix_rate());
	sample->set_loop_mode(AudioStreamSample::LOOP_DISABLED);
	sample->set_loop_begin(0);
	sample->set_loop_end(0);
	sample->set_stereo(stereo);

	return sample;
}
Example #15
0
void NavigationPolygon::make_polygons_from_outlines() {

	List<TriangulatorPoly> in_poly, out_poly;

	Vector2 outside_point(-1e10, -1e10);

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

		PoolVector<Vector2> ol = outlines[i];
		int olsize = ol.size();
		if (olsize < 3)
			continue;
		PoolVector<Vector2>::Read r = ol.read();
		for (int j = 0; j < olsize; j++) {
			outside_point.x = MAX(r[j].x, outside_point.x);
			outside_point.y = MAX(r[j].y, outside_point.y);
		}
	}

	outside_point += Vector2(0.7239784, 0.819238); //avoid precision issues

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

		PoolVector<Vector2> ol = outlines[i];
		int olsize = ol.size();
		if (olsize < 3)
			continue;
		PoolVector<Vector2>::Read r = ol.read();

		int interscount = 0;
		//test if this is an outer outline
		for (int k = 0; k < outlines.size(); k++) {

			if (i == k)
				continue; //no self intersect

			PoolVector<Vector2> ol2 = outlines[k];
			int olsize2 = ol2.size();
			if (olsize2 < 3)
				continue;
			PoolVector<Vector2>::Read r2 = ol2.read();

			for (int l = 0; l < olsize2; l++) {

				if (Geometry::segment_intersects_segment_2d(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], NULL)) {
					interscount++;
				}
			}
		}

		bool outer = (interscount % 2) == 0;

		TriangulatorPoly tp;
		tp.Init(olsize);
		for (int j = 0; j < olsize; j++) {
			tp[j] = r[j];
		}

		if (outer)
			tp.SetOrientation(TRIANGULATOR_CCW);
		else {
			tp.SetOrientation(TRIANGULATOR_CW);
			tp.SetHole(true);
		}

		in_poly.push_back(tp);
	}

	TriangulatorPartition tpart;
	if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
		print_line("convex partition failed!");
		return;
	}

	polygons.clear();
	vertices.resize(0);

	Map<Vector2, int> points;
	for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) {

		TriangulatorPoly &tp = I->get();

		struct Polygon p;

		for (int i = 0; i < tp.GetNumPoints(); i++) {

			Map<Vector2, int>::Element *E = points.find(tp[i]);
			if (!E) {
				E = points.insert(tp[i], vertices.size());
				vertices.push_back(tp[i]);
			}
			p.indices.push_back(E->get());
		}

		polygons.push_back(p);
	}

	emit_signal(CoreStringNames::get_singleton()->changed);
}
Example #16
0
void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) {

	PoolVector<Vector3> varr = arr[VS::ARRAY_VERTEX];
	PoolVector<Vector3> narr = arr[VS::ARRAY_NORMAL];
	PoolVector<float> tarr = arr[VS::ARRAY_TANGENT];
	PoolVector<Color> carr = arr[VS::ARRAY_COLOR];
	PoolVector<Vector2> uvarr = arr[VS::ARRAY_TEX_UV];
	PoolVector<Vector2> uv2arr = arr[VS::ARRAY_TEX_UV2];
	PoolVector<int> barr = arr[VS::ARRAY_BONES];
	PoolVector<float> warr = arr[VS::ARRAY_WEIGHTS];

	int vc = varr.size();

	if (vc == 0)
		return;
	lformat = 0;

	PoolVector<Vector3>::Read rv;
	if (varr.size()) {
		lformat |= VS::ARRAY_FORMAT_VERTEX;
		rv = varr.read();
	}
	PoolVector<Vector3>::Read rn;
	if (narr.size()) {
		lformat |= VS::ARRAY_FORMAT_NORMAL;
		rn = narr.read();
	}
	PoolVector<float>::Read rt;
	if (tarr.size()) {
		lformat |= VS::ARRAY_FORMAT_TANGENT;
		rt = tarr.read();
	}
	PoolVector<Color>::Read rc;
	if (carr.size()) {
		lformat |= VS::ARRAY_FORMAT_COLOR;
		rc = carr.read();
	}

	PoolVector<Vector2>::Read ruv;
	if (uvarr.size()) {
		lformat |= VS::ARRAY_FORMAT_TEX_UV;
		ruv = uvarr.read();
	}

	PoolVector<Vector2>::Read ruv2;
	if (uv2arr.size()) {
		lformat |= VS::ARRAY_FORMAT_TEX_UV2;
		ruv2 = uv2arr.read();
	}

	PoolVector<int>::Read rb;
	if (barr.size()) {
		lformat |= VS::ARRAY_FORMAT_BONES;
		rb = barr.read();
	}

	PoolVector<float>::Read rw;
	if (warr.size()) {
		lformat |= VS::ARRAY_FORMAT_WEIGHTS;
		rw = warr.read();
	}

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

		Vertex v;
		if (lformat & VS::ARRAY_FORMAT_VERTEX)
			v.vertex = varr[i];
		if (lformat & VS::ARRAY_FORMAT_NORMAL)
			v.normal = narr[i];
		if (lformat & VS::ARRAY_FORMAT_TANGENT) {
			Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]);
			v.tangent = p.normal;
			v.binormal = p.normal.cross(v.tangent).normalized() * p.d;
		}
		if (lformat & VS::ARRAY_FORMAT_COLOR)
			v.color = carr[i];
		if (lformat & VS::ARRAY_FORMAT_TEX_UV)
			v.uv = uvarr[i];
		if (lformat & VS::ARRAY_FORMAT_TEX_UV2)
			v.uv2 = uv2arr[i];
		if (lformat & VS::ARRAY_FORMAT_BONES) {
			Vector<int> b;
			b.resize(4);
			b.write[0] = barr[i * 4 + 0];
			b.write[1] = barr[i * 4 + 1];
			b.write[2] = barr[i * 4 + 2];
			b.write[3] = barr[i * 4 + 3];
			v.bones = b;
		}
		if (lformat & VS::ARRAY_FORMAT_WEIGHTS) {
			Vector<float> w;
			w.resize(4);
			w.write[0] = warr[i * 4 + 0];
			w.write[1] = warr[i * 4 + 1];
			w.write[2] = warr[i * 4 + 2];
			w.write[3] = warr[i * 4 + 3];
			v.weights = w;
		}

		r_vertex->push_back(v);
	}

	//indices

	PoolVector<int> idx = arr[VS::ARRAY_INDEX];
	int is = idx.size();
	if (is) {

		lformat |= VS::ARRAY_FORMAT_INDEX;
		PoolVector<int>::Read iarr = idx.read();
		for (int i = 0; i < is; i++) {
			r_index->push_back(iarr[i]);
		}
	}
}
Example #17
0
void NavigationPolygonInstance::_notification(int p_what) {

	switch (p_what) {
		case NOTIFICATION_ENTER_TREE: {

			Node2D *c = this;
			while (c) {

				navigation = Object::cast_to<Navigation2D>(c);
				if (navigation) {

					if (enabled && navpoly.is_valid()) {

						nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this);
					}
					break;
				}

				c = Object::cast_to<Node2D>(c->get_parent());
			}

		} break;
		case NOTIFICATION_TRANSFORM_CHANGED: {

			if (navigation && nav_id != -1) {
				navigation->navpoly_set_transform(nav_id, get_relative_transform_to_parent(navigation));
			}

		} break;
		case NOTIFICATION_EXIT_TREE: {

			if (navigation) {

				if (nav_id != -1) {
					navigation->navpoly_remove(nav_id);
					nav_id = -1;
				}
			}
			navigation = NULL;
		} break;
		case NOTIFICATION_DRAW: {

			if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) {

				PoolVector<Vector2> verts = navpoly->get_vertices();
				int vsize = verts.size();
				if (vsize < 3)
					return;

				Color color;
				if (enabled) {
					color = get_tree()->get_debug_navigation_color();
				} else {
					color = get_tree()->get_debug_navigation_disabled_color();
				}
				Vector<Color> colors;
				Vector<Vector2> vertices;
				vertices.resize(vsize);
				colors.resize(vsize);
				{
					PoolVector<Vector2>::Read vr = verts.read();
					for (int i = 0; i < vsize; i++) {
						vertices[i] = vr[i];
						colors[i] = color;
					}
				}

				Vector<int> indices;

				for (int i = 0; i < navpoly->get_polygon_count(); i++) {
					Vector<int> polygon = navpoly->get_polygon(i);

					for (int j = 2; j < polygon.size(); j++) {

						int kofs[3] = { 0, j - 1, j };
						for (int k = 0; k < 3; k++) {

							int idx = polygon[kofs[k]];
							ERR_FAIL_INDEX(idx, vsize);
							indices.push_back(idx);
						}
					}
				}
				VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, vertices, colors);
			}
		} break;
	}
}
Example #18
0
void SpriteEditor::_create_uv_lines() {

	Ref<Mesh> sprite = node->get_sprite();
	ERR_FAIL_COND(!sprite.is_valid());

	Set<SpriteEditorEdgeSort> edges;
	uv_lines.clear();
	for (int i = 0; i < sprite->get_surface_count(); i++) {
		if (sprite->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
			continue;
		Array a = sprite->surface_get_arrays(i);

		PoolVector<Vector2> uv = a[p_layer == 0 ? Mesh::ARRAY_TEX_UV : Mesh::ARRAY_TEX_UV2];
		if (uv.size() == 0) {
			err_dialog->set_text(TTR("Model has no UV in this layer"));
			err_dialog->popup_centered_minsize();
			return;
		}

		PoolVector<Vector2>::Read r = uv.read();

		PoolVector<int> indices = a[Mesh::ARRAY_INDEX];
		PoolVector<int>::Read ri;

		int ic;
		bool use_indices;

		if (indices.size()) {
			ic = indices.size();
			ri = indices.read();
			use_indices = true;
		} else {
			ic = uv.size();
			use_indices = false;
		}

		for (int j = 0; j < ic; j += 3) {

			for (int k = 0; k < 3; k++) {

				SpriteEditorEdgeSort edge;
				if (use_indices) {
					edge.a = r[ri[j + k]];
					edge.b = r[ri[j + ((k + 1) % 3)]];
				} else {
					edge.a = r[j + k];
					edge.b = r[j + ((k + 1) % 3)];
				}

				if (edges.has(edge))
					continue;

				uv_lines.push_back(edge.a);
				uv_lines.push_back(edge.b);
				edges.insert(edge);
			}
		}
	}

	debug_uv_dialog->popup_centered_minsize();
}
void CPUParticles2DEditorPlugin::_generate_emission_mask() {

	Ref<Image> img;
	img.instance();
	Error err = ImageLoader::load_image(source_emission_file, img);
	ERR_EXPLAIN(TTR("Error loading image:") + " " + source_emission_file);
	ERR_FAIL_COND(err != OK);

	if (img->is_compressed()) {
		img->decompress();
	}
	img->convert(Image::FORMAT_RGBA8);
	ERR_FAIL_COND(img->get_format() != Image::FORMAT_RGBA8);
	Size2i s = Size2(img->get_width(), img->get_height());
	ERR_FAIL_COND(s.width == 0 || s.height == 0);

	Vector<Point2> valid_positions;
	Vector<Point2> valid_normals;
	Vector<uint8_t> valid_colors;

	valid_positions.resize(s.width * s.height);

	EmissionMode emode = (EmissionMode)emission_mask_mode->get_selected();

	if (emode == EMISSION_MODE_BORDER_DIRECTED) {
		valid_normals.resize(s.width * s.height);
	}

	bool capture_colors = emission_colors->is_pressed();

	if (capture_colors) {
		valid_colors.resize(s.width * s.height * 4);
	}

	int vpc = 0;

	{
		PoolVector<uint8_t> data = img->get_data();
		PoolVector<uint8_t>::Read r = data.read();

		for (int i = 0; i < s.width; i++) {
			for (int j = 0; j < s.height; j++) {

				uint8_t a = r[(j * s.width + i) * 4 + 3];

				if (a > 128) {

					if (emode == EMISSION_MODE_SOLID) {

						if (capture_colors) {
							valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0];
							valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1];
							valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2];
							valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3];
						}
						valid_positions.write[vpc++] = Point2(i, j);

					} else {

						bool on_border = false;
						for (int x = i - 1; x <= i + 1; x++) {
							for (int y = j - 1; y <= j + 1; y++) {

								if (x < 0 || y < 0 || x >= s.width || y >= s.height || r[(y * s.width + x) * 4 + 3] <= 128) {
									on_border = true;
									break;
								}
							}

							if (on_border)
								break;
						}

						if (on_border) {
							valid_positions.write[vpc] = Point2(i, j);

							if (emode == EMISSION_MODE_BORDER_DIRECTED) {
								Vector2 normal;
								for (int x = i - 2; x <= i + 2; x++) {
									for (int y = j - 2; y <= j + 2; y++) {

										if (x == i && y == j)
											continue;

										if (x < 0 || y < 0 || x >= s.width || y >= s.height || r[(y * s.width + x) * 4 + 3] <= 128) {
											normal += Vector2(x - i, y - j).normalized();
										}
									}
								}

								normal.normalize();
								valid_normals.write[vpc] = normal;
							}

							if (capture_colors) {
								valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0];
								valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1];
								valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2];
								valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3];
							}

							vpc++;
						}
					}
				}
			}
		}
	}

	valid_positions.resize(vpc);
	if (valid_normals.size()) {
		valid_normals.resize(vpc);
	}

	ERR_EXPLAIN(TTR("No pixels with transparency > 128 in image..."));
	ERR_FAIL_COND(valid_positions.size() == 0);

	if (capture_colors) {
		PoolColorArray pca;
		pca.resize(vpc);
		PoolColorArray::Write pcaw = pca.write();
		for (int i = 0; i < vpc; i += 1) {
			Color color;
			color.r = valid_colors[i * 4 + 0] / 255.0f;
			color.g = valid_colors[i * 4 + 1] / 255.0f;
			color.b = valid_colors[i * 4 + 2] / 255.0f;
			color.a = valid_colors[i * 4 + 3] / 255.0f;
			pcaw[i] = color;
		}
		particles->set_emission_colors(pca);
	}

	if (valid_normals.size()) {
		particles->set_emission_shape(CPUParticles2D::EMISSION_SHAPE_DIRECTED_POINTS);
		PoolVector2Array norms;
		norms.resize(valid_normals.size());
		PoolVector2Array::Write normsw = norms.write();
		for (int i = 0; i < valid_normals.size(); i += 1) {
			normsw[i] = valid_normals[i];
		}
		particles->set_emission_normals(norms);
	} else {
		particles->set_emission_shape(CPUParticles2D::EMISSION_SHAPE_POINTS);
	}

	{
		PoolVector2Array points;
		points.resize(valid_positions.size());
		PoolVector2Array::Write pointsw = points.write();
		for (int i = 0; i < valid_positions.size(); i += 1) {
			pointsw[i] = valid_positions[i];
		}
		particles->set_emission_points(points);
	}
}
Example #20
0
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {

	uint8_t *buf = r_buffer;

	r_len = 0;

	uint32_t flags = 0;

	switch (p_variant.get_type()) {

		case Variant::INT: {
			int64_t val = p_variant;
			if (val > 0x7FFFFFFF || val < -0x80000000) {
				flags |= ENCODE_FLAG_64;
			}
		} break;
		case Variant::REAL: {

			double d = p_variant;
			float f = d;
			if (double(f) != d) {
				flags |= ENCODE_FLAG_64; //always encode real as double
			}
		} break;
	}

	if (buf) {
		encode_uint32(p_variant.get_type() | flags, buf);
		buf += 4;
	}
	r_len += 4;

	switch (p_variant.get_type()) {

		case Variant::NIL: {

			//nothing to do
		} break;
		case Variant::BOOL: {

			if (buf) {
				encode_uint32(p_variant.operator bool(), buf);
			}

			r_len += 4;

		} break;
		case Variant::INT: {

			int64_t val = p_variant;
			if (val > 0x7FFFFFFF || val < -0x80000000) {
				//64 bits
				if (buf) {
					encode_uint64(val, buf);
				}

				r_len += 8;
			} else {
				if (buf) {
					encode_uint32(int32_t(val), buf);
				}

				r_len += 4;
			}
		} break;
		case Variant::REAL: {

			double d = p_variant;
			float f = d;
			if (double(f) != d) {
				if (buf) {
					encode_double(p_variant.operator double(), buf);
				}

				r_len += 8;

			} else {

				if (buf) {
					encode_float(p_variant.operator float(), buf);
				}

				r_len += 4;
			}

		} break;
		case Variant::NODE_PATH: {

			NodePath np = p_variant;
			if (buf) {
				encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format
				encode_uint32(np.get_subname_count(), buf + 4);
				uint32_t flags = 0;
				if (np.is_absolute())
					flags |= 1;
				if (np.get_property() != StringName())
					flags |= 2;

				encode_uint32(flags, buf + 8);

				buf += 12;
			}

			r_len += 12;

			int total = np.get_name_count() + np.get_subname_count();
			if (np.get_property() != StringName())
				total++;

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

				String str;

				if (i < np.get_name_count())
					str = np.get_name(i);
				else if (i < np.get_name_count() + np.get_subname_count())
					str = np.get_subname(i - np.get_subname_count());
				else
					str = np.get_property();

				CharString utf8 = str.utf8();

				int pad = 0;

				if (utf8.length() % 4)
					pad = 4 - utf8.length() % 4;

				if (buf) {
					encode_uint32(utf8.length(), buf);
					buf += 4;
					copymem(buf, utf8.get_data(), utf8.length());
					buf += pad + utf8.length();
				}

				r_len += 4 + utf8.length() + pad;
			}

		} break;
		case Variant::STRING: {

			CharString utf8 = p_variant.operator String().utf8();

			if (buf) {
				encode_uint32(utf8.length(), buf);
				buf += 4;
				copymem(buf, utf8.get_data(), utf8.length());
			}

			r_len += 4 + utf8.length();
			while (r_len % 4)
				r_len++; //pad

		} break;
		// math types

		case Variant::VECTOR2: {

			if (buf) {
				Vector2 v2 = p_variant;
				encode_float(v2.x, &buf[0]);
				encode_float(v2.y, &buf[4]);
			}

			r_len += 2 * 4;

		} break; // 5
		case Variant::RECT2: {

			if (buf) {
				Rect2 r2 = p_variant;
				encode_float(r2.position.x, &buf[0]);
				encode_float(r2.position.y, &buf[4]);
				encode_float(r2.size.x, &buf[8]);
				encode_float(r2.size.y, &buf[12]);
			}
			r_len += 4 * 4;

		} break;
		case Variant::VECTOR3: {

			if (buf) {
				Vector3 v3 = p_variant;
				encode_float(v3.x, &buf[0]);
				encode_float(v3.y, &buf[4]);
				encode_float(v3.z, &buf[8]);
			}

			r_len += 3 * 4;

		} break;
		case Variant::TRANSFORM2D: {

			if (buf) {
				Transform2D val = p_variant;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 2; j++) {

						copymem(&buf[(i * 2 + j) * 4], &val.elements[i][j], sizeof(float));
					}
				}
			}

			r_len += 6 * 4;

		} break;
		case Variant::PLANE: {

			if (buf) {
				Plane p = p_variant;
				encode_float(p.normal.x, &buf[0]);
				encode_float(p.normal.y, &buf[4]);
				encode_float(p.normal.z, &buf[8]);
				encode_float(p.d, &buf[12]);
			}

			r_len += 4 * 4;

		} break;
		case Variant::QUAT: {

			if (buf) {
				Quat q = p_variant;
				encode_float(q.x, &buf[0]);
				encode_float(q.y, &buf[4]);
				encode_float(q.z, &buf[8]);
				encode_float(q.w, &buf[12]);
			}

			r_len += 4 * 4;

		} break;
		case Variant::RECT3: {

			if (buf) {
				Rect3 aabb = p_variant;
				encode_float(aabb.position.x, &buf[0]);
				encode_float(aabb.position.y, &buf[4]);
				encode_float(aabb.position.z, &buf[8]);
				encode_float(aabb.size.x, &buf[12]);
				encode_float(aabb.size.y, &buf[16]);
				encode_float(aabb.size.z, &buf[20]);
			}

			r_len += 6 * 4;

		} break;
		case Variant::BASIS: {

			if (buf) {
				Basis val = p_variant;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {

						copymem(&buf[(i * 3 + j) * 4], &val.elements[i][j], sizeof(float));
					}
				}
			}

			r_len += 9 * 4;

		} break;
		case Variant::TRANSFORM: {

			if (buf) {
				Transform val = p_variant;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {

						copymem(&buf[(i * 3 + j) * 4], &val.basis.elements[i][j], sizeof(float));
					}
				}

				encode_float(val.origin.x, &buf[36]);
				encode_float(val.origin.y, &buf[40]);
				encode_float(val.origin.z, &buf[44]);
			}

			r_len += 12 * 4;

		} break;

		// misc types
		case Variant::COLOR: {

			if (buf) {
				Color c = p_variant;
				encode_float(c.r, &buf[0]);
				encode_float(c.g, &buf[4]);
				encode_float(c.b, &buf[8]);
				encode_float(c.a, &buf[12]);
			}

			r_len += 4 * 4;

		} break;
		/*case Variant::RESOURCE: {

			ERR_EXPLAIN("Can't marshallize resources");
			ERR_FAIL_V(ERR_INVALID_DATA); //no, i'm sorry, no go
		} break;*/
		case Variant::_RID:
		case Variant::OBJECT: {

		} break;
		case Variant::DICTIONARY: {

			Dictionary d = p_variant;

			if (buf) {
				encode_uint32(uint32_t(d.size()), buf);
				buf += 4;
			}
			r_len += 4;

			List<Variant> keys;
			d.get_key_list(&keys);

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

				/*
				CharString utf8 = E->->utf8();

				if (buf) {
					encode_uint32(utf8.length()+1,buf);
					buf+=4;
					copymem(buf,utf8.get_data(),utf8.length()+1);
				}

				r_len+=4+utf8.length()+1;
				while (r_len%4)
					r_len++; //pad
				*/
				int len;
				encode_variant(E->get(), buf, len);
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
				r_len += len;
				if (buf)
					buf += len;
				encode_variant(d[E->get()], buf, len);
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
				r_len += len;
				if (buf)
					buf += len;
			}

		} break;
		case Variant::ARRAY: {

			Array v = p_variant;

			if (buf) {
				encode_uint32(uint32_t(v.size()), buf);
				buf += 4;
			}

			r_len += 4;

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

				int len;
				encode_variant(v.get(i), buf, len);
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
				r_len += len;
				if (buf)
					buf += len;
			}

		} break;
		// arrays
		case Variant::POOL_BYTE_ARRAY: {

			PoolVector<uint8_t> data = p_variant;
			int datalen = data.size();
			int datasize = sizeof(uint8_t);

			if (buf) {
				encode_uint32(datalen, buf);
				buf += 4;
				PoolVector<uint8_t>::Read r = data.read();
				copymem(buf, &r[0], datalen * datasize);
			}

			r_len += 4 + datalen * datasize;
			while (r_len % 4)
				r_len++;

		} break;
		case Variant::POOL_INT_ARRAY: {

			PoolVector<int> data = p_variant;
			int datalen = data.size();
			int datasize = sizeof(int32_t);

			if (buf) {
				encode_uint32(datalen, buf);
				buf += 4;
				PoolVector<int>::Read r = data.read();
				for (int i = 0; i < datalen; i++)
					encode_uint32(r[i], &buf[i * datasize]);
			}

			r_len += 4 + datalen * datasize;

		} break;
		case Variant::POOL_REAL_ARRAY: {

			PoolVector<real_t> data = p_variant;
			int datalen = data.size();
			int datasize = sizeof(real_t);

			if (buf) {
				encode_uint32(datalen, buf);
				buf += 4;
				PoolVector<real_t>::Read r = data.read();
				for (int i = 0; i < datalen; i++)
					encode_float(r[i], &buf[i * datasize]);
			}

			r_len += 4 + datalen * datasize;

		} break;
		case Variant::POOL_STRING_ARRAY: {

			PoolVector<String> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

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

				CharString utf8 = data.get(i).utf8();

				if (buf) {
					encode_uint32(utf8.length() + 1, buf);
					buf += 4;
					copymem(buf, utf8.get_data(), utf8.length() + 1);
					buf += utf8.length() + 1;
				}

				r_len += 4 + utf8.length() + 1;
				while (r_len % 4) {
					r_len++; //pad
					if (buf)
						buf++;
				}
			}

		} break;
		case Variant::POOL_VECTOR2_ARRAY: {

			PoolVector<Vector2> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			if (buf) {

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

					Vector2 v = data.get(i);

					encode_float(v.x, &buf[0]);
					encode_float(v.y, &buf[4]);
					buf += 4 * 2;
				}
			}

			r_len += 4 * 2 * len;

		} break;
		case Variant::POOL_VECTOR3_ARRAY: {

			PoolVector<Vector3> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			if (buf) {

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

					Vector3 v = data.get(i);

					encode_float(v.x, &buf[0]);
					encode_float(v.y, &buf[4]);
					encode_float(v.z, &buf[8]);
					buf += 4 * 3;
				}
			}

			r_len += 4 * 3 * len;

		} break;
		case Variant::POOL_COLOR_ARRAY: {

			PoolVector<Color> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			if (buf) {

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

					Color c = data.get(i);

					encode_float(c.r, &buf[0]);
					encode_float(c.g, &buf[4]);
					encode_float(c.b, &buf[8]);
					encode_float(c.a, &buf[12]);
					buf += 4 * 4;
				}
			}

			r_len += 4 * 4 * len;

		} break;
		default: { ERR_FAIL_V(ERR_BUG); }
	}

	return OK;
}
void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String &p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_force_rgbe, bool p_detect_normal, bool p_force_normal) {

	print_line("saving: " + p_to_path);
	FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE);
	f->store_8('G');
	f->store_8('D');
	f->store_8('S');
	f->store_8('T'); //godot streamable texture

	f->store_32(p_image->get_width());
	f->store_32(p_image->get_height());
	f->store_32(p_texture_flags);

	uint32_t format = 0;

	if (p_streamable)
		format |= StreamTexture::FORMAT_BIT_STREAM;
	if (p_mipmaps || p_compress_mode == COMPRESS_VIDEO_RAM) //VRAM always uses mipmaps
		format |= StreamTexture::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit
	if (p_detect_3d)
		format |= StreamTexture::FORMAT_BIT_DETECT_3D;
	if (p_detect_srgb)
		format |= StreamTexture::FORMAT_BIT_DETECT_SRGB;
	if (p_detect_normal)
		format |= StreamTexture::FORMAT_BIT_DETECT_NORMAL;

	if ((p_compress_mode == COMPRESS_LOSSLESS || p_compress_mode == COMPRESS_LOSSY) && p_image->get_format() > Image::FORMAT_RGBA8) {
		p_compress_mode == COMPRESS_UNCOMPRESSED; //these can't go as lossy
	}

	switch (p_compress_mode) {
		case COMPRESS_LOSSLESS: {

			Ref<Image> image = p_image->duplicate();
			if (p_mipmaps) {
				image->generate_mipmaps();
			} else {
				image->clear_mipmaps();
			}

			int mmc = image->get_mipmap_count() + 1;

			format |= StreamTexture::FORMAT_BIT_LOSSLESS;
			f->store_32(format);
			f->store_32(mmc);

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

				if (i > 0) {
					image->shrink_x2();
				}

				PoolVector<uint8_t> data = Image::lossless_packer(image);
				int data_len = data.size();
				f->store_32(data_len);

				PoolVector<uint8_t>::Read r = data.read();
				f->store_buffer(r.ptr(), data_len);
			}

		} break;
		case COMPRESS_LOSSY: {
			Ref<Image> image = p_image->duplicate();
			if (p_mipmaps) {
				image->generate_mipmaps();
			} else {
				image->clear_mipmaps();
			}

			int mmc = image->get_mipmap_count() + 1;

			format |= StreamTexture::FORMAT_BIT_LOSSY;
			f->store_32(format);
			f->store_32(mmc);

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

				if (i > 0) {
					image->shrink_x2();
				}

				PoolVector<uint8_t> data = Image::lossy_packer(image, p_lossy_quality);
				int data_len = data.size();
				f->store_32(data_len);

				PoolVector<uint8_t>::Read r = data.read();
				f->store_buffer(r.ptr(), data_len);
			}
		} break;
		case COMPRESS_VIDEO_RAM: {

			Ref<Image> image = p_image->duplicate();
			image->generate_mipmaps();

			if (p_force_rgbe && image->get_format() >= Image::FORMAT_R8 && image->get_format() <= Image::FORMAT_RGBE9995) {
				image->convert(Image::FORMAT_RGBE9995);
			} else {
				Image::CompressSource csource = Image::COMPRESS_SOURCE_GENERIC;
				if (p_force_normal) {
					csource = Image::COMPRESS_SOURCE_NORMAL;
				} else if (p_texture_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
					csource = Image::COMPRESS_SOURCE_SRGB;
				}

				image->compress(p_vram_compression, csource, p_lossy_quality);
			}

			format |= image->get_format();

			f->store_32(format);

			PoolVector<uint8_t> data = image->get_data();
			int dl = data.size();
			PoolVector<uint8_t>::Read r = data.read();
			f->store_buffer(r.ptr(), dl);
		} break;
		case COMPRESS_UNCOMPRESSED: {

			Ref<Image> image = p_image->duplicate();
			if (p_mipmaps) {
				image->generate_mipmaps();
			} else {
				image->clear_mipmaps();
			}

			format |= image->get_format();
			f->store_32(format);

			PoolVector<uint8_t> data = image->get_data();
			int dl = data.size();
			PoolVector<uint8_t>::Read r = data.read();

			f->store_buffer(r.ptr(), dl);

		} break;
	}

	memdelete(f);
}
Example #22
0
void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressSource p_source) {

	if (p_image->get_format() >= Image::FORMAT_BPTC_RGBA)
		return; //do not compress, already compressed

	int w = p_image->get_width();
	int h = p_image->get_height();

	bool is_ldr = (p_image->get_format() <= Image::FORMAT_RGBA8);
	bool is_hdr = (p_image->get_format() == Image::FORMAT_RGBH);

	if (!is_ldr && !is_hdr) {
		return; // Not a usable source format
	}

	cvtt::Options options;
	uint32_t flags = cvtt::Flags::Fastest;

	if (p_lossy_quality > 0.85)
		flags = cvtt::Flags::Ultra;
	else if (p_lossy_quality > 0.75)
		flags = cvtt::Flags::Better;
	else if (p_lossy_quality > 0.55)
		flags = cvtt::Flags::Default;
	else if (p_lossy_quality > 0.35)
		flags = cvtt::Flags::Fast;
	else if (p_lossy_quality > 0.15)
		flags = cvtt::Flags::Faster;

	flags |= cvtt::Flags::BC7_RespectPunchThrough;

	if (p_source == Image::COMPRESS_SOURCE_NORMAL) {
		flags |= cvtt::Flags::Uniform;
	}

	Image::Format target_format = Image::FORMAT_BPTC_RGBA;

	bool is_signed = false;
	if (is_hdr) {
		PoolVector<uint8_t>::Read rb = p_image->get_data().read();

		const uint16_t *source_data = reinterpret_cast<const uint16_t *>(&rb[0]);
		int pixel_element_count = w * h * 3;
		for (int i = 0; i < pixel_element_count; i++) {
			if ((source_data[i] & 0x8000) != 0 && (source_data[i] & 0x7fff) != 0) {
				is_signed = true;
				break;
			}
		}

		target_format = is_signed ? Image::FORMAT_BPTC_RGBF : Image::FORMAT_BPTC_RGBFU;
	} else {
		p_image->convert(Image::FORMAT_RGBA8); //still uses RGBA to convert
	}

	PoolVector<uint8_t>::Read rb = p_image->get_data().read();

	PoolVector<uint8_t> data;
	int target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps());
	int mm_count = p_image->has_mipmaps() ? Image::get_image_required_mipmaps(w, h, target_format) : 0;
	data.resize(target_size);
	int shift = Image::get_format_pixel_rshift(target_format);

	PoolVector<uint8_t>::Write wb = data.write();

	int dst_ofs = 0;

	CVTTCompressionJobQueue job_queue;
	job_queue.job_params.is_hdr = is_hdr;
	job_queue.job_params.is_signed = is_signed;
	job_queue.job_params.options = options;
	job_queue.job_params.bytes_per_pixel = is_hdr ? 6 : 4;

#ifdef NO_THREADS
	int num_job_threads = 0;
#else
	int num_job_threads = OS::get_singleton()->can_use_threads() ? (OS::get_singleton()->get_processor_count() - 1) : 0;
#endif

	PoolVector<CVTTCompressionRowTask> tasks;

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

		int bw = w % 4 != 0 ? w + (4 - w % 4) : w;
		int bh = h % 4 != 0 ? h + (4 - h % 4) : h;

		int src_ofs = p_image->get_mipmap_offset(i);

		const uint8_t *in_bytes = &rb[src_ofs];
		uint8_t *out_bytes = &wb[dst_ofs];

		for (int y_start = 0; y_start < h; y_start += 4) {
			int y_end = y_start + 4;

			CVTTCompressionRowTask row_task;
			row_task.width = w;
			row_task.height = h;
			row_task.y_start = y_start;
			row_task.in_mm_bytes = in_bytes;
			row_task.out_mm_bytes = out_bytes;

			if (num_job_threads > 0) {
				tasks.push_back(row_task);
			} else {
				_digest_row_task(job_queue.job_params, row_task);
			}

			out_bytes += 16 * (bw / 4);
		}

		dst_ofs += (MAX(4, bw) * MAX(4, bh)) >> shift;
		w = MAX(w / 2, 1);
		h = MAX(h / 2, 1);
	}

	if (num_job_threads > 0) {
		PoolVector<Thread *> threads;
		threads.resize(num_job_threads);

		PoolVector<Thread *>::Write threads_wb = threads.write();

		PoolVector<CVTTCompressionRowTask>::Read tasks_rb = tasks.read();

		job_queue.job_tasks = &tasks_rb[0];
		job_queue.current_task = 0;
		job_queue.num_tasks = static_cast<uint32_t>(tasks.size());

		for (int i = 0; i < num_job_threads; i++) {
			threads_wb[i] = Thread::create(_digest_job_queue, &job_queue);
		}
		_digest_job_queue(&job_queue);

		for (int i = 0; i < num_job_threads; i++) {
			Thread::wait_to_finish(threads_wb[i]);
			memdelete(threads_wb[i]);
		}
	}

	p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
}
Example #23
0
RES ResourceFormatPBM::load(const String &p_path,const String& p_original_path,Error *r_error) {

#define _RETURN(m_err)\
{\
	if (r_error)\
		*r_error=m_err;\
	ERR_FAIL_V(RES());\
}


	FileAccessRef f=FileAccess::open(p_path,FileAccess::READ);
	uint8_t saved=0;
	if (!f)
		_RETURN(ERR_CANT_OPEN);

	PoolVector<uint8_t> token;

	if (!_get_token(f,saved,token)) {
		_RETURN(ERR_PARSE_ERROR);
	}

	if (token.size()!=2) {
		_RETURN(ERR_FILE_CORRUPT);
	}
	if (token[0]!='P') {
		_RETURN(ERR_FILE_CORRUPT);
	}
	if (token[1]!='1' && token[1]!='4') {
		_RETURN(ERR_FILE_CORRUPT);
	}

	bool bits = token[1]=='4';

	if (!_get_token(f,saved,token)) {
		_RETURN(ERR_PARSE_ERROR);
	}

	int width = _get_number_from_token(token);
	if (width<=0) {
		_RETURN(ERR_FILE_CORRUPT);
	}


	if (!_get_token(f,saved,token)) {
		_RETURN(ERR_PARSE_ERROR);
	}

	int height = _get_number_from_token(token);
	if (height<=0) {
		_RETURN(ERR_FILE_CORRUPT);
	}


	Ref<BitMap> bm;
	bm.instance();
	bm->create(Size2i(width,height));

	if (!bits) {

		int required_bytes = width*height;
		if (!_get_token(f,saved,token,false,true)) {
			_RETURN(ERR_PARSE_ERROR);
		}

		if (token.size()<required_bytes) {
			_RETURN(ERR_FILE_CORRUPT);
		}

		PoolVector<uint8_t>::Read r=token.read();
			
		for(int i=0;i<height;i++) {
			for(int j=0;j<width;j++) {


				char num = r[i*width+j];
				bm->set_bit(Point2i(j,i),num=='0');
			}

		}



	} else {
		//a single, entire token of bits!
		if (!_get_token(f,saved,token,true)) {
			_RETURN(ERR_PARSE_ERROR);
		}
		int required_bytes = Math::ceil((width*height)/8.0);
		if (token.size()<required_bytes) {
			_RETURN(ERR_FILE_CORRUPT);
		}

		PoolVector<uint8_t>::Read r=token.read();
		int bitwidth = width;
		if (bitwidth % 8)
			bitwidth+=8-(bitwidth%8);

		for(int i=0;i<height;i++) {
			for(int j=0;j<width;j++) {

				int ofs = bitwidth*i+j;

				uint8_t byte = r[ofs/8];
				bool bit = (byte>>(7-(ofs%8)))&1;

				bm->set_bit(Point2i(j,i),!bit);

			}

		}

	}

	return bm;


}
void Particles2DEditorPlugin::_generate_emission_mask() {

	Ref<ParticlesMaterial> pm = particles->get_process_material();
	if (!pm.is_valid()) {
		EditorNode::get_singleton()->show_warning(TTR("Can only set point into a ParticlesMaterial process material"));
		return;
	}

	Ref<Image> img;
	img.instance();
	Error err = ImageLoader::load_image(source_emission_file, img);
	ERR_EXPLAIN(TTR("Error loading image:") + " " + source_emission_file);
	ERR_FAIL_COND(err != OK);

	if (img->is_compressed()) {
		img->decompress();
	}
	img->convert(Image::FORMAT_RGBA8);
	ERR_FAIL_COND(img->get_format() != Image::FORMAT_RGBA8);
	Size2i s = Size2(img->get_width(), img->get_height());
	ERR_FAIL_COND(s.width == 0 || s.height == 0);

	Vector<Point2> valid_positions;
	Vector<Point2> valid_normals;
	Vector<uint8_t> valid_colors;

	valid_positions.resize(s.width * s.height);

	EmissionMode emode = (EmissionMode)emission_mask_mode->get_selected();

	if (emode == EMISSION_MODE_BORDER_DIRECTED) {
		valid_normals.resize(s.width * s.height);
	}

	bool capture_colors = emission_colors->is_pressed();

	if (capture_colors) {
		valid_colors.resize(s.width * s.height * 4);
	}

	int vpc = 0;

	{
		PoolVector<uint8_t> data = img->get_data();
		PoolVector<uint8_t>::Read r = data.read();

		for (int i = 0; i < s.width; i++) {
			for (int j = 0; j < s.height; j++) {

				uint8_t a = r[(j * s.width + i) * 4 + 3];

				if (a > 128) {

					if (emode == EMISSION_MODE_SOLID) {

						if (capture_colors) {
							valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0];
							valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1];
							valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2];
							valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3];
						}
						valid_positions.write[vpc++] = Point2(i, j);

					} else {

						bool on_border = false;
						for (int x = i - 1; x <= i + 1; x++) {
							for (int y = j - 1; y <= j + 1; y++) {

								if (x < 0 || y < 0 || x >= s.width || y >= s.height || r[(y * s.width + x) * 4 + 3] <= 128) {
									on_border = true;
									break;
								}
							}

							if (on_border)
								break;
						}

						if (on_border) {
							valid_positions.write[vpc] = Point2(i, j);

							if (emode == EMISSION_MODE_BORDER_DIRECTED) {
								Vector2 normal;
								for (int x = i - 2; x <= i + 2; x++) {
									for (int y = j - 2; y <= j + 2; y++) {

										if (x == i && y == j)
											continue;

										if (x < 0 || y < 0 || x >= s.width || y >= s.height || r[(y * s.width + x) * 4 + 3] <= 128) {
											normal += Vector2(x - i, y - j).normalized();
										}
									}
								}

								normal.normalize();
								valid_normals.write[vpc] = normal;
							}

							if (capture_colors) {
								valid_colors.write[vpc * 4 + 0] = r[(j * s.width + i) * 4 + 0];
								valid_colors.write[vpc * 4 + 1] = r[(j * s.width + i) * 4 + 1];
								valid_colors.write[vpc * 4 + 2] = r[(j * s.width + i) * 4 + 2];
								valid_colors.write[vpc * 4 + 3] = r[(j * s.width + i) * 4 + 3];
							}

							vpc++;
						}
					}
				}
			}
		}
	}

	valid_positions.resize(vpc);
	if (valid_normals.size()) {
		valid_normals.resize(vpc);
	}

	ERR_EXPLAIN(TTR("No pixels with transparency > 128 in image..."));
	ERR_FAIL_COND(valid_positions.size() == 0);

	PoolVector<uint8_t> texdata;

	int w = 2048;
	int h = (vpc / 2048) + 1;

	texdata.resize(w * h * 2 * sizeof(float));

	{
		PoolVector<uint8_t>::Write tw = texdata.write();
		float *twf = (float *)tw.ptr();
		for (int i = 0; i < vpc; i++) {

			twf[i * 2 + 0] = valid_positions[i].x;
			twf[i * 2 + 1] = valid_positions[i].y;
		}
	}

	img.instance();
	img->create(w, h, false, Image::FORMAT_RGF, texdata);

	Ref<ImageTexture> imgt;
	imgt.instance();
	imgt->create_from_image(img, 0);

	pm->set_emission_point_texture(imgt);
	pm->set_emission_point_count(vpc);

	if (capture_colors) {

		PoolVector<uint8_t> colordata;
		colordata.resize(w * h * 4); //use RG texture

		{
			PoolVector<uint8_t>::Write tw = colordata.write();
			for (int i = 0; i < vpc * 4; i++) {

				tw[i] = valid_colors[i];
			}
		}

		img.instance();
		img->create(w, h, false, Image::FORMAT_RGBA8, colordata);

		imgt.instance();
		imgt->create_from_image(img, 0);
		pm->set_emission_color_texture(imgt);
	}

	if (valid_normals.size()) {
		pm->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS);

		PoolVector<uint8_t> normdata;
		normdata.resize(w * h * 2 * sizeof(float)); //use RG texture

		{
			PoolVector<uint8_t>::Write tw = normdata.write();
			float *twf = (float *)tw.ptr();
			for (int i = 0; i < vpc; i++) {
				twf[i * 2 + 0] = valid_normals[i].x;
				twf[i * 2 + 1] = valid_normals[i].y;
			}
		}

		img.instance();
		img->create(w, h, false, Image::FORMAT_RGF, normdata);

		imgt.instance();
		imgt->create_from_image(img, 0);
		pm->set_emission_normal_texture(imgt);

	} else {
		pm->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_POINTS);
	}
}
Example #25
0
void SoftBodyBullet::set_trimesh_body_shape(PoolVector<int> p_indices, PoolVector<Vector3> p_vertices) {
	/// Assert the current soft body is destroyed
	destroy_soft_body();

	/// Parse visual server indices to physical indices.
	/// Merge all overlapping vertices and create a map of physical vertices to visual server

	{
		/// This is the map of visual server indices to physics indices (So it's the inverse of idices_map), Thanks to it I don't need make a heavy search in the indices_map
		Vector<int> vs_indices_to_physics_table;

		{ // Map vertices
			indices_table.resize(0);

			int index = 0;
			Map<Vector3, int> unique_vertices;

			const int vs_vertices_size(p_vertices.size());

			PoolVector<Vector3>::Read p_vertices_read = p_vertices.read();

			for (int vs_vertex_index = 0; vs_vertex_index < vs_vertices_size; ++vs_vertex_index) {

				Map<Vector3, int>::Element *e = unique_vertices.find(p_vertices_read[vs_vertex_index]);
				int vertex_id;
				if (e) {
					// Already rxisting
					vertex_id = e->value();
				} else {
					// Create new one
					unique_vertices[p_vertices_read[vs_vertex_index]] = vertex_id = index++;
					indices_table.push_back(Vector<int>());
				}

				indices_table.write[vertex_id].push_back(vs_vertex_index);
				vs_indices_to_physics_table.push_back(vertex_id);
			}
		}

		const int indices_map_size(indices_table.size());

		Vector<btScalar> bt_vertices;

		{ // Parse vertices to bullet

			bt_vertices.resize(indices_map_size * 3);
			PoolVector<Vector3>::Read p_vertices_read = p_vertices.read();

			for (int i = 0; i < indices_map_size; ++i) {
				bt_vertices.write[3 * i + 0] = p_vertices_read[indices_table[i][0]].x;
				bt_vertices.write[3 * i + 1] = p_vertices_read[indices_table[i][0]].y;
				bt_vertices.write[3 * i + 2] = p_vertices_read[indices_table[i][0]].z;
			}
		}

		Vector<int> bt_triangles;
		const int triangles_size(p_indices.size() / 3);

		{ // Parse indices

			bt_triangles.resize(triangles_size * 3);

			PoolVector<int>::Read p_indices_read = p_indices.read();

			for (int i = 0; i < triangles_size; ++i) {
				bt_triangles.write[3 * i + 0] = vs_indices_to_physics_table[p_indices_read[3 * i + 2]];
				bt_triangles.write[3 * i + 1] = vs_indices_to_physics_table[p_indices_read[3 * i + 1]];
				bt_triangles.write[3 * i + 2] = vs_indices_to_physics_table[p_indices_read[3 * i + 0]];
			}
		}

		btSoftBodyWorldInfo fake_world_info;
		bt_soft_body = btSoftBodyHelpers::CreateFromTriMesh(fake_world_info, &bt_vertices[0], &bt_triangles[0], triangles_size, false);
		setup_soft_body();
	}
}
Example #26
0
void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {

	CSGShape *cs = Object::cast_to<CSGShape>(p_gizmo->get_spatial_node());

	p_gizmo->clear();

	Ref<Material> material = get_material("shape_material", p_gizmo);
	Ref<Material> handles_material = get_material("handles");

	PoolVector<Vector3> faces = cs->get_brush_faces();

	Vector<Vector3> lines;
	lines.resize(faces.size() * 2);
	{
		PoolVector<Vector3>::Read r = faces.read();

		for (int i = 0; i < lines.size(); i += 6) {
			int f = i / 6;
			for (int j = 0; j < 3; j++) {
				int j_n = (j + 1) % 3;
				lines.write[i + j * 2 + 0] = r[f * 3 + j];
				lines.write[i + j * 2 + 1] = r[f * 3 + j_n];
			}
		}
	}

	p_gizmo->add_lines(lines, material);
	p_gizmo->add_collision_segments(lines);

	if (Object::cast_to<CSGSphere>(cs)) {
		CSGSphere *s = Object::cast_to<CSGSphere>(cs);

		float r = s->get_radius();
		Vector<Vector3> handles;
		handles.push_back(Vector3(r, 0, 0));
		p_gizmo->add_handles(handles, handles_material);
	}

	if (Object::cast_to<CSGBox>(cs)) {
		CSGBox *s = Object::cast_to<CSGBox>(cs);

		Vector<Vector3> handles;
		handles.push_back(Vector3(s->get_width(), 0, 0));
		handles.push_back(Vector3(0, s->get_height(), 0));
		handles.push_back(Vector3(0, 0, s->get_depth()));
		p_gizmo->add_handles(handles, handles_material);
	}

	if (Object::cast_to<CSGCylinder>(cs)) {
		CSGCylinder *s = Object::cast_to<CSGCylinder>(cs);

		Vector<Vector3> handles;
		handles.push_back(Vector3(s->get_radius(), 0, 0));
		handles.push_back(Vector3(0, s->get_height() * 0.5, 0));
		p_gizmo->add_handles(handles, handles_material);
	}

	if (Object::cast_to<CSGTorus>(cs)) {
		CSGTorus *s = Object::cast_to<CSGTorus>(cs);

		Vector<Vector3> handles;
		handles.push_back(Vector3(s->get_inner_radius(), 0, 0));
		handles.push_back(Vector3(s->get_outer_radius(), 0, 0));
		p_gizmo->add_handles(handles, handles_material);
	}
}