Array StreamPeer::_get_partial_data(int p_bytes) { Array ret; PoolVector<uint8_t> data; data.resize(p_bytes); if (data.size() != p_bytes) { ret.push_back(ERR_OUT_OF_MEMORY); ret.push_back(PoolVector<uint8_t>()); return ret; } PoolVector<uint8_t>::Write w = data.write(); int received; Error err = get_partial_data(&w[0], p_bytes, received); w = PoolVector<uint8_t>::Write(); if (err != OK) { data.resize(0); } else if (received != data.size()) { data.resize(received); } ret.push_back(err); ret.push_back(data); return ret; }
Dictionary PolygonPathFinder::_get_data() const { Dictionary d; PoolVector<Vector2> p; PoolVector<int> ind; Array connections; p.resize(points.size() - 2); connections.resize(points.size() - 2); ind.resize(edges.size() * 2); PoolVector<float> penalties; penalties.resize(points.size() - 2); { PoolVector<Vector2>::Write wp = p.write(); PoolVector<float>::Write pw = penalties.write(); for (int i = 0; i < points.size() - 2; i++) { wp[i] = points[i].pos; pw[i] = points[i].penalty; PoolVector<int> c; c.resize(points[i].connections.size()); { PoolVector<int>::Write cw = c.write(); int idx = 0; for (Set<int>::Element *E = points[i].connections.front(); E; E = E->next()) { cw[idx++] = E->get(); } } connections[i] = c; } } { PoolVector<int>::Write iw = ind.write(); int idx = 0; for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { iw[idx++] = E->get().points[0]; iw[idx++] = E->get().points[1]; } } d["bounds"] = bounds; d["points"] = p; d["penalties"] = penalties; d["connections"] = connections; d["segments"] = ind; return d; }
RES ResourceFormatLoaderDynamicFont::load(const String &p_path, const String &p_original_path, Error *r_error) { if (r_error) *r_error = ERR_FILE_CANT_OPEN; FileAccess *f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V(!f, RES()); PoolVector<uint8_t> data; data.resize(f->get_len()); ERR_FAIL_COND_V(data.size() == 0, RES()); { PoolVector<uint8_t>::Write w = data.write(); f->get_buffer(w.ptr(), data.size()); } Ref<DynamicFontData> dfd; dfd.instance(); dfd->set_font_data(data); if (r_error) *r_error = OK; return dfd; }
void VisualServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const PoolVector<Vector2> &p_shape, bool p_closed) { if (p_shape.size() < 3) { canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, p_shape); return; } PoolVector<Vector2> lines; int lc = p_shape.size() * 2; lines.resize(lc - (p_closed ? 0 : 2)); { PoolVector<Vector2>::Write w = lines.write(); PoolVector<Vector2>::Read r = p_shape.read(); int max = lc / 2; if (!p_closed) { max--; } for (int i = 0; i < max; i++) { Vector2 a = r[i]; Vector2 b = r[(i + 1) % (lc / 2)]; w[i * 2 + 0] = a; w[i * 2 + 1] = b; } } canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, lines); }
Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) { bool loop = p_options["loop"]; FileAccess *f = FileAccess::open(p_source_file, FileAccess::READ); if (!f) { ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); } size_t len = f->get_len(); PoolVector<uint8_t> data; data.resize(len); PoolVector<uint8_t>::Write w = data.write(); f->get_buffer(w.ptr(), len); memdelete(f); Ref<AudioStreamOGGVorbis> ogg_stream; ogg_stream.instance(); ogg_stream->set_data(data); ogg_stream->set_loop(loop); return ResourceSaver::save(p_save_path + ".asogg", ogg_stream); }
void ColorPicker::_update_presets() { Size2 size = bt_add_preset->get_size(); preset->set_custom_minimum_size(Size2(size.width * presets.size(), size.height)); PoolVector<uint8_t> img; img.resize(size.x * presets.size() * size.y * 3); { PoolVector<uint8_t>::Write w = img.write(); for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x * presets.size(); x++) { int ofs = (y * (size.x * presets.size()) + x) * 3; w[ofs + 0] = uint8_t(CLAMP(presets[(int)x / size.x].r * 255.0, 0, 255)); w[ofs + 1] = uint8_t(CLAMP(presets[(int)x / size.x].g * 255.0, 0, 255)); w[ofs + 2] = uint8_t(CLAMP(presets[(int)x / size.x].b * 255.0, 0, 255)); } } } Ref<Image> i = memnew(Image(size.x * presets.size(), size.y, false, Image::FORMAT_RGB8, img)); Ref<ImageTexture> t; t.instance(); t->create_from_image(i); preset->set_texture(t); }
Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const { if (triangle_mesh.is_valid()) return triangle_mesh; PoolVector<Vector3> faces; faces.resize(6); PoolVector<Vector3>::Write facesw = faces.write(); Rect2 final_rect = get_item_rect(); if (final_rect.size.x == 0 || final_rect.size.y == 0) return Ref<TriangleMesh>(); float pixel_size = get_pixel_size(); Vector2 vertices[4] = { (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, final_rect.position * pixel_size, }; int x_axis = ((axis + 1) % 3); int y_axis = ((axis + 2) % 3); if (axis != Vector3::AXIS_Z) { SWAP(x_axis, y_axis); for (int i = 0; i < 4; i++) { if (axis == Vector3::AXIS_Y) { vertices[i].y = -vertices[i].y; } else if (axis == Vector3::AXIS_X) { vertices[i].x = -vertices[i].x; } } } static const int indices[6] = { 0, 1, 2, 0, 2, 3 }; for (int j = 0; j < 6; j++) { int i = indices[j]; Vector3 vtx; vtx[x_axis] = vertices[i][0]; vtx[y_axis] = vertices[i][1]; facesw[j] = vtx; } facesw = PoolVector<Vector3>::Write(); triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); triangle_mesh->create(faces); return triangle_mesh; }
void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { if (unparenting || !can_update_body) return; CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>(); ERR_FAIL_COND(!co); if (polygon.size() == 0) return; bool solids = build_mode == BUILD_SOLIDS; if (solids) { //here comes the sun, lalalala //decompose concave into multiple convex polygons and add them Vector<Vector<Vector2> > decomp = _decompose_in_convex(); shape_from = co->get_shape_count(); for (int i = 0; i < decomp.size(); i++) { Ref<ConvexPolygonShape2D> convex = memnew(ConvexPolygonShape2D); convex->set_points(decomp[i]); co->add_shape(convex, get_transform()); if (trigger) co->set_shape_as_trigger(co->get_shape_count() - 1, true); } shape_to = co->get_shape_count() - 1; if (shape_to < shape_from) { shape_from = -1; shape_to = -1; } } else { Ref<ConcavePolygonShape2D> concave = memnew(ConcavePolygonShape2D); PoolVector<Vector2> segments; segments.resize(polygon.size() * 2); PoolVector<Vector2>::Write w = segments.write(); for (int i = 0; i < polygon.size(); i++) { w[(i << 1) + 0] = polygon[i]; w[(i << 1) + 1] = polygon[(i + 1) % polygon.size()]; } w = PoolVector<Vector2>::Write(); concave->set_segments(segments); co->add_shape(concave, get_transform()); if (trigger) co->set_shape_as_trigger(co->get_shape_count() - 1, true); shape_from = co->get_shape_count() - 1; shape_to = co->get_shape_count() - 1; } //co->add_shape(shape,get_transform()); }
void QuadMesh::_create_mesh_array(Array &p_arr) const { PoolVector<Vector3> faces; PoolVector<Vector3> normals; PoolVector<float> tangents; PoolVector<Vector2> uvs; faces.resize(4); normals.resize(4); tangents.resize(4 * 4); uvs.resize(4); Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f); Vector3 quad_faces[4] = { Vector3(-_size.x, -_size.y, 0), Vector3(-_size.x, _size.y, 0), Vector3(_size.x, _size.y, 0), Vector3(_size.x, -_size.y, 0), }; for (int i = 0; i < 4; i++) { faces.set(i, quad_faces[i]); normals.set(i, Vector3(0, 0, 1)); tangents.set(i * 4 + 0, 1.0); tangents.set(i * 4 + 1, 0.0); tangents.set(i * 4 + 2, 0.0); tangents.set(i * 4 + 3, 1.0); static const Vector2 quad_uv[4] = { Vector2(0, 1), Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), }; uvs.set(i, quad_uv[i]); } p_arr[VS::ARRAY_VERTEX] = faces; p_arr[VS::ARRAY_NORMAL] = normals; p_arr[VS::ARRAY_TANGENT] = tangents; p_arr[VS::ARRAY_TEX_UV] = uvs; };
void GDAPI godot_pool_color_array_new_with_array(godot_pool_color_array *r_dest, const godot_array *p_a) { PoolVector<Color> *dest = (PoolVector<Color> *)r_dest; Array *a = (Array *)p_a; memnew_placement(dest, PoolVector<Color>); dest->resize(a->size()); for (int i = 0; i < a->size(); i++) { dest->set(i, (*a)[i]); } }
bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { String name = p_name; if (name == "theme") { r_ret = get_theme(); } else if (name == "cell_size") { r_ret = get_cell_size(); } else if (name == "cell_octant_size") { r_ret = get_octant_size(); } else if (name == "cell_center_x") { r_ret = get_center_x(); } else if (name == "cell_center_y") { r_ret = get_center_y(); } else if (name == "cell_center_z") { r_ret = get_center_z(); } else if (name == "cell_scale") { r_ret = cell_scale; } else if (name == "data") { Dictionary d; PoolVector<int> cells; cells.resize(cell_map.size() * 3); { PoolVector<int>::Write w = cells.write(); int i = 0; for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next(), i++) { encode_uint64(E->key().key, (uint8_t *)&w[i * 3]); encode_uint32(E->get().cell, (uint8_t *)&w[i * 3 + 2]); } } d["cells"] = cells; r_ret = d; } else if (name.begins_with("areas/")) { int which = name.get_slicec('/', 1).to_int(); String what = name.get_slicec('/', 2); if (what == "bounds") r_ret = area_get_bounds(which); else if (what == "name") r_ret = area_get_name(which); else if (what == "disable_distance") r_ret = area_get_portal_disable_distance(which); else if (what == "exterior_portal") r_ret = area_is_exterior_portal(which); else return false; } else return false; return true; }
PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { ERR_FAIL_COND_V(!points.has(p_from_id),PoolVector<Vector3>()); ERR_FAIL_COND_V(!points.has(p_to_id),PoolVector<Vector3>()); pass++; Point* a = points[p_from_id]; Point* b = points[p_to_id]; if (a==b) { PoolVector<Vector3> ret; ret.push_back(a->pos); return ret; } Point *begin_point=a; Point *end_point=b; bool found_route=_solve(begin_point,end_point); if (!found_route) return PoolVector<Vector3>(); //midpoints Point *p=end_point; int pc=1; //begin point while(p!=begin_point) { pc++; p=p->prev_point; } PoolVector<Vector3> path; path.resize(pc); { PoolVector<Vector3>::Write w = path.write(); Point *p=end_point; int idx=pc-1; while(p!=begin_point) { w[idx--]=p->pos; p=p->prev_point; } w[0]=p->pos; //assign first } return path; }
void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) { ERR_FAIL_COND(p_packet_len < 2); PoolVector<uint8_t> out; int len = p_packet_len - 1; out.resize(len); { PoolVector<uint8_t>::Write w = out.write(); memcpy(&w[0], &p_packet[1], len); } emit_signal("network_peer_packet", p_from, out); }
PoolVector<String> Translation::_get_message_list() const { PoolVector<String> msgs; msgs.resize(translation_map.size()); int idx = 0; for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) { msgs.set(idx, E->key()); idx += 1; } return msgs; }
void Shape::add_vertices_to_array(PoolVector<Vector3> &array, const Transform &p_xform) { Vector<Vector3> toadd = _gen_debug_mesh_lines(); if (toadd.size()) { int base = array.size(); array.resize(base + toadd.size()); PoolVector<Vector3>::Write w = array.write(); for (int i = 0; i < toadd.size(); i++) { w[i + base] = p_xform.xform(toadd[i]); } } }
PoolVector<Vector3> ConcavePolygonShapeSW::get_faces() const { PoolVector<Vector3> rfaces; rfaces.resize(faces.size() * 3); for (int i = 0; i < faces.size(); i++) { Face f = faces.get(i); for (int j = 0; j < 3; j++) { rfaces.set(i * 3 + j, vertices.get(f.indices[j])); } } return rfaces; }
Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) const { const uint8_t *buffer; int buffer_size; Error err = get_packet(&buffer, buffer_size); if (err) return err; r_buffer.resize(buffer_size); if (buffer_size == 0) return OK; PoolVector<uint8_t>::Write w = r_buffer.write(); for (int i = 0; i < buffer_size; i++) w[i] = buffer[i]; return OK; }
bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { String name = p_name; if (name == "theme") { r_ret = get_theme(); } else if (name == "cell_size") { r_ret = get_cell_size(); } else if (name == "cell_octant_size") { r_ret = get_octant_size(); } else if (name == "cell_center_x") { r_ret = get_center_x(); } else if (name == "cell_center_y") { r_ret = get_center_y(); } else if (name == "cell_center_z") { r_ret = get_center_z(); } else if (name == "cell_scale") { r_ret = cell_scale; } else if (name == "data") { Dictionary d; PoolVector<int> cells; cells.resize(cell_map.size() * 3); { PoolVector<int>::Write w = cells.write(); int i = 0; for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next(), i++) { encode_uint64(E->key().key, (uint8_t *)&w[i * 3]); encode_uint32(E->get().cell, (uint8_t *)&w[i * 3 + 2]); } } d["cells"] = cells; r_ret = d; } else return false; return true; }
Array StreamPeer::_get_data(int p_bytes) { Array ret; PoolVector<uint8_t> data; data.resize(p_bytes); if (data.size() != p_bytes) { ret.push_back(ERR_OUT_OF_MEMORY); ret.push_back(PoolVector<uint8_t>()); return ret; } PoolVector<uint8_t>::Write w = data.write(); Error err = get_data(&w[0], p_bytes); w = PoolVector<uint8_t>::Write(); ret.push_back(err); ret.push_back(data); return ret; }
void image_decompress_squish(Image *p_image) { int w = p_image->get_width(); int h = p_image->get_height(); Image::Format target_format = Image::FORMAT_RGBA8; PoolVector<uint8_t> data; int target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps() ? -1 : 0); int mm_count = p_image->get_mipmap_count(); data.resize(target_size); PoolVector<uint8_t>::Read rb = p_image->get_data().read(); PoolVector<uint8_t>::Write wb = data.write(); int squish_flags = Image::FORMAT_MAX; if (p_image->get_format() == Image::FORMAT_DXT1) { squish_flags = squish::kDxt1; } else if (p_image->get_format() == Image::FORMAT_DXT3) { squish_flags = squish::kDxt3; } else if (p_image->get_format() == Image::FORMAT_DXT5) { squish_flags = squish::kDxt5; } else if (p_image->get_format() == Image::FORMAT_RGTC_R) { squish_flags = squish::kBc4; } else if (p_image->get_format() == Image::FORMAT_RGTC_RG) { squish_flags = squish::kBc5; } else { print_line("wtf askd to decompress.. " + itos(p_image->get_format())); ERR_FAIL_COND(true); return; } int dst_ofs = 0; for (int i = 0; i <= mm_count; i++) { int src_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0; p_image->get_mipmap_offset_size_and_dimensions(i, src_ofs, mipmap_size, mipmap_w, mipmap_h); squish::DecompressImage(&wb[dst_ofs], mipmap_w, mipmap_h, &rb[src_ofs], squish_flags); } p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); }
PoolVector<Face3> TriangleMesh::get_faces() const { if (!valid) return PoolVector<Face3>(); PoolVector<Face3> faces; int ts = triangles.size(); faces.resize(triangles.size()); PoolVector<Face3>::Write w = faces.write(); PoolVector<Triangle>::Read r = triangles.read(); PoolVector<Vector3>::Read rv = vertices.read(); for (int i = 0; i < ts; i++) { for (int j = 0; j < 3; j++) { w[i].vertex[j] = rv[r[i].indices[j]]; } } w = PoolVector<Face3>::Write(); return faces; }
Ref<Image> SimplexNoise::get_image(int p_width, int p_height) { PoolVector<uint8_t> data; data.resize(p_width * p_height * 4); PoolVector<uint8_t>::Write wd8 = data.write(); for (int i = 0; i < p_height; i++) { for (int j = 0; j < p_width; j++) { float v = get_noise_2d(i, j); v = v * 0.5 + 0.5; // Normalize [0..1] uint8_t value = uint8_t(CLAMP(v * 255.0, 0, 255)); wd8[(i * p_width + j) * 4 + 0] = value; wd8[(i * p_width + j) * 4 + 1] = value; wd8[(i * p_width + j) * 4 + 2] = value; wd8[(i * p_width + j) * 4 + 3] = 255; } } Ref<Image> image = memnew(Image(p_width, p_height, false, Image::FORMAT_RGBA8, data)); return image; }
void CollisionPolygon::_build_polygon() { if (!parent) return; parent->shape_owner_clear_shapes(owner_id); if (polygon.size() == 0) return; Vector<Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); if (decomp.size() == 0) return; //here comes the sun, lalalala //decompose concave into multiple convex polygons and add them for (int i = 0; i < decomp.size(); i++) { Ref<ConvexPolygonShape> convex = memnew(ConvexPolygonShape); PoolVector<Vector3> cp; int cs = decomp[i].size(); cp.resize(cs * 2); { PoolVector<Vector3>::Write w = cp.write(); int idx = 0; for (int j = 0; j < cs; j++) { Vector2 d = decomp[i][j]; w[idx++] = Vector3(d.x, d.y, depth * 0.5); w[idx++] = Vector3(d.x, d.y, -depth * 0.5); } } convex->set_points(cp); parent->shape_owner_add_shape(owner_id, convex); parent->shape_owner_set_disabled(owner_id, disabled); } }
Error read_all_file_utf8(const String &p_path, String &r_content) { PoolVector<uint8_t> sourcef; Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); ERR_FAIL_COND_V(err != OK, err); int len = f->get_len(); sourcef.resize(len + 1); PoolVector<uint8_t>::Write w = sourcef.write(); int r = f->get_buffer(w.ptr(), len); f->close(); memdelete(f); ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN); w[len] = 0; String source; if (source.parse_utf8((const char *)w.ptr())) { ERR_FAIL_V(ERR_INVALID_DATA); } r_content = source; return OK; }
Ref<ArrayMesh> Shape::get_debug_mesh() { if (debug_mesh_cache.is_valid()) return debug_mesh_cache; Vector<Vector3> lines = _gen_debug_mesh_lines(); debug_mesh_cache = Ref<ArrayMesh>(memnew(ArrayMesh)); if (!lines.empty()) { //make mesh PoolVector<Vector3> array; array.resize(lines.size()); { PoolVector<Vector3>::Write w = array.write(); for (int i = 0; i < lines.size(); i++) { w[i] = lines[i]; } } Array arr; arr.resize(Mesh::ARRAY_MAX); arr[Mesh::ARRAY_VERTEX] = array; SceneTree *st = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop()); debug_mesh_cache->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr); if (st) { debug_mesh_cache->surface_set_material(0, st->get_debug_collision_material()); } } return debug_mesh_cache; }
Ref<Image> SimplexNoise::get_seamless_image(int p_size) { PoolVector<uint8_t> data; data.resize(p_size * p_size * 4); PoolVector<uint8_t>::Write wd8 = data.write(); for (int i = 0; i < p_size; i++) { for (int j = 0; j < p_size; j++) { float ii = (float)i / (float)p_size; float jj = (float)j / (float)p_size; ii *= 2.0 * Math_PI; jj *= 2.0 * Math_PI; float radius = p_size / (2.0 * Math_PI); float x = radius * Math::sin(jj); float y = radius * Math::cos(jj); float z = radius * Math::sin(ii); float w = radius * Math::cos(ii); float v = get_noise_4d(x, y, z, w); v = v * 0.5 + 0.5; // Normalize [0..1] uint8_t value = uint8_t(CLAMP(v * 255.0, 0, 255)); wd8[(i * p_size + j) * 4 + 0] = value; wd8[(i * p_size + j) * 4 + 1] = value; wd8[(i * p_size + j) * 4 + 2] = value; wd8[(i * p_size + j) * 4 + 3] = 255; } } Ref<Image> image = memnew(Image(p_size, p_size, false, Image::FORMAT_RGBA8, data)); return image; }
static PoolVector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quality) { ERR_FAIL_COND_V(p_image.is_null() || p_image->empty(), PoolVector<uint8_t>()); Ref<Image> img = p_image->duplicate(); if (img->detect_alpha()) img->convert(Image::FORMAT_RGBA8); else img->convert(Image::FORMAT_RGB8); Size2 s(img->get_width(), img->get_height()); PoolVector<uint8_t> data = img->get_data(); PoolVector<uint8_t>::Read r = data.read(); uint8_t *dst_buff = NULL; size_t dst_size = 0; if (img->get_format() == Image::FORMAT_RGB8) { dst_size = WebPEncodeRGB(r.ptr(), s.width, s.height, 3 * s.width, CLAMP(p_quality * 100.0, 0, 100.0), &dst_buff); } else { dst_size = WebPEncodeRGBA(r.ptr(), s.width, s.height, 4 * s.width, CLAMP(p_quality * 100.0, 0, 100.0), &dst_buff); } ERR_FAIL_COND_V(dst_size == 0, PoolVector<uint8_t>()); PoolVector<uint8_t> dst; dst.resize(4 + dst_size); PoolVector<uint8_t>::Write w = dst.write(); w[0] = 'W'; w[1] = 'E'; w[2] = 'B'; w[3] = 'P'; copymem(&w[4], dst_buff, dst_size); free(dst_buff); w = PoolVector<uint8_t>::Write(); return dst; }
PoolVector<Point2> Curve2D::bake(int p_subdivs) const { int pc = points.size(); PoolVector<Point2> ret; if (pc<2) return ret; ret.resize((pc-1)*p_subdivs+1); PoolVector<Point2>::Write w = ret.write(); const Point *r = points.ptr(); for(int i=0;i<pc;i++) { int ofs = pc*p_subdivs; int limit=(i==pc-1)?p_subdivs+1:p_subdivs; for(int j=0;j<limit;j++) { Vector2 p0 = r[i].pos; Vector2 p1 = p0+r[i].out; Vector2 p3 = r[i].pos; Vector2 p2 = p3+r[i].in; real_t t = j/(real_t)p_subdivs; w[ofs+j]=_bezier_interp(t,p0,p1,p2,p3); } } w = PoolVector<Point2>::Write(); return ret; }
RES ResourceFormatLoaderWAV::load(const String &p_path, const String& p_original_path, Error *r_error) { if (r_error) *r_error=ERR_FILE_CANT_OPEN; Error err; FileAccess *file=FileAccess::open(p_path, FileAccess::READ,&err); ERR_FAIL_COND_V( err!=OK, RES() ); if (r_error) *r_error=ERR_FILE_CORRUPT; /* CHECK RIFF */ char riff[5]; riff[4]=0; file->get_buffer((uint8_t*)&riff,4); //RIFF if (riff[0]!='R' || riff[1]!='I' || riff[2]!='F' || riff[3]!='F') { file->close(); memdelete(file); ERR_FAIL_V( RES() ); } /* GET FILESIZE */ uint32_t filesize=file->get_32(); /* CHECK WAVE */ char wave[4]; file->get_buffer((uint8_t*)&wave,4); //RIFF if (wave[0]!='W' || wave[1]!='A' || wave[2]!='V' || wave[3]!='E') { file->close(); memdelete(file); ERR_EXPLAIN("Not a WAV file (no WAVE RIFF Header)") ERR_FAIL_V( RES() ); } bool format_found=false; bool data_found=false; int format_bits=0; int format_channels=0; int format_freq=0; Sample::LoopFormat loop=Sample::LOOP_NONE; int loop_begin=0; int loop_end=0; Ref<Sample> sample( memnew( Sample ) ); while (!file->eof_reached()) { /* chunk */ char chunkID[4]; file->get_buffer((uint8_t*)&chunkID,4); //RIFF /* chunk size */ uint32_t chunksize=file->get_32(); uint32_t file_pos=file->get_position(); //save file pos, so we can skip to next chunk safely if (file->eof_reached()) { //ERR_PRINT("EOF REACH"); break; } if (chunkID[0]=='f' && chunkID[1]=='m' && chunkID[2]=='t' && chunkID[3]==' ' && !format_found) { /* IS FORMAT CHUNK */ uint16_t compression_code=file->get_16(); if (compression_code!=1) { ERR_PRINT("Format not supported for WAVE file (not PCM). Save WAVE files as uncompressed PCM instead."); break; } format_channels=file->get_16(); if (format_channels!=1 && format_channels !=2) { ERR_PRINT("Format not supported for WAVE file (not stereo or mono)"); break; } format_freq=file->get_32(); //sampling rate file->get_32(); // average bits/second (unused) file->get_16(); // block align (unused) format_bits=file->get_16(); // bits per sample if (format_bits%8) { ERR_PRINT("Strange number of bits in sample (not 8,16,24,32)"); break; } /* Don't need anything else, continue */ format_found=true; } if (chunkID[0]=='d' && chunkID[1]=='a' && chunkID[2]=='t' && chunkID[3]=='a' && !data_found) { /* IS FORMAT CHUNK */ data_found=true; if (!format_found) { ERR_PRINT("'data' chunk before 'format' chunk found."); break; } int frames=chunksize; frames/=format_channels; frames/=(format_bits>>3); /*print_line("chunksize: "+itos(chunksize)); print_line("channels: "+itos(format_channels)); print_line("bits: "+itos(format_bits)); */ sample->create( (format_bits==8) ? Sample::FORMAT_PCM8 : Sample::FORMAT_PCM16, (format_channels==2)?true:false, frames ); sample->set_mix_rate( format_freq ); int len=frames; if (format_channels==2) len*=2; if (format_bits>8) len*=2; PoolVector<uint8_t> data; data.resize(len); PoolVector<uint8_t>::Write dataw = data.write(); void * data_ptr = dataw.ptr(); for (int i=0;i<frames;i++) { for (int c=0;c<format_channels;c++) { if (format_bits==8) { // 8 bit samples are UNSIGNED uint8_t s = file->get_8(); s-=128; int8_t *sp=(int8_t*)&s; int8_t *data_ptr8=&((int8_t*)data_ptr)[i*format_channels+c]; *data_ptr8=*sp; } else { //16+ bits samples are SIGNED // if sample is > 16 bits, just read extra bytes uint32_t data=0; for (int b=0;b<(format_bits>>3);b++) { data|=((uint32_t)file->get_8())<<(b*8); } data<<=(32-format_bits); int32_t s=data; int16_t *data_ptr16=&((int16_t*)data_ptr)[i*format_channels+c]; *data_ptr16=s>>16; } } } dataw=PoolVector<uint8_t>::Write(); sample->set_data(data); if (file->eof_reached()) { file->close(); memdelete(file); ERR_EXPLAIN("Premature end of file."); ERR_FAIL_V(RES()); } } if (chunkID[0]=='s' && chunkID[1]=='m' && chunkID[2]=='p' && chunkID[3]=='l') { //loop point info! for(int i=0;i<10;i++) file->get_32(); // i wish to know why should i do this... no doc! loop=file->get_32()?Sample::LOOP_PING_PONG:Sample::LOOP_FORWARD; loop_begin=file->get_32(); loop_end=file->get_32(); } file->seek( file_pos+chunksize ); }
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++) {