Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data()); Error err; FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err); if (err) { ERR_PRINTS("Failed to open " + p_from); return err; } FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE, &err); if (err) { fsrc->close(); memdelete(fsrc); ERR_PRINTS("Failed to open " + p_to); return err; } fsrc->seek_end(0); int size = fsrc->get_position(); fsrc->seek(0); err = OK; while (size--) { if (fsrc->get_error() != OK) { err = fsrc->get_error(); break; } if (fdst->get_error() != OK) { err = fdst->get_error(); break; } fdst->store_8(fsrc->get_8()); } if (err == OK && p_chmod_flags != -1) { fdst->close(); err = FileAccess::set_unix_permissions(p_to, p_chmod_flags); // If running on a platform with no chmod support (i.e., Windows), don't fail if (err == ERR_UNAVAILABLE) err = OK; } memdelete(fsrc); memdelete(fdst); return err; }
Error DirAccess::copy(String p_from,String p_to) { //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data()); Error err; FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ,&err); if (err) { ERR_FAIL_COND_V( err, err ); } FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE,&err ); if (err) { fsrc->close(); memdelete( fsrc ); ERR_FAIL_COND_V( err, err ); } fsrc->seek_end(0); int size = fsrc->get_pos(); fsrc->seek(0); err = OK; while(size--) { if (fsrc->get_error()!=OK) { err= fsrc->get_error(); break; } if (fdst->get_error()!=OK) { err= fdst->get_error(); break; } fdst->store_8( fsrc->get_8() ); } memdelete(fsrc); memdelete(fdst); return err; }
Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files) { EditorProgress ep("savepack", TTR("Packing"), 102, true); String tmppath = EditorSettings::get_singleton()->get_cache_dir().plus_file("packtmp"); FileAccess *ftmp = FileAccess::open(tmppath, FileAccess::WRITE); ERR_FAIL_COND_V(!ftmp, ERR_CANT_CREATE) PackData pd; pd.ep = &ep; pd.f = ftmp; pd.so_files = p_so_files; Error err = export_project_files(p_preset, _save_pack_file, &pd, _add_shared_object); memdelete(ftmp); //close tmp file if (err) return err; pd.file_ofs.sort(); //do sort, so we can do binary search later FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE); ERR_FAIL_COND_V(!f, ERR_CANT_CREATE) f->store_32(0x43504447); //GDPK f->store_32(1); //pack version f->store_32(VERSION_MAJOR); f->store_32(VERSION_MINOR); f->store_32(0); //hmph for (int i = 0; i < 16; i++) { //reserved f->store_32(0); } f->store_32(pd.file_ofs.size()); //amount of files size_t header_size = f->get_position(); //precalculate header size for (int i = 0; i < pd.file_ofs.size(); i++) { header_size += 4; // size of path string (32 bits is enough) uint32_t string_len = pd.file_ofs[i].path_utf8.length(); header_size += string_len + _get_pad(4, string_len); ///size of path string header_size += 8; // offset to file _with_ header size included header_size += 8; // size of file header_size += 16; // md5 } size_t header_padding = _get_pad(PCK_PADDING, header_size); for (int i = 0; i < pd.file_ofs.size(); i++) { uint32_t string_len = pd.file_ofs[i].path_utf8.length(); uint32_t pad = _get_pad(4, string_len); ; f->store_32(string_len + pad); f->store_buffer((const uint8_t *)pd.file_ofs[i].path_utf8.get_data(), string_len); for (uint32_t j = 0; j < pad; j++) { f->store_8(0); } f->store_64(pd.file_ofs[i].ofs + header_padding + header_size); f->store_64(pd.file_ofs[i].size); // pay attention here, this is where file is f->store_buffer(pd.file_ofs[i].md5.ptr(), 16); //also save md5 for file } for (uint32_t j = 0; j < header_padding; j++) { f->store_8(0); } //save the rest of the data ftmp = FileAccess::open(tmppath, FileAccess::READ); if (!ftmp) { memdelete(f); ERR_FAIL_COND_V(!ftmp, ERR_CANT_CREATE) }
Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) { open(p_f,true); ERR_FAIL_COND_V(error!=OK,error); ignore_resource_parsing=true; //FileAccess FileAccess *fw = NULL; String base_path=local_path.get_base_dir(); uint64_t tag_end = f->get_pos(); while(true) { Error err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); if (err!=OK) { if (fw) { memdelete(fw); } error=ERR_FILE_CORRUPT; ERR_FAIL_V(error); } if (next_tag.name!="ext_resource") { //nothing was done if (!fw) return OK; break; } else { if (!fw) { fw=FileAccess::open(p_path+".depren",FileAccess::WRITE); if (is_scene) { fw->store_line("[gd_scene load_steps="+itos(resources_total)+" format="+itos(FORMAT_VERSION)+"]\n"); } else { fw->store_line("[gd_resource type=\""+res_type+"\" load_steps="+itos(resources_total)+" format="+itos(FORMAT_VERSION)+"]\n"); } } if (!next_tag.fields.has("path") || !next_tag.fields.has("id") || !next_tag.fields.has("type")) { memdelete(fw); error=ERR_FILE_CORRUPT; ERR_FAIL_V(error); } String path = next_tag.fields["path"]; int index = next_tag.fields["id"]; String type = next_tag.fields["type"]; bool relative=false; if (!path.begins_with("res://")) { path=base_path.plus_file(path).simplify_path(); relative=true; } if (p_map.has(path)) { String np=p_map[path]; path=np; } if (relative) { //restore relative path=base_path.path_to_file(path); } fw->store_line("[ext_resource path=\""+path+"\" type=\""+type+"\" id="+itos(index)+"]"); tag_end = f->get_pos(); } } f->seek(tag_end); uint8_t c=f->get_8(); while(!f->eof_reached()) { fw->store_8(c); c=f->get_8(); } f->close(); bool all_ok = fw->get_error()==OK; memdelete(fw); if (!all_ok) { return ERR_CANT_CREATE; } DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); da->remove(p_path); da->rename(p_path+".depren",p_path); memdelete(da); return OK; }
Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) { #if 0 open(p_f); ERR_FAIL_COND_V(error!=OK,error); //FileAccess bool old_format=false; FileAccess *fw = NULL; String base_path=local_path.get_base_dir(); while(true) { bool exit; List<String> order; Tag *tag = parse_tag(&exit,true,&order); bool done=false; if (!tag) { if (fw) { memdelete(fw); } error=ERR_FILE_CORRUPT; ERR_FAIL_COND_V(!exit,error); error=ERR_FILE_EOF; return error; } if (tag->name=="ext_resource") { if (!tag->args.has("index") || !tag->args.has("path") || !tag->args.has("type")) { old_format=true; break; } if (!fw) { fw=FileAccess::open(p_path+".depren",FileAccess::WRITE); fw->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); //no escape fw->store_line("<resource_file type=\""+resource_type+"\" subresource_count=\""+itos(resources_total)+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\">"); } String path = tag->args["path"]; String index = tag->args["index"]; String type = tag->args["type"]; bool relative=false; if (!path.begins_with("res://")) { path=base_path.plus_file(path).simplify_path(); relative=true; } if (p_map.has(path)) { String np=p_map[path]; path=np; } if (relative) { //restore relative path=base_path.path_to_file(path); } tag->args["path"]=path; tag->args["index"]=index; tag->args["type"]=type; } else { done=true; } String tagt="\t<"; if (exit) tagt+="/"; tagt+=tag->name; for(List<String>::Element *E=order.front();E;E=E->next()) { tagt+=" "+E->get()+"=\""+tag->args[E->get()]+"\""; } tagt+=">"; fw->store_line(tagt); if (done) break; close_tag("ext_resource"); fw->store_line("\t</ext_resource>"); } if (old_format) { if (fw) memdelete(fw); DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); da->remove(p_path+".depren"); memdelete(da); //f**k it, use the old approach; WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data()); Error err; FileAccess *f2 = FileAccess::open(p_path,FileAccess::READ,&err); if (err!=OK) { ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN); } Ref<ResourceInteractiveLoaderText> ria = memnew( ResourceInteractiveLoaderText ); ria->local_path=Globals::get_singleton()->localize_path(p_path); ria->res_path=ria->local_path; ria->remaps=p_map; // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); ria->open(f2); err = ria->poll(); while(err==OK) { err=ria->poll(); } ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT); RES res = ria->get_resource(); ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT); return ResourceFormatSaverText::singleton->save(p_path,res); } if (!fw) { return OK; //nothing to rename, do nothing } uint8_t c=f->get_8(); while(!f->eof_reached()) { fw->store_8(c); c=f->get_8(); } bool all_ok = fw->get_error()==OK; memdelete(fw); if (!all_ok) { return ERR_CANT_CREATE; } DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); da->remove(p_path); da->rename(p_path+".depren",p_path); memdelete(da); #endif 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); }