From 9ce2ab9749b07633aadd0f1745dc99274865a573 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 3 Feb 2017 00:08:50 -0300 Subject: OBJ file importing! --- tools/editor/editor_node.cpp | 10 +- tools/editor/import/resource_import_texture.cpp | 274 ---------- tools/editor/import/resource_import_texture.h | 43 -- tools/editor/import/resource_import_wav.cpp | 619 ---------------------- tools/editor/import/resource_import_wav.h | 30 -- tools/editor/import/resource_importer_obj.cpp | 231 ++++++++ tools/editor/import/resource_importer_obj.h | 28 + tools/editor/import/resource_importer_texture.cpp | 274 ++++++++++ tools/editor/import/resource_importer_texture.h | 43 ++ tools/editor/import/resource_importer_wav.cpp | 619 ++++++++++++++++++++++ tools/editor/import/resource_importer_wav.h | 30 ++ 11 files changed, 1233 insertions(+), 968 deletions(-) delete mode 100644 tools/editor/import/resource_import_texture.cpp delete mode 100644 tools/editor/import/resource_import_texture.h delete mode 100644 tools/editor/import/resource_import_wav.cpp delete mode 100644 tools/editor/import/resource_import_wav.h create mode 100644 tools/editor/import/resource_importer_obj.cpp create mode 100644 tools/editor/import/resource_importer_obj.h create mode 100644 tools/editor/import/resource_importer_texture.cpp create mode 100644 tools/editor/import/resource_importer_texture.h create mode 100644 tools/editor/import/resource_importer_wav.cpp create mode 100644 tools/editor/import/resource_importer_wav.h diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 1c57d374b2..9607ee9876 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -99,9 +99,10 @@ #include "plugins/color_ramp_editor_plugin.h" #include "plugins/collision_shape_2d_editor_plugin.h" #include "plugins/gi_probe_editor_plugin.h" -#include "import/resource_import_texture.h" +#include "import/resource_importer_texture.h" #include "import/resource_importer_csv_translation.h" -#include "import/resource_import_wav.h" +#include "import/resource_importer_wav.h" +#include "import/resource_importer_obj.h" // end #include "editor_settings.h" #include "io_plugins/editor_texture_import_plugin.h" @@ -5131,6 +5132,11 @@ EditorNode::EditorNode() { import_wav.instance(); ResourceFormatImporter::get_singleton()->add_importer(import_wav); + + Ref import_obj; + import_obj.instance(); + ResourceFormatImporter::get_singleton()->add_importer(import_obj); + } _pvrtc_register_compressors(); diff --git a/tools/editor/import/resource_import_texture.cpp b/tools/editor/import/resource_import_texture.cpp deleted file mode 100644 index 940b932e54..0000000000 --- a/tools/editor/import/resource_import_texture.cpp +++ /dev/null @@ -1,274 +0,0 @@ -#include "resource_import_texture.h" -#include "io/image_loader.h" -#include "scene/resources/texture.h" - -String ResourceImporterTexture::get_importer_name() const { - - return "texture"; -} - -String ResourceImporterTexture::get_visible_name() const{ - - return "Texture"; -} -void ResourceImporterTexture::get_recognized_extensions(List *p_extensions) const{ - - ImageLoader::get_recognized_extensions(p_extensions); -} -String ResourceImporterTexture::get_save_extension() const { - return "stex"; -} - -String ResourceImporterTexture::get_resource_type() const{ - - return "StreamTexture"; -} - -bool ResourceImporterTexture::get_option_visibility(const String& p_option,const Map& p_options) const { - - if (p_option=="compress/lossy_quality" && int(p_options["compress/mode"])!=COMPRESS_LOSSY) - return false; - - return true; -} - -int ResourceImporterTexture::get_preset_count() const { - return 4; -} -String ResourceImporterTexture::get_preset_name(int p_idx) const { - - static const char* preset_names[]={ - "2D, Detect 3D", - "2D", - "2D Pixel", - "3D" - }; - - return preset_names[p_idx]; -} - - -void ResourceImporterTexture::get_import_options(List *r_options,int p_preset) const { - - - r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Lossless,Lossy,Video RAM,Uncompressed",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),p_preset==PRESET_3D?2:0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"compress/lossy_quality",PROPERTY_HINT_RANGE,"0,1,0.01"),0.7)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"flags/repeat",PROPERTY_HINT_ENUM,"Disabled,Enabled,Mirrored"),p_preset==PRESET_3D?1:0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/filter"),p_preset==PRESET_2D_PIXEL?false:true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/mipmaps"),p_preset==PRESET_3D?true:false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/anisotropic"),false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/srgb",PROPERTY_HINT_ENUM,"Disable,Enable,Detect"),2)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/fix_alpha_border"),p_preset!=PRESET_3D?true:false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/premult_alpha"),true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"stream"),false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"size_limit",PROPERTY_HINT_RANGE,"0,4096,1"),0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"detect_3d"),p_preset==PRESET_DETECT)); - -} - - -void ResourceImporterTexture::_save_stex(const 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) { - - - 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 - - switch (p_compress_mode) { - case COMPRESS_LOSSLESS: { - - Image image = p_image; - 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;i0) { - image.shrink_x2(); - } - - PoolVector data = Image::lossless_packer(image); - int data_len = data.size(); - f->store_32(data_len); - - PoolVector::Read r= data.read(); - f->store_buffer(r.ptr(),data_len); - - } - - - } break; - case COMPRESS_LOSSY: { - Image image = p_image; - 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;i0) { - image.shrink_x2(); - } - - PoolVector data = Image::lossy_packer(image,p_lossy_quality); - int data_len = data.size(); - f->store_32(data_len); - - PoolVector::Read r = data.read(); - f->store_buffer(r.ptr(),data_len); - - } - } break; - case COMPRESS_VIDEO_RAM: { - - Image image = p_image; - image.generate_mipmaps(); - image.compress(p_vram_compression); - - format |= image.get_format(); - - f->store_32(format); - - PoolVector data=image.get_data(); - int dl = data.size(); - PoolVector::Read r = data.read(); - - f->store_buffer(r.ptr(),dl); - - } break; - case COMPRESS_UNCOMPRESSED: { - - Image image = p_image; - if (p_mipmaps) { - image.generate_mipmaps(); - } else { - image.clear_mipmaps(); - } - - format |= image.get_format(); - f->store_32(format); - - PoolVector data=image.get_data(); - int dl = data.size(); - PoolVector::Read r = data.read(); - - f->store_buffer(r.ptr(),dl); - - } break; - } - - memdelete(f); -} - -Error ResourceImporterTexture::import(const String& p_source_file, const String& p_save_path, const Map& p_options, List* r_platform_variants, List *r_gen_files) { - - int compress_mode = p_options["compress/mode"]; - float lossy= p_options["compress/lossy_quality"]; - int repeat= p_options["flags/repeat"]; - bool filter= p_options["flags/filter"]; - bool mipmaps= p_options["flags/mipmaps"]; - bool anisotropic= p_options["flags/anisotropic"]; - bool srgb= p_options["flags/srgb"]; - bool fix_alpha_border= p_options["process/fix_alpha_border"]; - bool premult_alpha= p_options["process/premult_alpha"]; - bool stream = p_options["stream"]; - int size_limit = p_options["size_limit"]; - - - Image image; - Error err = ImageLoader::load_image(p_source_file,&image); - if (err!=OK) - return err; - - - int tex_flags=0; - if (repeat>0) - tex_flags|=Texture::FLAG_REPEAT; - if (repeat==2) - tex_flags|=Texture::FLAG_MIRRORED_REPEAT; - if (filter) - tex_flags|=Texture::FLAG_FILTER; - if (mipmaps || compress_mode==COMPRESS_VIDEO_RAM) - tex_flags|=Texture::FLAG_MIPMAPS; - if (anisotropic) - tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER; - if (srgb) - tex_flags|=Texture::FLAG_CONVERT_TO_LINEAR; - - if (size_limit >0 && (image.get_width()>size_limit || image.get_height()>size_limit )) { - //limit size - if (image.get_width() >= image.get_height()) { - int new_width = size_limit; - int new_height = image.get_height() * new_width / image.get_width(); - - image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC); - } else { - - int new_height = size_limit; - int new_width = image.get_width() * new_height / image.get_height(); - - image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC); - } - } - - if (fix_alpha_border) { - image.fix_alpha_edges(); - } - - if (premult_alpha) { - image.premultiply_alpha(); - } - - - if (compress_mode==COMPRESS_VIDEO_RAM) { - //must import in all formats - //Android, GLES 2.x - _save_stex(image,p_save_path+".etc.stex",compress_mode,lossy,Image::COMPRESS_ETC,mipmaps,tex_flags,stream); - r_platform_variants->push_back("etc"); - //_save_stex(image,p_save_path+".etc2.stex",compress_mode,lossy,Image::COMPRESS_ETC2,mipmaps,tex_flags,stream); - //r_platform_variants->push_back("etc2"); - _save_stex(image,p_save_path+".s3tc.stex",compress_mode,lossy,Image::COMPRESS_S3TC,mipmaps,tex_flags,stream); - r_platform_variants->push_back("s3tc"); - - } else { - //import normally - _save_stex(image,p_save_path+".stex",compress_mode,lossy,Image::COMPRESS_16BIT /*this is ignored */,mipmaps,tex_flags,stream); - } - - return OK; -} - -ResourceImporterTexture::ResourceImporterTexture() -{ - -} diff --git a/tools/editor/import/resource_import_texture.h b/tools/editor/import/resource_import_texture.h deleted file mode 100644 index 84f7b77838..0000000000 --- a/tools/editor/import/resource_import_texture.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef RESOURCEIMPORTTEXTURE_H -#define RESOURCEIMPORTTEXTURE_H - -#include "io/resource_import.h" - -class ResourceImporterTexture : public ResourceImporter { - GDCLASS(ResourceImporterTexture,ResourceImporter) -public: - virtual String get_importer_name() const; - virtual String get_visible_name() const; - virtual void get_recognized_extensions(List *p_extensions) const; - virtual String get_save_extension() const; - virtual String get_resource_type() const; - - - enum Preset { - PRESET_DETECT, - PRESET_2D, - PRESET_2D_PIXEL, - PRESET_3D, - }; - - enum CompressMode { - COMPRESS_LOSSLESS, - COMPRESS_LOSSY, - COMPRESS_VIDEO_RAM, - COMPRESS_UNCOMPRESSED - }; - - virtual int get_preset_count() const; - virtual String get_preset_name(int p_idx) const; - - virtual void get_import_options(List *r_options,int p_preset=0) const; - virtual bool get_option_visibility(const String& p_option,const Map& p_options) const; - - void _save_stex(const 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); - - virtual Error import(const String& p_source_file,const String& p_save_path,const Map& p_options,List* r_platform_variants,List* r_gen_files=NULL); - - ResourceImporterTexture(); -}; - -#endif // RESOURCEIMPORTTEXTURE_H diff --git a/tools/editor/import/resource_import_wav.cpp b/tools/editor/import/resource_import_wav.cpp deleted file mode 100644 index c277bd3b6c..0000000000 --- a/tools/editor/import/resource_import_wav.cpp +++ /dev/null @@ -1,619 +0,0 @@ -#include "resource_import_wav.h" - -#include "scene/resources/audio_stream_sample.h" -#include "os/file_access.h" -#include "io/marshalls.h" -#include "io/resource_saver.h" - -String ResourceImporterWAV::get_importer_name() const { - - return "wav"; -} - -String ResourceImporterWAV::get_visible_name() const{ - - return "Microsoft WAV"; -} -void ResourceImporterWAV::get_recognized_extensions(List *p_extensions) const{ - - p_extensions->push_back("wav"); -} -String ResourceImporterWAV::get_save_extension() const { - return "smp"; -} - -String ResourceImporterWAV::get_resource_type() const{ - - return "AudioStreamSample"; -} - -bool ResourceImporterWAV::get_option_visibility(const String& p_option,const Map& p_options) const { - - return true; -} - -int ResourceImporterWAV::get_preset_count() const { - return 0; -} -String ResourceImporterWAV::get_preset_name(int p_idx) const { - - return String(); -} - - -void ResourceImporterWAV::get_import_options(List *r_options,int p_preset) const { - - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/8_bit"),false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/mono"),false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/max_rate"),false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"force/max_rate_hz",PROPERTY_HINT_EXP_RANGE,"11025,192000,1"),44100)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/trim"),true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/normalize"),true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/loop"),false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)"),0)); - -} - - -Error ResourceImporterWAV::import(const String& p_source_file, const String& p_save_path, const Map& p_options, List* r_platform_variants, List *r_gen_files) { - - /* STEP 1, READ WAVE FILE */ - - Error err; - FileAccess *file=FileAccess::open(p_source_file, FileAccess::READ,&err); - - ERR_FAIL_COND_V( err!=OK, ERR_CANT_OPEN ); - - /* 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( ERR_FILE_UNRECOGNIZED ); - } - - - /* 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( ERR_FILE_UNRECOGNIZED ); - } - - int format_bits=0; - int format_channels=0; - - AudioStreamSample::LoopMode loop=AudioStreamSample::LOOP_DISABLED; - bool format_found=false; - bool data_found=false; - int format_freq=0; - int loop_begin=0; - int loop_end=0; - int frames; - - Vector data; - - 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_pos(); //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; - } - - /* Dont 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; - - } - - 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)); -*/ - - int len=frames; - if (format_channels==2) - len*=2; - if (format_bits>8) - len*=2; - - - data.resize(frames*format_channels); - - for (int i=0;iget_8(); - s-=128; - int8_t *sp=(int8_t*)&s; - - data[i*format_channels+c]=float(*sp)/128.0; - - } else { - //16+ bits samples are SIGNED - // if sample is > 16 bits, just read extra bytes - - uint32_t s=0; - for (int b=0;b<(format_bits>>3);b++) { - - s|=((uint32_t)file->get_8())<<(b*8); - } - s<<=(32-format_bits); - int32_t ss=s; - - - data[i*format_channels+c]=(ss>>16)/32768.0; - } - } - - } - - - - if (file->eof_reached()) { - file->close(); - memdelete(file); - ERR_EXPLAIN("Premature end of file."); - ERR_FAIL_V(ERR_FILE_CORRUPT); - } - } - - 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()?AudioStreamSample::LOOP_PING_PONG:AudioStreamSample::LOOP_FORWARD; - loop_begin=file->get_32(); - loop_end=file->get_32(); - - } - file->seek( file_pos+chunksize ); - } - - file->close(); - memdelete(file); - - // STEP 2, APPLY CONVERSIONS - - - bool is16=format_bits!=8; - int rate=format_freq; - - print_line("Input Sample: "); - print_line("\tframes: "+itos(frames)); - print_line("\tformat_channels: "+itos(format_channels)); - print_line("\t16bits: "+itos(is16)); - print_line("\trate: "+itos(rate)); - print_line("\tloop: "+itos(loop)); - print_line("\tloop begin: "+itos(loop_begin)); - print_line("\tloop end: "+itos(loop_end)); - - - //apply frequency limit - - bool limit_rate = p_options["force/max_rate"]; - int limit_rate_hz = p_options["force/max_rate_hz"]; - if (limit_rate && rate > limit_rate_hz) { - //resampleeee!!! - int new_data_frames = frames * limit_rate_hz / rate; - Vector new_data; - new_data.resize( new_data_frames * format_channels ); - for(int c=0;cmax) - max=amp; - } - - if (max>0) { - - float mult=1.0/max; - for(int i=0;i limit) { - first=i; - found=true; - } - - if (found && amp > limit) { - last=i; - } - } - - first/=format_channels; - last/=format_channels; - - if (first new_data; - new_data.resize((last-first+1)*format_channels); - for(int i=first*format_channels;i<=last*format_channels;i++) { - new_data[i-first*format_channels]=data[i]; - } - - data=new_data; - frames=data.size()/format_channels; - } - - } - - bool make_loop = p_options["edit/loop"]; - - if (make_loop && !loop) { - - loop=AudioStreamSample::LOOP_FORWARD; - loop_begin=0; - loop_end=frames; - } - - int compression = p_options["compress/mode"]; - bool force_mono = p_options["force/mono"]; - - - if (force_mono && format_channels==2) { - - Vector new_data; - new_data.resize(data.size()/2); - for(int i=0;i dst_data; - AudioStreamSample::Format dst_format; - - if ( compression == 1) { - - dst_format=AudioStreamSample::FORMAT_IMA_ADPCM; - if (format_channels==1) { - _compress_ima_adpcm(data,dst_data); - } else { - - //byte interleave - Vector left; - Vector right; - - int tframes = data.size()/2; - left.resize(tframes); - right.resize(tframes); - - for(int i=0;i bleft; - PoolVector bright; - - _compress_ima_adpcm(left,bleft); - _compress_ima_adpcm(right,bright); - - int dl = bleft.size(); - dst_data.resize( dl *2 ); - - PoolVector::Write w=dst_data.write(); - PoolVector::Read rl=bleft.read(); - PoolVector::Read rr=bright.read(); - - for(int i=0;i::Write w = dst_data.write(); - - int ds=data.size(); - for(int i=0;i sample; - sample.instance(); - sample->set_data(dst_data); - sample->set_format(dst_format); - sample->set_mix_rate(rate); - sample->set_loop_mode(loop); - sample->set_loop_begin(loop_begin); - sample->set_loop_end(loop_end); - sample->set_stereo(format_channels==2); - - ResourceSaver::save(p_save_path+".smp",sample); - - - return OK; - -} - -void ResourceImporterWAV::_compress_ima_adpcm(const Vector& p_data,PoolVector& dst_data) { - - - /*p_sample_data->data = (void*)malloc(len); - xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/ - - 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 - }; - - - int datalen = p_data.size(); - int datamax=datalen; - if (datalen&1) - datalen++; - - dst_data.resize(datalen/2+4); - PoolVector::Write w = dst_data.write(); - - - int i,step_idx=0,prev=0; - uint8_t *out = w.ptr(); - //int16_t xm_prev=0; - const float *in=p_data.ptr(); - - - /* initial value is zero */ - *(out++) =0; - *(out++) =0; - /* Table index initial value */ - *(out++) =0; - /* unused */ - *(out++) =0; - - for (i=0;i=datamax) - xm_sample=0; - else { - - - xm_sample=CLAMP(in[i]*32767.0,-32768,32767); - /* - if (xm_sample==32767 || xm_sample==-32768) - printf("clippy!\n",xm_sample); - */ - } - - //xm_sample=xm_sample+xm_prev; - //xm_prev=xm_sample; - - diff = (int)xm_sample - prev ; - - nibble=0 ; - step = _ima_adpcm_step_table[ step_idx ]; - vpdiff = step >> 3 ; - if (diff < 0) { - nibble=8; - diff=-diff ; - } - mask = 4 ; - while (mask) { - - if (diff >= step) { - - nibble |= mask; - diff -= step; - vpdiff += step; - } - - step >>= 1 ; - mask >>= 1 ; - }; - - if (nibble&8) - prev-=vpdiff ; - else - prev+=vpdiff ; - - if (prev > 32767) { - //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev); - prev=32767; - } else if (prev < -32768) { - //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev); - prev = -32768 ; - } - - step_idx += _ima_adpcm_index_table[nibble]; - if (step_idx< 0) - step_idx= 0 ; - else if (step_idx> 88) - step_idx= 88 ; - - - if (i&1) { - *out|=nibble<<4; - out++; - } else { - *out=nibble; - } - /*dataptr[i]=prev>>8;*/ - } - - - - -} - -ResourceImporterWAV::ResourceImporterWAV() -{ - -} diff --git a/tools/editor/import/resource_import_wav.h b/tools/editor/import/resource_import_wav.h deleted file mode 100644 index 9f1bd57da7..0000000000 --- a/tools/editor/import/resource_import_wav.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef RESOURCEIMPORTWAV_H -#define RESOURCEIMPORTWAV_H - - -#include "io/resource_import.h" - -class ResourceImporterWAV : public ResourceImporter { - GDCLASS(ResourceImporterWAV,ResourceImporter) -public: - virtual String get_importer_name() const; - virtual String get_visible_name() const; - virtual void get_recognized_extensions(List *p_extensions) const; - virtual String get_save_extension() const; - virtual String get_resource_type() const; - - - virtual int get_preset_count() const; - virtual String get_preset_name(int p_idx) const; - - virtual void get_import_options(List *r_options,int p_preset=0) const; - virtual bool get_option_visibility(const String& p_option,const Map& p_options) const; - - void _compress_ima_adpcm(const Vector& p_data,PoolVector& dst_data); - - virtual Error import(const String& p_source_file,const String& p_save_path,const Map& p_options,List* r_platform_variants,List* r_gen_files=NULL); - - ResourceImporterWAV(); -}; - -#endif // RESOURCEIMPORTWAV_H diff --git a/tools/editor/import/resource_importer_obj.cpp b/tools/editor/import/resource_importer_obj.cpp new file mode 100644 index 0000000000..e6e23366f6 --- /dev/null +++ b/tools/editor/import/resource_importer_obj.cpp @@ -0,0 +1,231 @@ +#include "resource_importer_obj.h" + +#include "io/resource_saver.h" +#include "scene/resources/mesh.h" +#include "scene/resources/surface_tool.h" +#include "scene/resources/surface_tool.h" +#include "os/file_access.h" + +String ResourceImporterOBJ::get_importer_name() const { + + return "obj_mesh"; +} + +String ResourceImporterOBJ::get_visible_name() const{ + + return "OBJ As Mesh"; +} +void ResourceImporterOBJ::get_recognized_extensions(List *p_extensions) const{ + + p_extensions->push_back("obj"); +} +String ResourceImporterOBJ::get_save_extension() const { + return "msh"; +} + +String ResourceImporterOBJ::get_resource_type() const{ + + return "Mesh"; +} + +bool ResourceImporterOBJ::get_option_visibility(const String& p_option,const Map& p_options) const { + + return true; +} + +int ResourceImporterOBJ::get_preset_count() const { + return 0; +} +String ResourceImporterOBJ::get_preset_name(int p_idx) const { + + return String(); +} + + +void ResourceImporterOBJ::get_import_options(List *r_options,int p_preset) const { + + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"generate/tangents"),true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"generate/normals"),true)); + //not for nowp + //r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"import/materials"))); + //r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"import/textures"))); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/flip_faces"),false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/smooth_shading"),true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/weld_vertices"),true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001"),0.0001)); + //r_options->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192")); + +} + + + +Error ResourceImporterOBJ::import(const String& p_source_file, const String& p_save_path, const Map& p_options, List* r_platform_variants, List *r_gen_files) { + + FileAccessRef f = FileAccess::open(p_source_file,FileAccess::READ); + ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); + + Ref mesh = Ref( memnew( Mesh ) ); + Map > name_map; + + + + bool generate_normals=p_options["generate/normals"]; + bool generate_tangents=p_options["generate/tangents"]; + bool flip_faces=p_options["force/flip_faces"]; + bool force_smooth=p_options["force/smooth_shading"]; + bool weld_vertices=p_options["force/weld_vertices"]; + float weld_tolerance=p_options["force/weld_tolerance"]; + Vector vertices; + Vector normals; + Vector uvs; + String name; + + Ref surf_tool = memnew( SurfaceTool) ; + surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES); + if (force_smooth) + surf_tool->add_smooth_group(true); + int has_index_data=false; + + while(true) { + + + String l = f->get_line().strip_edges(); + + if (l.begins_with("v ")) { + //vertex + Vector v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA); + Vector3 vtx; + vtx.x=v[1].to_float(); + vtx.y=v[2].to_float(); + vtx.z=v[3].to_float(); + vertices.push_back(vtx); + } else if (l.begins_with("vt ")) { + //uv + Vector v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA); + Vector2 uv; + uv.x=v[1].to_float(); + uv.y=1.0-v[2].to_float(); + uvs.push_back(uv); + + } else if (l.begins_with("vn ")) { + //normal + Vector v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA); + Vector3 nrm; + nrm.x=v[1].to_float(); + nrm.y=v[2].to_float(); + nrm.z=v[3].to_float(); + normals.push_back(nrm); + } if (l.begins_with("f ")) { + //vertex + + has_index_data=true; + Vector v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA); + + //not very fast, could be sped up + + + Vector face[3]; + face[0] = v[1].split("/"); + face[1] = v[2].split("/"); + ERR_FAIL_COND_V(face[0].size()==0,ERR_PARSE_ERROR); + ERR_FAIL_COND_V(face[0].size()!=face[1].size(),ERR_PARSE_ERROR); + for(int i=2;iadd_normal(normals[norm]); + } + + if (face[idx].size()>=2 && face[idx][1]!=String()) { + + int uv = face[idx][1].to_int()-1; + ERR_FAIL_INDEX_V(uv,uvs.size(),ERR_PARSE_ERROR); + surf_tool->add_uv(uvs[uv]); + } + + int vtx = face[idx][0].to_int()-1; + ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR); + + Vector3 vertex = vertices[vtx]; + if (weld_vertices) + vertex=vertex.snapped(weld_tolerance); + surf_tool->add_vertex(vertex); + } + + face[1]=face[2]; + } + } else if (l.begins_with("s ") && !force_smooth) { //smoothing + String what = l.substr(2,l.length()).strip_edges(); + if (what=="off") + surf_tool->add_smooth_group(false); + else + surf_tool->add_smooth_group(true); + + } else if (l.begins_with("o ") || f->eof_reached()) { //new surface or done + + if (has_index_data) { + //new object/surface + if (generate_normals || force_smooth) + surf_tool->generate_normals(); + if (uvs.size() && (normals.size() || generate_normals) && generate_tangents) + surf_tool->generate_tangents(); + + surf_tool->index(); + mesh = surf_tool->commit(mesh); + if (name=="") + name=vformat(TTR("Surface %d"),mesh->get_surface_count()-1); + mesh->surface_set_name(mesh->get_surface_count()-1,name); + name=""; + surf_tool->clear(); + surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES); + if (force_smooth) + surf_tool->add_smooth_group(true); + + has_index_data=false; + + if (f->eof_reached()) + break; + } + + if (l.begins_with("o ")) //name + name=l.substr(2,l.length()).strip_edges(); + } + } + +/* + TODO, check existing materials and merge? + //re-apply materials if exist + for(int i=0;iget_surface_count();i++) { + + String n = mesh->surface_get_name(i); + if (name_map.has(n)) + mesh->surface_set_material(i,name_map[n]); + } +*/ + + Error err = ResourceSaver::save(p_save_path+".msh",mesh); + + return err; + +} + +ResourceImporterOBJ::ResourceImporterOBJ() +{ + +} diff --git a/tools/editor/import/resource_importer_obj.h b/tools/editor/import/resource_importer_obj.h new file mode 100644 index 0000000000..d2a3c4fddd --- /dev/null +++ b/tools/editor/import/resource_importer_obj.h @@ -0,0 +1,28 @@ +#ifndef RESOURCEIMPORTEROBJ_H +#define RESOURCEIMPORTEROBJ_H + + +#include "io/resource_import.h" + +class ResourceImporterOBJ : public ResourceImporter { + GDCLASS(ResourceImporterOBJ,ResourceImporter) +public: + virtual String get_importer_name() const; + virtual String get_visible_name() const; + virtual void get_recognized_extensions(List *p_extensions) const; + virtual String get_save_extension() const; + virtual String get_resource_type() const; + + virtual int get_preset_count() const; + virtual String get_preset_name(int p_idx) const; + + virtual void get_import_options(List *r_options,int p_preset=0) const; + virtual bool get_option_visibility(const String& p_option,const Map& p_options) const; + + virtual Error import(const String& p_source_file,const String& p_save_path,const Map& p_options,List* r_platform_variants,List* r_gen_files=NULL); + + ResourceImporterOBJ(); +}; + + +#endif // RESOURCEIMPORTEROBJ_H diff --git a/tools/editor/import/resource_importer_texture.cpp b/tools/editor/import/resource_importer_texture.cpp new file mode 100644 index 0000000000..3cbe034e4d --- /dev/null +++ b/tools/editor/import/resource_importer_texture.cpp @@ -0,0 +1,274 @@ +#include "resource_importer_texture.h" +#include "io/image_loader.h" +#include "scene/resources/texture.h" + +String ResourceImporterTexture::get_importer_name() const { + + return "texture"; +} + +String ResourceImporterTexture::get_visible_name() const{ + + return "Texture"; +} +void ResourceImporterTexture::get_recognized_extensions(List *p_extensions) const{ + + ImageLoader::get_recognized_extensions(p_extensions); +} +String ResourceImporterTexture::get_save_extension() const { + return "stex"; +} + +String ResourceImporterTexture::get_resource_type() const{ + + return "StreamTexture"; +} + +bool ResourceImporterTexture::get_option_visibility(const String& p_option,const Map& p_options) const { + + if (p_option=="compress/lossy_quality" && int(p_options["compress/mode"])!=COMPRESS_LOSSY) + return false; + + return true; +} + +int ResourceImporterTexture::get_preset_count() const { + return 4; +} +String ResourceImporterTexture::get_preset_name(int p_idx) const { + + static const char* preset_names[]={ + "2D, Detect 3D", + "2D", + "2D Pixel", + "3D" + }; + + return preset_names[p_idx]; +} + + +void ResourceImporterTexture::get_import_options(List *r_options,int p_preset) const { + + + r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Lossless,Lossy,Video RAM,Uncompressed",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),p_preset==PRESET_3D?2:0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"compress/lossy_quality",PROPERTY_HINT_RANGE,"0,1,0.01"),0.7)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"flags/repeat",PROPERTY_HINT_ENUM,"Disabled,Enabled,Mirrored"),p_preset==PRESET_3D?1:0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/filter"),p_preset==PRESET_2D_PIXEL?false:true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/mipmaps"),p_preset==PRESET_3D?true:false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/anisotropic"),false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/srgb",PROPERTY_HINT_ENUM,"Disable,Enable,Detect"),2)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/fix_alpha_border"),p_preset!=PRESET_3D?true:false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/premult_alpha"),true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"stream"),false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"size_limit",PROPERTY_HINT_RANGE,"0,4096,1"),0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"detect_3d"),p_preset==PRESET_DETECT)); + +} + + +void ResourceImporterTexture::_save_stex(const 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) { + + + 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 + + switch (p_compress_mode) { + case COMPRESS_LOSSLESS: { + + Image image = p_image; + 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;i0) { + image.shrink_x2(); + } + + PoolVector data = Image::lossless_packer(image); + int data_len = data.size(); + f->store_32(data_len); + + PoolVector::Read r= data.read(); + f->store_buffer(r.ptr(),data_len); + + } + + + } break; + case COMPRESS_LOSSY: { + Image image = p_image; + 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;i0) { + image.shrink_x2(); + } + + PoolVector data = Image::lossy_packer(image,p_lossy_quality); + int data_len = data.size(); + f->store_32(data_len); + + PoolVector::Read r = data.read(); + f->store_buffer(r.ptr(),data_len); + + } + } break; + case COMPRESS_VIDEO_RAM: { + + Image image = p_image; + image.generate_mipmaps(); + image.compress(p_vram_compression); + + format |= image.get_format(); + + f->store_32(format); + + PoolVector data=image.get_data(); + int dl = data.size(); + PoolVector::Read r = data.read(); + + f->store_buffer(r.ptr(),dl); + + } break; + case COMPRESS_UNCOMPRESSED: { + + Image image = p_image; + if (p_mipmaps) { + image.generate_mipmaps(); + } else { + image.clear_mipmaps(); + } + + format |= image.get_format(); + f->store_32(format); + + PoolVector data=image.get_data(); + int dl = data.size(); + PoolVector::Read r = data.read(); + + f->store_buffer(r.ptr(),dl); + + } break; + } + + memdelete(f); +} + +Error ResourceImporterTexture::import(const String& p_source_file, const String& p_save_path, const Map& p_options, List* r_platform_variants, List *r_gen_files) { + + int compress_mode = p_options["compress/mode"]; + float lossy= p_options["compress/lossy_quality"]; + int repeat= p_options["flags/repeat"]; + bool filter= p_options["flags/filter"]; + bool mipmaps= p_options["flags/mipmaps"]; + bool anisotropic= p_options["flags/anisotropic"]; + bool srgb= p_options["flags/srgb"]; + bool fix_alpha_border= p_options["process/fix_alpha_border"]; + bool premult_alpha= p_options["process/premult_alpha"]; + bool stream = p_options["stream"]; + int size_limit = p_options["size_limit"]; + + + Image image; + Error err = ImageLoader::load_image(p_source_file,&image); + if (err!=OK) + return err; + + + int tex_flags=0; + if (repeat>0) + tex_flags|=Texture::FLAG_REPEAT; + if (repeat==2) + tex_flags|=Texture::FLAG_MIRRORED_REPEAT; + if (filter) + tex_flags|=Texture::FLAG_FILTER; + if (mipmaps || compress_mode==COMPRESS_VIDEO_RAM) + tex_flags|=Texture::FLAG_MIPMAPS; + if (anisotropic) + tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER; + if (srgb) + tex_flags|=Texture::FLAG_CONVERT_TO_LINEAR; + + if (size_limit >0 && (image.get_width()>size_limit || image.get_height()>size_limit )) { + //limit size + if (image.get_width() >= image.get_height()) { + int new_width = size_limit; + int new_height = image.get_height() * new_width / image.get_width(); + + image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC); + } else { + + int new_height = size_limit; + int new_width = image.get_width() * new_height / image.get_height(); + + image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC); + } + } + + if (fix_alpha_border) { + image.fix_alpha_edges(); + } + + if (premult_alpha) { + image.premultiply_alpha(); + } + + + if (compress_mode==COMPRESS_VIDEO_RAM) { + //must import in all formats + //Android, GLES 2.x + _save_stex(image,p_save_path+".etc.stex",compress_mode,lossy,Image::COMPRESS_ETC,mipmaps,tex_flags,stream); + r_platform_variants->push_back("etc"); + //_save_stex(image,p_save_path+".etc2.stex",compress_mode,lossy,Image::COMPRESS_ETC2,mipmaps,tex_flags,stream); + //r_platform_variants->push_back("etc2"); + _save_stex(image,p_save_path+".s3tc.stex",compress_mode,lossy,Image::COMPRESS_S3TC,mipmaps,tex_flags,stream); + r_platform_variants->push_back("s3tc"); + + } else { + //import normally + _save_stex(image,p_save_path+".stex",compress_mode,lossy,Image::COMPRESS_16BIT /*this is ignored */,mipmaps,tex_flags,stream); + } + + return OK; +} + +ResourceImporterTexture::ResourceImporterTexture() +{ + +} diff --git a/tools/editor/import/resource_importer_texture.h b/tools/editor/import/resource_importer_texture.h new file mode 100644 index 0000000000..84f7b77838 --- /dev/null +++ b/tools/editor/import/resource_importer_texture.h @@ -0,0 +1,43 @@ +#ifndef RESOURCEIMPORTTEXTURE_H +#define RESOURCEIMPORTTEXTURE_H + +#include "io/resource_import.h" + +class ResourceImporterTexture : public ResourceImporter { + GDCLASS(ResourceImporterTexture,ResourceImporter) +public: + virtual String get_importer_name() const; + virtual String get_visible_name() const; + virtual void get_recognized_extensions(List *p_extensions) const; + virtual String get_save_extension() const; + virtual String get_resource_type() const; + + + enum Preset { + PRESET_DETECT, + PRESET_2D, + PRESET_2D_PIXEL, + PRESET_3D, + }; + + enum CompressMode { + COMPRESS_LOSSLESS, + COMPRESS_LOSSY, + COMPRESS_VIDEO_RAM, + COMPRESS_UNCOMPRESSED + }; + + virtual int get_preset_count() const; + virtual String get_preset_name(int p_idx) const; + + virtual void get_import_options(List *r_options,int p_preset=0) const; + virtual bool get_option_visibility(const String& p_option,const Map& p_options) const; + + void _save_stex(const 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); + + virtual Error import(const String& p_source_file,const String& p_save_path,const Map& p_options,List* r_platform_variants,List* r_gen_files=NULL); + + ResourceImporterTexture(); +}; + +#endif // RESOURCEIMPORTTEXTURE_H diff --git a/tools/editor/import/resource_importer_wav.cpp b/tools/editor/import/resource_importer_wav.cpp new file mode 100644 index 0000000000..ee53b740ca --- /dev/null +++ b/tools/editor/import/resource_importer_wav.cpp @@ -0,0 +1,619 @@ +#include "resource_importer_wav.h" + +#include "scene/resources/audio_stream_sample.h" +#include "os/file_access.h" +#include "io/marshalls.h" +#include "io/resource_saver.h" + +String ResourceImporterWAV::get_importer_name() const { + + return "wav"; +} + +String ResourceImporterWAV::get_visible_name() const{ + + return "Microsoft WAV"; +} +void ResourceImporterWAV::get_recognized_extensions(List *p_extensions) const{ + + p_extensions->push_back("wav"); +} +String ResourceImporterWAV::get_save_extension() const { + return "smp"; +} + +String ResourceImporterWAV::get_resource_type() const{ + + return "AudioStreamSample"; +} + +bool ResourceImporterWAV::get_option_visibility(const String& p_option,const Map& p_options) const { + + return true; +} + +int ResourceImporterWAV::get_preset_count() const { + return 0; +} +String ResourceImporterWAV::get_preset_name(int p_idx) const { + + return String(); +} + + +void ResourceImporterWAV::get_import_options(List *r_options,int p_preset) const { + + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/8_bit"),false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/mono"),false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/max_rate"),false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"force/max_rate_hz",PROPERTY_HINT_EXP_RANGE,"11025,192000,1"),44100)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/trim"),true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/normalize"),true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/loop"),false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)"),0)); + +} + + +Error ResourceImporterWAV::import(const String& p_source_file, const String& p_save_path, const Map& p_options, List* r_platform_variants, List *r_gen_files) { + + /* STEP 1, READ WAVE FILE */ + + Error err; + FileAccess *file=FileAccess::open(p_source_file, FileAccess::READ,&err); + + ERR_FAIL_COND_V( err!=OK, ERR_CANT_OPEN ); + + /* 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( ERR_FILE_UNRECOGNIZED ); + } + + + /* 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( ERR_FILE_UNRECOGNIZED ); + } + + int format_bits=0; + int format_channels=0; + + AudioStreamSample::LoopMode loop=AudioStreamSample::LOOP_DISABLED; + bool format_found=false; + bool data_found=false; + int format_freq=0; + int loop_begin=0; + int loop_end=0; + int frames; + + Vector data; + + 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_pos(); //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; + } + + /* Dont 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; + + } + + 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)); +*/ + + int len=frames; + if (format_channels==2) + len*=2; + if (format_bits>8) + len*=2; + + + data.resize(frames*format_channels); + + for (int i=0;iget_8(); + s-=128; + int8_t *sp=(int8_t*)&s; + + data[i*format_channels+c]=float(*sp)/128.0; + + } else { + //16+ bits samples are SIGNED + // if sample is > 16 bits, just read extra bytes + + uint32_t s=0; + for (int b=0;b<(format_bits>>3);b++) { + + s|=((uint32_t)file->get_8())<<(b*8); + } + s<<=(32-format_bits); + int32_t ss=s; + + + data[i*format_channels+c]=(ss>>16)/32768.0; + } + } + + } + + + + if (file->eof_reached()) { + file->close(); + memdelete(file); + ERR_EXPLAIN("Premature end of file."); + ERR_FAIL_V(ERR_FILE_CORRUPT); + } + } + + 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()?AudioStreamSample::LOOP_PING_PONG:AudioStreamSample::LOOP_FORWARD; + loop_begin=file->get_32(); + loop_end=file->get_32(); + + } + file->seek( file_pos+chunksize ); + } + + file->close(); + memdelete(file); + + // STEP 2, APPLY CONVERSIONS + + + bool is16=format_bits!=8; + int rate=format_freq; + + print_line("Input Sample: "); + print_line("\tframes: "+itos(frames)); + print_line("\tformat_channels: "+itos(format_channels)); + print_line("\t16bits: "+itos(is16)); + print_line("\trate: "+itos(rate)); + print_line("\tloop: "+itos(loop)); + print_line("\tloop begin: "+itos(loop_begin)); + print_line("\tloop end: "+itos(loop_end)); + + + //apply frequency limit + + bool limit_rate = p_options["force/max_rate"]; + int limit_rate_hz = p_options["force/max_rate_hz"]; + if (limit_rate && rate > limit_rate_hz) { + //resampleeee!!! + int new_data_frames = frames * limit_rate_hz / rate; + Vector new_data; + new_data.resize( new_data_frames * format_channels ); + for(int c=0;cmax) + max=amp; + } + + if (max>0) { + + float mult=1.0/max; + for(int i=0;i limit) { + first=i; + found=true; + } + + if (found && amp > limit) { + last=i; + } + } + + first/=format_channels; + last/=format_channels; + + if (first new_data; + new_data.resize((last-first+1)*format_channels); + for(int i=first*format_channels;i<=last*format_channels;i++) { + new_data[i-first*format_channels]=data[i]; + } + + data=new_data; + frames=data.size()/format_channels; + } + + } + + bool make_loop = p_options["edit/loop"]; + + if (make_loop && !loop) { + + loop=AudioStreamSample::LOOP_FORWARD; + loop_begin=0; + loop_end=frames; + } + + int compression = p_options["compress/mode"]; + bool force_mono = p_options["force/mono"]; + + + if (force_mono && format_channels==2) { + + Vector new_data; + new_data.resize(data.size()/2); + for(int i=0;i dst_data; + AudioStreamSample::Format dst_format; + + if ( compression == 1) { + + dst_format=AudioStreamSample::FORMAT_IMA_ADPCM; + if (format_channels==1) { + _compress_ima_adpcm(data,dst_data); + } else { + + //byte interleave + Vector left; + Vector right; + + int tframes = data.size()/2; + left.resize(tframes); + right.resize(tframes); + + for(int i=0;i bleft; + PoolVector bright; + + _compress_ima_adpcm(left,bleft); + _compress_ima_adpcm(right,bright); + + int dl = bleft.size(); + dst_data.resize( dl *2 ); + + PoolVector::Write w=dst_data.write(); + PoolVector::Read rl=bleft.read(); + PoolVector::Read rr=bright.read(); + + for(int i=0;i::Write w = dst_data.write(); + + int ds=data.size(); + for(int i=0;i sample; + sample.instance(); + sample->set_data(dst_data); + sample->set_format(dst_format); + sample->set_mix_rate(rate); + sample->set_loop_mode(loop); + sample->set_loop_begin(loop_begin); + sample->set_loop_end(loop_end); + sample->set_stereo(format_channels==2); + + ResourceSaver::save(p_save_path+".smp",sample); + + + return OK; + +} + +void ResourceImporterWAV::_compress_ima_adpcm(const Vector& p_data,PoolVector& dst_data) { + + + /*p_sample_data->data = (void*)malloc(len); + xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/ + + 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 + }; + + + int datalen = p_data.size(); + int datamax=datalen; + if (datalen&1) + datalen++; + + dst_data.resize(datalen/2+4); + PoolVector::Write w = dst_data.write(); + + + int i,step_idx=0,prev=0; + uint8_t *out = w.ptr(); + //int16_t xm_prev=0; + const float *in=p_data.ptr(); + + + /* initial value is zero */ + *(out++) =0; + *(out++) =0; + /* Table index initial value */ + *(out++) =0; + /* unused */ + *(out++) =0; + + for (i=0;i=datamax) + xm_sample=0; + else { + + + xm_sample=CLAMP(in[i]*32767.0,-32768,32767); + /* + if (xm_sample==32767 || xm_sample==-32768) + printf("clippy!\n",xm_sample); + */ + } + + //xm_sample=xm_sample+xm_prev; + //xm_prev=xm_sample; + + diff = (int)xm_sample - prev ; + + nibble=0 ; + step = _ima_adpcm_step_table[ step_idx ]; + vpdiff = step >> 3 ; + if (diff < 0) { + nibble=8; + diff=-diff ; + } + mask = 4 ; + while (mask) { + + if (diff >= step) { + + nibble |= mask; + diff -= step; + vpdiff += step; + } + + step >>= 1 ; + mask >>= 1 ; + }; + + if (nibble&8) + prev-=vpdiff ; + else + prev+=vpdiff ; + + if (prev > 32767) { + //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev); + prev=32767; + } else if (prev < -32768) { + //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev); + prev = -32768 ; + } + + step_idx += _ima_adpcm_index_table[nibble]; + if (step_idx< 0) + step_idx= 0 ; + else if (step_idx> 88) + step_idx= 88 ; + + + if (i&1) { + *out|=nibble<<4; + out++; + } else { + *out=nibble; + } + /*dataptr[i]=prev>>8;*/ + } + + + + +} + +ResourceImporterWAV::ResourceImporterWAV() +{ + +} diff --git a/tools/editor/import/resource_importer_wav.h b/tools/editor/import/resource_importer_wav.h new file mode 100644 index 0000000000..9f1bd57da7 --- /dev/null +++ b/tools/editor/import/resource_importer_wav.h @@ -0,0 +1,30 @@ +#ifndef RESOURCEIMPORTWAV_H +#define RESOURCEIMPORTWAV_H + + +#include "io/resource_import.h" + +class ResourceImporterWAV : public ResourceImporter { + GDCLASS(ResourceImporterWAV,ResourceImporter) +public: + virtual String get_importer_name() const; + virtual String get_visible_name() const; + virtual void get_recognized_extensions(List *p_extensions) const; + virtual String get_save_extension() const; + virtual String get_resource_type() const; + + + virtual int get_preset_count() const; + virtual String get_preset_name(int p_idx) const; + + virtual void get_import_options(List *r_options,int p_preset=0) const; + virtual bool get_option_visibility(const String& p_option,const Map& p_options) const; + + void _compress_ima_adpcm(const Vector& p_data,PoolVector& dst_data); + + virtual Error import(const String& p_source_file,const String& p_save_path,const Map& p_options,List* r_platform_variants,List* r_gen_files=NULL); + + ResourceImporterWAV(); +}; + +#endif // RESOURCEIMPORTWAV_H -- cgit v1.2.3