From b324ff7ea584676fcc3292808d7e7ea609982f8e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 14 May 2014 01:22:15 -0300 Subject: A bit of everything: -IMA-ADPCM support for samples, this means that sound effects can be compressed and use 4 timess less RAM. -New 3D import workflow based on Wavefront OBJ. Import single objects as mesh resources instead of full scenes. Many people prefers to work this way. Just like the rest of the imported resources, these are updated in realtime if modified externally. -Mesh resources now support naming surfaces. This helps reimporting to identify which user-created materials must be kept. -Several fixes and improvements to SurfaceTool. -Anti Aliasing added to WorldEnvironment effects (using FXAA) -2D Physics bodies (RigidBody, KinematicBody, etc), Raycasts, Tilemap, etc support collision layers. This makes easy to group which objects collide against which. -2D Trigger shapes can now also trigger collision reporting in other 2D bodies (it used to be in Area2D before) -Viewport render target textures can now be filtered. -Few fixes in GDscript make it easier to work with static functions and class members. -Several and many bugfixes. --- tools/editor/editor_node.cpp | 5 + .../io_plugins/editor_mesh_import_plugin.cpp | 555 ++++++++++++ .../editor/io_plugins/editor_mesh_import_plugin.h | 29 + .../io_plugins/editor_sample_import_plugin.cpp | 178 +++- .../io_plugins/editor_sample_import_plugin.h | 1 + tools/editor/plugins/baked_light_editor_plugin.cpp | 996 +++++++++++++++++++++ tools/editor/plugins/baked_light_editor_plugin.h | 70 ++ tools/editor/plugins/sample_editor_plugin.cpp | 149 +-- .../plugins/sample_library_editor_plugin.cpp | 2 +- tools/editor/property_editor.cpp | 12 +- tools/editor/property_editor.h | 2 +- 11 files changed, 1901 insertions(+), 98 deletions(-) create mode 100644 tools/editor/io_plugins/editor_mesh_import_plugin.cpp create mode 100644 tools/editor/io_plugins/editor_mesh_import_plugin.h create mode 100644 tools/editor/plugins/baked_light_editor_plugin.cpp create mode 100644 tools/editor/plugins/baked_light_editor_plugin.h (limited to 'tools/editor') diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index fc644e76c5..9821dad872 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -85,12 +85,15 @@ #include "plugins/animation_tree_editor_plugin.h" #include "plugins/tile_set_editor_plugin.h" #include "plugins/animation_player_editor_plugin.h" +#include "plugins/baked_light_editor_plugin.h" // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" #include "tools/editor/io_plugins/editor_font_import_plugin.h" #include "tools/editor/io_plugins/editor_sample_import_plugin.h" #include "tools/editor/io_plugins/editor_translation_import_plugin.h" +#include "tools/editor/io_plugins/editor_mesh_import_plugin.h" + EditorNode *EditorNode::singleton=NULL; @@ -4013,6 +4016,7 @@ EditorNode::EditorNode() { _scene_import->add_importer(_collada_import); editor_import_export->add_import_plugin( _scene_import); editor_import_export->add_import_plugin( Ref( memnew(EditorSceneAnimationImportPlugin(this)))); + editor_import_export->add_import_plugin( Ref( memnew(EditorMeshImportPlugin(this)))); editor_import_export->add_import_plugin( Ref( memnew(EditorFontImportPlugin(this)))); editor_import_export->add_import_plugin( Ref( memnew(EditorSampleImportPlugin(this)))); editor_import_export->add_import_plugin( Ref( memnew(EditorTranslationImportPlugin(this)))); @@ -4051,6 +4055,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( Particles2DEditorPlugin(this) ) ); add_editor_plugin( memnew( Path2DEditorPlugin(this) ) ); add_editor_plugin( memnew( PathEditorPlugin(this) ) ); + add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) ); for(int i=0;i *p_list) const{ + + p_list->push_back(PropertyInfo(Variant::BOOL,"generate/tangents")); + p_list->push_back(PropertyInfo(Variant::BOOL,"generate/normals")); + //not for nowp + //p_list->push_back(PropertyInfo(Variant::BOOL,"import/materials")); + //p_list->push_back(PropertyInfo(Variant::BOOL,"import/textures")); + p_list->push_back(PropertyInfo(Variant::BOOL,"force/flip_faces")); + p_list->push_back(PropertyInfo(Variant::BOOL,"force/smooth_shading")); + p_list->push_back(PropertyInfo(Variant::BOOL,"force/weld_vertices")); + p_list->push_back(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001")); + //p_list->push_back(PropertyInfo(Variant::BOOL,"compress/enable")); + //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192")); + + + } + + + static void _bind_methods() { + + + ADD_SIGNAL( MethodInfo("changed")); + } + + + _EditorMeshImportOptions() { + + generate_tangents=true; + generate_normals=true; + flip_faces=false; + smooth_shading=false; + weld_vertices=true; + weld_tolerance=0.0001; + import_material=false; + import_textures=false; + + } + + +}; + +class EditorMeshImportDialog : public ConfirmationDialog { + + OBJ_TYPE(EditorMeshImportDialog,ConfirmationDialog); + + EditorMeshImportPlugin *plugin; + + LineEdit *import_path; + LineEdit *save_path; + FileDialog *file_select; + EditorDirDialog *save_select; + ConfirmationDialog *error_dialog; + PropertyEditor *option_editor; + + _EditorMeshImportOptions *options; + + +public: + + void _choose_files(const Vector& p_path) { + + String files; + for(int i=0;i0) + files+=","; + files+=p_path[i]; + } + /* + if (p_path.size()) { + String srctex=p_path[0]; + String ipath = EditorImportDB::get_singleton()->find_source_path(srctex); + + if (ipath!="") + save_path->set_text(ipath.get_base_dir()); + }*/ + import_path->set_text(files); + + } + void _choose_save_dir(const String& p_path) { + + save_path->set_text(p_path); + } + + void _browse() { + + file_select->popup_centered_ratio(); + } + + void _browse_target() { + + save_select->popup_centered_ratio(); + + } + + + void popup_import(const String& p_path) { + + popup_centered(Size2(400,400)); + if (p_path!="") { + + Ref rimd = ResourceLoader::load_import_metadata(p_path); + ERR_FAIL_COND(!rimd.is_valid()); + + save_path->set_text(p_path.get_base_dir()); + List opts; + rimd->get_options(&opts); + for(List::Element *E=opts.front();E;E=E->next()) { + + options->_set(E->get(),rimd->get_option(E->get())); + } + + String src = ""; + for(int i=0;iget_source_count();i++) { + if (i>0) + src+=","; + src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i)); + } + import_path->set_text(src); + } + } + + + void _import() { + + Vector meshes = import_path->get_text().split(","); + + if (meshes.size()==0) { + error_dialog->set_text("No meshes to import!"); + error_dialog->popup_centered(Size2(200,100)); + } + + for(int i=0;i imd = memnew( ResourceImportMetadata ); + + List pl; + options->_get_property_list(&pl); + for(List::Element *E=pl.front();E;E=E->next()) { + + Variant v; + String opt=E->get().name; + options->_get(opt,v); + imd->set_option(opt,v); + + } + + imd->add_source(EditorImportPlugin::validate_source_path(meshes[i])); + + String dst = save_path->get_text(); + if (dst=="") { + error_dialog->set_text("Save path is empty!"); + error_dialog->popup_centered(Size2(200,100)); + } + + dst = dst.plus_file(meshes[i].get_file().basename()+".msh"); + + Error err = plugin->import(dst,imd); + } + + hide(); + + } + + + void _notification(int p_what) { + + + if (p_what==NOTIFICATION_ENTER_SCENE) { + + option_editor->edit(options); + } + } + + static void _bind_methods() { + + + ObjectTypeDB::bind_method("_choose_files",&EditorMeshImportDialog::_choose_files); + ObjectTypeDB::bind_method("_choose_save_dir",&EditorMeshImportDialog::_choose_save_dir); + ObjectTypeDB::bind_method("_import",&EditorMeshImportDialog::_import); + ObjectTypeDB::bind_method("_browse",&EditorMeshImportDialog::_browse); + ObjectTypeDB::bind_method("_browse_target",&EditorMeshImportDialog::_browse_target); + // ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) ); + } + + EditorMeshImportDialog(EditorMeshImportPlugin *p_plugin) { + + plugin=p_plugin; + + + set_title("Single Mesh Import"); + + VBoxContainer *vbc = memnew( VBoxContainer ); + add_child(vbc); + set_child_rect(vbc); + + + HBoxContainer *hbc = memnew( HBoxContainer ); + vbc->add_margin_child("Source Mesh(es):",hbc); + + import_path = memnew( LineEdit ); + import_path->set_h_size_flags(SIZE_EXPAND_FILL); + hbc->add_child(import_path); + + Button * import_choose = memnew( Button ); + import_choose->set_text(" .. "); + hbc->add_child(import_choose); + + import_choose->connect("pressed", this,"_browse"); + + hbc = memnew( HBoxContainer ); + vbc->add_margin_child("Target Path:",hbc); + + save_path = memnew( LineEdit ); + save_path->set_h_size_flags(SIZE_EXPAND_FILL); + hbc->add_child(save_path); + + Button * save_choose = memnew( Button ); + save_choose->set_text(" .. "); + hbc->add_child(save_choose); + + save_choose->connect("pressed", this,"_browse_target"); + + file_select = memnew(FileDialog); + file_select->set_access(FileDialog::ACCESS_FILESYSTEM); + add_child(file_select); + file_select->set_mode(FileDialog::MODE_OPEN_FILES); + file_select->connect("files_selected", this,"_choose_files"); + file_select->add_filter("*.obj ; Wavefront OBJ"); + save_select = memnew( EditorDirDialog ); + add_child(save_select); + + // save_select->set_mode(FileDialog::MODE_OPEN_DIR); + save_select->connect("dir_selected", this,"_choose_save_dir"); + + get_ok()->connect("pressed", this,"_import"); + get_ok()->set_text("Import"); + + + error_dialog = memnew ( ConfirmationDialog ); + add_child(error_dialog); + error_dialog->get_ok()->set_text("Accept"); + // error_dialog->get_cancel()->hide(); + + set_hide_on_ok(false); + options = memnew( _EditorMeshImportOptions ); + + option_editor = memnew( PropertyEditor ); + option_editor->hide_top_label(); + vbc->add_margin_child("Options:",option_editor,true); + } + + ~EditorMeshImportDialog() { + memdelete(options); + } + +}; + + +String EditorMeshImportPlugin::get_name() const { + + return "mesh"; +} +String EditorMeshImportPlugin::get_visible_name() const{ + + return "3D Mesh"; +} +void EditorMeshImportPlugin::import_dialog(const String& p_from){ + + dialog->popup_import(p_from); +} +Error EditorMeshImportPlugin::import(const String& p_path, const Ref& p_from){ + + + ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER); + + Ref from=p_from; + + String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0)); + FileAccessRef f = FileAccess::open(src_path,FileAccess::READ); + ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); + + Ref mesh; + Map > name_map; + + if (FileAccess::exists(p_path)) { + mesh=ResourceLoader::load(p_path,"Mesh"); + if (mesh.is_valid()) { + for(int i=0;iget_surface_count();i++) { + + if (!mesh->surface_get_material(i).is_valid()) + continue; + String name; + if (mesh->surface_get_name(i)!="") + name=mesh->surface_get_name(i); + else + name="Surface "+itos(i+1); + + name_map[name]=mesh->surface_get_material(i); + } + + while(mesh->get_surface_count()) { + mesh->surface_remove(0); + } + } + } + + if (!mesh.is_valid()) + mesh = Ref( memnew( Mesh ) ); + + + bool generate_normals=from->get_option("generate/normals"); + bool generate_tangents=from->get_option("generate/tangents"); + bool flip_faces=from->get_option("force/flip_faces"); + bool force_smooth=from->get_option("force/smooth_shading"); + bool weld_vertices=from->get_option("force/weld_vertices"); + float weld_tolerance=from->get_option("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=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; + print_line("vtx: "+itos(vtx)+"/"+itos(vertices.size())); + 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)) + surf_tool->generate_tangents(); + + surf_tool->index(); + mesh = surf_tool->commit(mesh); + if (name=="") + name="Surface "+itos(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(); + } + } + + + from->set_source_md5(0,FileAccess::get_md5(src_path)); + from->set_editor(get_name()); + mesh->set_import_metadata(from); + + //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_path,mesh); + + return err; +} + + +EditorMeshImportPlugin::EditorMeshImportPlugin(EditorNode* p_editor) { + + dialog = memnew( EditorMeshImportDialog(this)); + p_editor->get_gui_base()->add_child(dialog); +} + diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.h b/tools/editor/io_plugins/editor_mesh_import_plugin.h new file mode 100644 index 0000000000..014954685d --- /dev/null +++ b/tools/editor/io_plugins/editor_mesh_import_plugin.h @@ -0,0 +1,29 @@ +#ifndef EDITOR_MESH_IMPORT_PLUGIN_H +#define EDITOR_MESH_IMPORT_PLUGIN_H + + +#include "tools/editor/editor_import_export.h" +#include "scene/resources/font.h" + +class EditorNode; +class EditorMeshImportDialog; + +class EditorMeshImportPlugin : public EditorImportPlugin { + + OBJ_TYPE(EditorMeshImportPlugin,EditorImportPlugin); + + EditorMeshImportDialog *dialog; + + +public: + + virtual String get_name() const; + virtual String get_visible_name() const; + virtual void import_dialog(const String& p_from=""); + virtual Error import(const String& p_path, const Ref& p_from); + + + EditorMeshImportPlugin(EditorNode* p_editor); +}; + +#endif // EDITOR_MESH_IMPORT_PLUGIN_H diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp index 55cba432e3..cd02156eef 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp @@ -41,6 +41,12 @@ class _EditorSampleImportOptions : public Object { OBJ_TYPE(_EditorSampleImportOptions,Object); public: + enum CompressMode { + COMPRESS_MODE_DISABLED, + COMPRESS_MODE_RAM, + COMPRESS_MODE_DISK + }; + enum CompressBitrate { COMPRESS_64, COMPRESS_96, @@ -57,7 +63,7 @@ public: bool edit_normalize; bool edit_loop; - bool compress_enable; + CompressMode compress_mode; CompressBitrate compress_bitrate; @@ -78,8 +84,8 @@ public: edit_normalize=p_value; else if (n=="edit/loop") edit_loop=p_value; - else if (n=="compress/enable") - compress_enable=p_value; + else if (n=="compress/mode") + compress_mode=CompressMode(int(p_value)); else if (n=="compress/bitrate") compress_bitrate=CompressBitrate(int(p_value)); else @@ -106,8 +112,8 @@ public: r_ret=edit_normalize; else if (n=="edit/loop") r_ret=edit_loop; - else if (n=="compress/enable") - r_ret=compress_enable; + else if (n=="compress/mode") + r_ret=compress_mode; else if (n=="compress/bitrate") r_ret=compress_bitrate; else @@ -125,7 +131,7 @@ public: p_list->push_back(PropertyInfo(Variant::BOOL,"edit/trim")); p_list->push_back(PropertyInfo(Variant::BOOL,"edit/normalize")); p_list->push_back(PropertyInfo(Variant::BOOL,"edit/loop")); - //p_list->push_back(PropertyInfo(Variant::BOOL,"compress/enable")); + p_list->push_back(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)")); //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192")); @@ -150,7 +156,7 @@ public: edit_normalize=true; edit_loop=false; - compress_enable=false; + compress_mode=COMPRESS_MODE_DISABLED; compress_bitrate=COMPRESS_128; } @@ -554,7 +560,11 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Refget_option("compress/mode"); bool force_mono = from->get_option("force/mono"); + if (compression==_EditorSampleImportOptions::COMPRESS_MODE_RAM) + force_mono=true; + if (force_mono && chans==2) { Vector new_data; @@ -575,19 +585,31 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref dst_data; - dst_data.resize( data.size() * (is16?2:1)); - { - DVector::Write w = dst_data.write(); + Sample::Format dst_format; - int ds=data.size(); - for(int i=0;i::Write w = dst_data.write(); + + int ds=data.size(); + for(int i=0;icreate(is16?Sample::FORMAT_PCM16:Sample::FORMAT_PCM8,chans==2?true:false,len); + target->create(dst_format,chans==2?true:false,len); target->set_data(dst_data); target->set_mix_rate(rate); target->set_loop_format(loop); @@ -621,6 +643,124 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref& p_data,DVector& 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); + DVector::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;*/ + } + +} EditorSampleImportPlugin::EditorSampleImportPlugin(EditorNode* p_editor) { diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.h b/tools/editor/io_plugins/editor_sample_import_plugin.h index a5420671e6..176dece0d5 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.h +++ b/tools/editor/io_plugins/editor_sample_import_plugin.h @@ -40,6 +40,7 @@ class EditorSampleImportPlugin : public EditorImportPlugin { OBJ_TYPE(EditorSampleImportPlugin,EditorImportPlugin); EditorSampleImportDialog *dialog; + void _compress_ima_adpcm(const Vector& p_data,DVector& dst_data); public: virtual String get_name() const; diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp new file mode 100644 index 0000000000..b1e42e3369 --- /dev/null +++ b/tools/editor/plugins/baked_light_editor_plugin.cpp @@ -0,0 +1,996 @@ +#include "baked_light_editor_plugin.h" +#include "scene/gui/box_container.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/light.h" + + +class BakedLightBaker { +public: + + enum { + + ATTENUATION_CURVE_LEN=256 + }; + + struct Octant { + bool leaf; + union { + struct { + float light_accum[3]; + float surface_area; + Octant *next_leaf; + float offset[3]; + }; + Octant* children[8]; + }; + }; + + struct Triangle { + + Vector3 vertices[3]; + Vector2 uv[3]; + }; + + + struct BVH { + + AABB aabb; + Vector3 center; + Triangle *leaf; + BVH*children[2]; + }; + + + struct BVHCmpX { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.x < p_right->center.x; + } + }; + + struct BVHCmpY { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.y < p_right->center.y; + } + }; + struct BVHCmpZ { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.z < p_right->center.z; + } + }; + + + struct DirLight { + + + Vector3 pos; + Vector3 up; + Vector3 left; + Vector3 dir; + Color diffuse; + Color specular; + float energy; + float length; + int rays_thrown; + + }; + + AABB octree_aabb; + Octant *octree; + BVH*bvh; + Vector triangles; + Transform base_inv; + Octant *leaf_list; + int octree_depth; + int cell_count; + uint32_t *ray_stack; + BVH **bvh_stack; + float cell_size; + float plot_size; //multiplied by cell size + Vector directional_lights; + int max_bounces; + + + + void _add_mesh(const Ref& p_mesh,const Ref& p_mat_override,const Transform& p_xform); + void _parse_geometry(Node* p_node); + BVH* _parse_bvh(BVH** p_children,int p_size,int p_depth,int& max_depth); + void _make_bvh(); + void _make_octree(); + void _octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth); + + void _free_octree(Octant *p_octant) { + + if (!p_octant->leaf) { + + for(int i=0;i<8;i++) { + if (p_octant->children[i]) + _free_octree(p_octant->children[i]); + } + } + + memdelete(p_octant); + } + + void _free_bvh(BVH* p_bvh) { + + if (!p_bvh->leaf) { + if (p_bvh->children[0]) + _free_bvh(p_bvh->children[0]); + if (p_bvh->children[1]) + _free_bvh(p_bvh->children[1]); + } + + memdelete(p_bvh); + + } + + void _fix_lights(); + + + void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light); + void _throw_ray(const Vector3& p_from, const Vector3& p_to,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces); + + + void throw_rays(int p_amount); + float get_normalization() const; + + + void bake(Node *p_base); + + + void clear() { + + if (octree) + _free_octree(octree); + if (bvh) + _free_bvh(bvh); + + if (ray_stack) + memdelete_arr(ray_stack); + if (bvh_stack) + memdelete_arr(bvh_stack); + + octree=NULL; + bvh=NULL; + leaf_list=NULL; + cell_count=0; + ray_stack=NULL; + bvh_stack=NULL; + } + + BakedLightBaker() { + octree_depth=8; + octree=NULL; + bvh=NULL; + leaf_list=NULL; + cell_count=0; + ray_stack=NULL; + bvh_stack=NULL; + plot_size=2; + max_bounces=3; + } + + ~BakedLightBaker() { + + clear(); + } + +}; + + +void BakedLightBaker::_add_mesh(const Ref& p_mesh,const Ref& p_mat_override,const Transform& p_xform) { + + + for(int i=0;iget_surface_count();i++) { + + if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES) + continue; + Ref mat = p_mat_override.is_valid()?p_mat_override:p_mesh->surface_get_material(i); + + int facecount=0; + + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { + + facecount=p_mesh->surface_get_array_index_len(i); + } else { + + facecount=p_mesh->surface_get_array_len(i); + } + + ERR_CONTINUE((facecount==0 || (facecount%3)!=0)); + + facecount/=3; + + int tbase=triangles.size(); + triangles.resize(facecount+tbase); + + + Array a = p_mesh->surface_get_arrays(i); + + DVector vertices = a[Mesh::ARRAY_VERTEX]; + DVector::Read vr=vertices.read(); + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { + + DVector indices = a[Mesh::ARRAY_INDEX]; + DVector::Read ir = indices.read(); + + for(int i=0;icast_to()) { + + MeshInstance *meshi=p_node->cast_to(); + Ref mesh=meshi->get_mesh(); + if (mesh.is_valid()) { + _add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform()); + } + } + + if (p_node->cast_to()) { + + DirectionalLight *dl=p_node->cast_to(); + + DirLight dirl; + dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE); + dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR); + dirl.energy=dl->get_parameter(DirectionalLight::PARAM_ENERGY); + dirl.pos=dl->get_global_transform().origin; + dirl.up=dl->get_global_transform().basis.get_axis(1).normalized(); + dirl.left=dl->get_global_transform().basis.get_axis(0).normalized(); + dirl.dir=-dl->get_global_transform().basis.get_axis(2).normalized(); + dirl.rays_thrown=0; + directional_lights.push_back(dirl); + + } + + for(int i=0;iget_child_count();i++) { + + _parse_geometry(p_node->get_child(i)); + } +} + + +void BakedLightBaker::_fix_lights() { + + + for(int i=0;iup_max) + up_max=up_d; + if (up_dleft_max) + left_max=left_d; + if (left_ddir_max) + dir_max=dir_d; + if (dir_dmax_depth) { + max_depth=p_depth; + } + + if (p_size==1) { + + return p_children[0]; + } else if (p_size==0) { + + return NULL; + } + + + AABB aabb; + aabb=p_children[0]->aabb; + for(int i=1;iaabb); + } + + int li=aabb.get_longest_axis_index(); + + switch(li) { + + case Vector3::AXIS_X: { + SortArray sort_x; + sort_x.nth_element(0,p_size,p_size/2,p_children); + //sort_x.sort(&p_bb[p_from],p_size); + } break; + case Vector3::AXIS_Y: { + SortArray sort_y; + sort_y.nth_element(0,p_size,p_size/2,p_children); + //sort_y.sort(&p_bb[p_from],p_size); + } break; + case Vector3::AXIS_Z: { + SortArray sort_z; + sort_z.nth_element(0,p_size,p_size/2,p_children); + //sort_z.sort(&p_bb[p_from],p_size); + + } break; + } + + + BVH* left = _parse_bvh(p_children,p_size/2,p_depth+1,max_depth); + BVH* right = _parse_bvh(&p_children[p_size/2],p_size-p_size/2,p_depth+1,max_depth); + + BVH *_new = memnew(BVH); + _new->aabb=aabb; + _new->center=aabb.pos+aabb.size*0.5; + _new->children[0]=left; + _new->children[1]=right; + _new->leaf=NULL; + + return _new; +} + +void BakedLightBaker::_make_bvh() { + + Vector bases; + bases.resize(triangles.size()); + int max_depth=0; + for(int i=0;ileaf=&triangles[i]; + bases[i]->aabb.pos=triangles[i].vertices[0]; + bases[i]->aabb.expand_to(triangles[i].vertices[1]); + bases[i]->aabb.expand_to(triangles[i].vertices[2]); + bases[i]->center=bases[i]->aabb.pos+bases[i]->aabb.size*0.5; + } + + bvh=_parse_bvh(bases.ptr(),bases.size(),1,max_depth); + ray_stack = memnew_arr(uint32_t,max_depth); + bvh_stack = memnew_arr(BVH*,max_depth); +} + +void BakedLightBaker::_octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth) { + + if (p_octant->leaf) { + + if (p_aabb.has_point(p_triangle->vertices[0]) && p_aabb.has_point(p_triangle->vertices[1]) &&p_aabb.has_point(p_triangle->vertices[2])) { + //face is completely enclosed, add area + p_octant->surface_area+=Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area(); + } else { + //not completely enclosed, will need to be clipped.. + Vector poly; + poly.push_back(p_triangle->vertices[0]); + poly.push_back(p_triangle->vertices[1]); + poly.push_back(p_triangle->vertices[2]); + + //clip + for(int i=0;i<3;i++) { + + //top plane + Plane p(0,0,0,0); + p.normal[i]=1.0; + p.d=p_aabb.pos[i]+p_aabb.size[i]; + poly=Geometry::clip_polygon(poly,p); + + //bottom plane + p.normal[i]=-1.0; + p.d=-p_aabb.pos[i]; + poly=Geometry::clip_polygon(poly,p); + } + //calculate area + for(int i=2;isurface_area+=Face3(poly[0],poly[i-1],poly[i]).get_area(); + } + } + + } else { + + + for(int i=0;i<8;i++) { + + AABB aabb=p_aabb; + aabb.size*=0.5; + if (i&1) + aabb.pos.x+=aabb.size.x; + if (i&2) + aabb.pos.y+=aabb.size.y; + if (i&4) + aabb.pos.z+=aabb.size.z; + + AABB fit_aabb=aabb; + //fit_aabb=fit_aabb.grow(bvh->aabb.size.x*0.0001); + + if (!Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb(fit_aabb)) + continue; + + if (!p_octant->children[i]) { + p_octant->children[i]=memnew(Octant); + if (p_depth==0) { + p_octant->children[i]->leaf=true; + p_octant->children[i]->light_accum[0]=0; + p_octant->children[i]->light_accum[1]=0; + p_octant->children[i]->light_accum[2]=0; + p_octant->children[i]->offset[0]=aabb.pos.x+aabb.size.x*0.5; + p_octant->children[i]->offset[1]=aabb.pos.y+aabb.size.y*0.5; + p_octant->children[i]->offset[2]=aabb.pos.z+aabb.size.z*0.5; + p_octant->children[i]->surface_area=0; + p_octant->children[i]->next_leaf=leaf_list; + leaf_list=p_octant->children[i]; + cell_count++; + } else { + + p_octant->children[i]->leaf=false; + for(int j=0;j<8;j++) { + p_octant->children[i]->children[j]=0; + } + } + } + + _octree_insert(aabb,p_octant->children[i],p_triangle,p_depth-1); + } + } +} + + +void BakedLightBaker::_make_octree() { + + AABB base = bvh->aabb; + float lal=base.get_longest_axis_size(); + //must be square because we want square blocks + base.size.x=lal; + base.size.y=lal; + base.size.z=lal; + base.grow_by(lal*0.001); //for precision + octree_aabb=base; + + cell_size=base.size.x; + for(int i=0;i<=octree_depth;i++) + cell_size/=2.0; + + octree = memnew( Octant ); + octree->leaf=false; + for(int i=0;i<8;i++) + octree->children[i]=NULL; + + for(int i=0;ileaf) { + + float r=cell_size*plot_size; + Vector3 center=p_aabb.pos+p_aabb.size*0.5; + float d = p_plot_pos.distance_to(center); + if (d>r) + return; //oh crap! outside radius + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + p_octant->light_accum[0]+=p_light.r*intensity; + p_octant->light_accum[1]+=p_light.g*intensity; + p_octant->light_accum[2]+=p_light.b*intensity; + + } else { + + for(int i=0;i<8;i++) { + + if (!p_octant->children[i]) + continue; + + AABB aabb=p_aabb; + aabb.size*=0.5; + if (i&1) + aabb.pos.x+=aabb.size.x; + if (i&2) + aabb.pos.y+=aabb.size.y; + if (i&4) + aabb.pos.z+=aabb.size.z; + + + if (!aabb.intersects(p_plot_aabb)) + continue; + + _plot_light(p_plot_pos,p_plot_aabb,p_octant->children[i],aabb,p_light); + + } + + } +} + + +void BakedLightBaker::_throw_ray(const Vector3& p_begin, const Vector3& p_end,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces) { + + + uint32_t* stack = ray_stack; + BVH **bstack = bvh_stack; + + enum { + TEST_AABB_BIT=0, + VISIT_LEFT_BIT=1, + VISIT_RIGHT_BIT=2, + VISIT_DONE_BIT=3, + + + }; + + Vector3 n = (p_end-p_begin).normalized(); + real_t d=1e10; + bool inters=false; + Vector3 r_normal; + Vector3 r_point; + + //for(int i=0;ivertices[0],b.leaf->vertices[1],b.leaf->vertices[2]); + + + Vector3 res; + + if (f3.intersects_segment(p_begin,p_end,&res)) { + + + float nd = n.dot(res); + if (nd0) + r_normal=-r_normal; + + //ok... + Color diffuse_at_point(0.8,0.8,0.8); + Color specular_at_point(0.8,0.8,0.8); + + AABB aabb; + aabb.pos=r_point; + aabb.pos-=Vector3(1,1,1)*cell_size*plot_size; + aabb.size=Vector3(2,2,2)*cell_size*plot_size; + + _plot_light(r_point,aabb,octree,octree_aabb,p_light); + + } + +} + + + + + + +float BakedLightBaker::get_normalization() const { + + float nrg=0; + for(int i=0;iremove_child(preview); + preview->set_mesh(Ref()); + hide(); + } + +} + + + +void BakedLightEditor::_menu_option(int p_option) { + + + switch(p_option) { + + + case MENU_OPTION_BAKE: { + + ERR_FAIL_COND(!node); + preview->set_mesh(Ref()); + baker->base_inv=node->get_global_transform().affine_inverse(); + baker->bake(node); + baker->throw_rays(100000); + float norm = baker->get_normalization(); + float max_lum=0; + + print_line("CELLS: "+itos(baker->cell_count)); + DVector colors; + DVector vertices; + colors.resize(baker->cell_count*36); + vertices.resize(baker->cell_count*36); + + + { + DVector::Write cw=colors.write(); + DVector::Write vw=vertices.write(); + BakedLightBaker::Octant *oct = baker->leaf_list; + int vert_idx=0; + + while(oct) { + + Color color; + color.r=oct->light_accum[0]/norm; + color.g=oct->light_accum[1]/norm; + color.b=oct->light_accum[2]/norm; + float lum = color.get_v(); + if (lum>max_lum) + max_lum=lum; + + for (int i=0;i<6;i++) { + + + Vector3 face_points[4]; + for (int j=0;j<4;j++) { + + float v[3]; + v[0]=1.0; + v[1]=1-2*((j>>1)&1); + v[2]=v[1]*(1-2*(j&1)); + + for (int k=0;k<3;k++) { + + if (i<3) + face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); + else + face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); + } + } + + for(int j=0;j<4;j++) { + face_points[j]*=baker->cell_size; + face_points[j]+=Vector3(oct->offset[0],oct->offset[1],oct->offset[2]); + } + +#define ADD_VTX(m_idx) \ + vw[vert_idx]=face_points[m_idx]; \ + cw[vert_idx]=color; \ + vert_idx++; + + //tri 1 + ADD_VTX(0); + ADD_VTX(1); + ADD_VTX(2); + //tri 2 + ADD_VTX(2); + ADD_VTX(3); + ADD_VTX(0); + +#undef ADD_VTX + + } + + oct=oct->next_leaf; + } + + + } + + print_line("max lum: "+rtos(max_lum)); + Array a; + a.resize(Mesh::ARRAY_MAX); + a[Mesh::ARRAY_VERTEX]=vertices; + a[Mesh::ARRAY_COLOR]=colors; + + Ref matcol = memnew( FixedMaterial ); + matcol->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true); + matcol->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); + matcol->set_flag(FixedMaterial::FLAG_UNSHADED,true); + matcol->set_flag(FixedMaterial::FLAG_DOUBLE_SIDED,true); + matcol->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1)); + Ref m = memnew( Mesh ); + m->add_surface(Mesh::PRIMITIVE_TRIANGLES,a); + m->surface_set_material(0,matcol); + preview->set_mesh(m); + + + + + + } break; + case MENU_OPTION_CLEAR: { + + + + } break; + + } +} + + +void BakedLightEditor::edit(BakedLight *p_baked_light) { + + if (node==p_baked_light) + return; + if (node) { + node->remove_child(preview); + } + + node=p_baked_light; + + if (node) + node->add_child(preview); + +} + + + +void BakedLightEditor::_bind_methods() { + + ObjectTypeDB::bind_method("_menu_option",&BakedLightEditor::_menu_option); +} + +BakedLightEditor::BakedLightEditor() { + + + options = memnew( MenuButton ); + + options->set_text("BakedLight"); + options->get_popup()->add_item("Bake..",MENU_OPTION_BAKE); + options->get_popup()->add_item("Clear",MENU_OPTION_CLEAR); + options->get_popup()->connect("item_pressed", this,"_menu_option"); + + + err_dialog = memnew( AcceptDialog ); + add_child(err_dialog); + node=NULL; + baker = memnew( BakedLightBaker ); + preview = memnew( MeshInstance ); +} + +BakedLightEditor::~BakedLightEditor() { + + memdelete(baker); +} + +void BakedLightEditorPlugin::edit(Object *p_object) { + + baked_light_editor->edit(p_object->cast_to()); +} + +bool BakedLightEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("BakedLight"); +} + +void BakedLightEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + baked_light_editor->show(); + baked_light_editor->options->show(); + } else { + + baked_light_editor->hide(); + baked_light_editor->options->show(); + baked_light_editor->edit(NULL); + if (baked_light_editor->node) { + baked_light_editor->node->remove_child(baked_light_editor->preview); + baked_light_editor->node=NULL; + } + } + +} + +BakedLightEditorPlugin::BakedLightEditorPlugin(EditorNode *p_node) { + + editor=p_node; + baked_light_editor = memnew( BakedLightEditor ); + editor->get_viewport()->add_child(baked_light_editor); + add_custom_control(CONTAINER_SPATIAL_EDITOR_MENU,baked_light_editor->options); + baked_light_editor->hide(); + baked_light_editor->options->hide(); +} + + +BakedLightEditorPlugin::~BakedLightEditorPlugin() +{ +} + + diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h new file mode 100644 index 0000000000..698d3f825f --- /dev/null +++ b/tools/editor/plugins/baked_light_editor_plugin.h @@ -0,0 +1,70 @@ +#ifndef BAKED_LIGHT_EDITOR_PLUGIN_H +#define BAKED_LIGHT_EDITOR_PLUGIN_H + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/3d/baked_light.h" +#include "scene/gui/spin_box.h" + +/** + @author Juan Linietsky +*/ + + +class BakedLightBaker; +class MeshInstance; + +class BakedLightEditor : public Control { + + OBJ_TYPE(BakedLightEditor, Control ); + + + MeshInstance *preview; + BakedLightBaker *baker; + AcceptDialog *err_dialog; + + MenuButton * options; + BakedLight *node; + + enum Menu { + + MENU_OPTION_BAKE, + MENU_OPTION_CLEAR + }; + + void _menu_option(int); + +friend class BakedLightEditorPlugin; +protected: + void _node_removed(Node *p_node); + static void _bind_methods(); +public: + + void edit(BakedLight *p_baked_light); + BakedLightEditor(); + ~BakedLightEditor(); +}; + +class BakedLightEditorPlugin : public EditorPlugin { + + OBJ_TYPE( BakedLightEditorPlugin, EditorPlugin ); + + BakedLightEditor *baked_light_editor; + EditorNode *editor; + +public: + + virtual String get_name() const { return "BakedLight"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + BakedLightEditorPlugin(EditorNode *p_node); + ~BakedLightEditorPlugin(); + +}; + +#endif // MULTIMESH_EDITOR_PLUGIN_H + + diff --git a/tools/editor/plugins/sample_editor_plugin.cpp b/tools/editor/plugins/sample_editor_plugin.cpp index f55d6640c2..e3fad58a89 100644 --- a/tools/editor/plugins/sample_editor_plugin.cpp +++ b/tools/editor/plugins/sample_editor_plugin.cpp @@ -95,93 +95,98 @@ void SampleEditor::generate_preview_texture(const Ref& p_sample,Ref=len) - to=len-1; - - if (_16) { - const int16_t*src =(const int16_t*)sdata; - - for(int j=0;jmax[j]) - max[j]=v; - if (vget_format()==Sample::FORMAT_IMA_ADPCM) { + + + } else { + for(int i=0;i=len) + to=len-1; + + if (_16) { + const int16_t*src =(const int16_t*)sdata; + + for(int j=0;jmax[j]) + max[j]=v; + if (vmax[j]) + max[j]=v; + if (vmax[j]) - max[j]=v; - if (vmin[0] && vmin[0] && vmin[half] && vmin[half] && v::Write(); diff --git a/tools/editor/plugins/sample_library_editor_plugin.cpp b/tools/editor/plugins/sample_library_editor_plugin.cpp index 86ac1671ae..84143dcd4b 100644 --- a/tools/editor/plugins/sample_library_editor_plugin.cpp +++ b/tools/editor/plugins/sample_library_editor_plugin.cpp @@ -262,7 +262,7 @@ void SampleLibraryEditor::_update_library() { ti->set_editable(2,false); ti->set_selectable(2,false); Ref s = sample_library->get_sample(E->get()); - ti->set_text(2,String()+/*itos(s->get_length())+" frames ("+String::num(s->get_length()/(float)s->get_mix_rate(),2)+" s), "+*/(s->get_format()==Sample::FORMAT_PCM16?"16 Bits, ":"8 bits, ")+(s->is_stereo()?"Stereo":"Mono")); + ti->set_text(2,String()+/*itos(s->get_length())+" frames ("+String::num(s->get_length()/(float)s->get_mix_rate(),2)+" s), "+*/(s->get_format()==Sample::FORMAT_PCM16?"16 Bits, ":(s->get_format()==Sample::FORMAT_PCM8?"8 bits, ":"IMA-ADPCM,"))+(s->is_stereo()?"Stereo":"Mono")); ti->set_cell_mode(3,TreeItem::CELL_MODE_RANGE); ti->set_range_config(3,-60,24,0.01); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 8c16207887..2087345888 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -261,12 +261,12 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty for(int i=0;i<2;i++) { Point2 ofs(4,4); - ofs.y+=16*i; + ofs.y+=22*i; for(int j=0;j<10;j++) { - CheckButton *c=checks20[i*10+j]; + Button *c=checks20[i*10+j]; Point2 o=ofs; - o.x+=j*16; + o.x+=j*22; if (j>=5) o.x+=4; c->set_pos(o); @@ -277,7 +277,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty } - set_size(checks20[19]->get_pos()+Size2(12,17)); + set_size(checks20[19]->get_pos()+Size2(20,25)); } else if (hint==PROPERTY_HINT_EXP_EASING) { @@ -1560,7 +1560,9 @@ CustomPropertyEditor::CustomPropertyEditor() { } for(int i=0;i<20;i++) { - checks20[i]=memnew( CheckButton ); + checks20[i]=memnew( Button ); + checks20[i]->set_toggle_mode(true); + checks20[i]->set_focus_mode(FOCUS_NONE); add_child(checks20[i]); checks20[i]->hide(); checks20[i]->connect("pressed",this,"_action_pressed",make_binds(i)); diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index 7ee14679c1..f13deab1ae 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -92,7 +92,7 @@ class CustomPropertyEditor : public Popup { ColorPicker *color_picker; TextEdit *text_edit; bool read_only; - CheckButton *checks20[20]; + Button *checks20[20]; Control *easing_draw; -- cgit v1.2.3