summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/editor/editor_node.cpp5
-rw-r--r--tools/editor/io_plugins/editor_mesh_import_plugin.cpp555
-rw-r--r--tools/editor/io_plugins/editor_mesh_import_plugin.h29
-rw-r--r--tools/editor/io_plugins/editor_sample_import_plugin.cpp178
-rw-r--r--tools/editor/io_plugins/editor_sample_import_plugin.h1
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.cpp996
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.h70
-rw-r--r--tools/editor/plugins/sample_editor_plugin.cpp149
-rw-r--r--tools/editor/plugins/sample_library_editor_plugin.cpp2
-rw-r--r--tools/editor/property_editor.cpp12
-rw-r--r--tools/editor/property_editor.h2
11 files changed, 1901 insertions, 98 deletions
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<EditorSceneAnimationImportPlugin>( memnew(EditorSceneAnimationImportPlugin(this))));
+ editor_import_export->add_import_plugin( Ref<EditorMeshImportPlugin>( memnew(EditorMeshImportPlugin(this))));
editor_import_export->add_import_plugin( Ref<EditorFontImportPlugin>( memnew(EditorFontImportPlugin(this))));
editor_import_export->add_import_plugin( Ref<EditorSampleImportPlugin>( memnew(EditorSampleImportPlugin(this))));
editor_import_export->add_import_plugin( Ref<EditorTranslationImportPlugin>( 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<EditorPlugins::get_plugin_count();i++)
add_editor_plugin( EditorPlugins::create(i,this) );
diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp
new file mode 100644
index 0000000000..d76a778433
--- /dev/null
+++ b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp
@@ -0,0 +1,555 @@
+#include "editor_mesh_import_plugin.h"
+
+#include "scene/gui/file_dialog.h"
+#include "tools/editor/editor_dir_dialog.h"
+#include "tools/editor/editor_node.h"
+#include "tools/editor/property_editor.h"
+#include "scene/resources/sample.h"
+#include "io/resource_saver.h"
+#include "os/file_access.h"
+#include "io/marshalls.h"
+#include "scene/resources/surface_tool.h"
+
+class _EditorMeshImportOptions : public Object {
+
+ OBJ_TYPE(_EditorMeshImportOptions,Object);
+public:
+
+
+ bool generate_tangents;
+ bool generate_normals;
+ bool flip_faces;
+ bool smooth_shading;
+ bool weld_vertices;
+ bool import_material;
+ bool import_textures;
+ float weld_tolerance;
+
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ String n = p_name;
+ if (n=="generate/tangents")
+ generate_tangents=p_value;
+ else if (n=="generate/normals")
+ generate_normals=p_value;
+ else if (n=="import/materials")
+ import_material=p_value;
+ else if (n=="import/textures")
+ import_textures=p_value;
+ else if (n=="force/flip_faces")
+ flip_faces=p_value;
+ else if (n=="force/smooth_shading")
+ smooth_shading=p_value;
+ else if (n=="force/weld_vertices")
+ weld_vertices=p_value;
+ else if (n=="force/weld_tolerance")
+ weld_tolerance=p_value;
+ else
+ return false;
+
+ return true;
+
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const{
+
+ String n = p_name;
+ if (n=="generate/tangents")
+ r_ret=generate_tangents;
+ else if (n=="generate/normals")
+ r_ret=generate_normals;
+ else if (n=="import/materials")
+ r_ret=import_material;
+ else if (n=="import/textures")
+ r_ret=import_textures;
+ else if (n=="force/flip_faces")
+ r_ret=flip_faces;
+ else if (n=="force/smooth_shading")
+ r_ret=smooth_shading;
+ else if (n=="force/weld_vertices")
+ r_ret=weld_vertices;
+ else if (n=="force/weld_tolerance")
+ r_ret=weld_tolerance;
+ else
+ return false;
+
+ return true;
+
+ }
+ void _get_property_list( List<PropertyInfo> *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<String>& p_path) {
+
+ String files;
+ for(int i=0;i<p_path.size();i++) {
+
+ if (i>0)
+ 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<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
+ ERR_FAIL_COND(!rimd.is_valid());
+
+ save_path->set_text(p_path.get_base_dir());
+ List<String> opts;
+ rimd->get_options(&opts);
+ for(List<String>::Element *E=opts.front();E;E=E->next()) {
+
+ options->_set(E->get(),rimd->get_option(E->get()));
+ }
+
+ String src = "";
+ for(int i=0;i<rimd->get_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<String> 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<meshes.size();i++) {
+
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+
+ List<PropertyInfo> pl;
+ options->_get_property_list(&pl);
+ for(List<PropertyInfo>::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<ResourceImportMetadata>& p_from){
+
+
+ ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER);
+
+ Ref<ResourceImportMetadata> 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> mesh;
+ Map<String,Ref<Material> > name_map;
+
+ if (FileAccess::exists(p_path)) {
+ mesh=ResourceLoader::load(p_path,"Mesh");
+ if (mesh.is_valid()) {
+ for(int i=0;i<mesh->get_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<Mesh>( 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<Vector3> vertices;
+ Vector<Vector3> normals;
+ Vector<Vector2> uvs;
+ String name;
+
+ Ref<SurfaceTool> 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<String> 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<String> 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<String> 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<String> v = l.split(" ",false);
+ ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+
+ //not very fast, could be sped up
+
+
+ Vector<String> 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;i<v.size()-1;i++) {
+
+ face[2] = v[i+1].split("/");
+ ERR_FAIL_COND_V(face[0].size()!=face[2].size(),ERR_PARSE_ERROR);
+ for(int j=0;j<3;j++) {
+
+ int idx=j;
+
+ if (!flip_faces && idx<2) {
+ idx=1^idx;
+ }
+
+
+ if (face[idx].size()==3) {
+ int norm = face[idx][2].to_int()-1;
+ ERR_FAIL_INDEX_V(norm,normals.size(),ERR_PARSE_ERROR);
+ surf_tool->add_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;i<mesh->get_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<ResourceImportMetadata>& 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 Ref<ResourceI
loop_end=len;
}
+ int compression = from->get_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<float> new_data;
@@ -575,19 +585,31 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI
DVector<uint8_t> dst_data;
- dst_data.resize( data.size() * (is16?2:1));
- {
- DVector<uint8_t>::Write w = dst_data.write();
+ Sample::Format dst_format;
- int ds=data.size();
- for(int i=0;i<ds;i++) {
+ if ( compression == _EditorSampleImportOptions::COMPRESS_MODE_RAM) {
- if (is16) {
- int16_t v = CLAMP(data[i]*32767,-32768,32767);
- encode_uint16(v,&w[i*2]);
- } else {
- int8_t v = CLAMP(data[i]*127,-128,127);
- w[i]=v;
+ dst_format=Sample::FORMAT_IMA_ADPCM;
+
+ _compress_ima_adpcm(data,dst_data);
+
+ } else {
+
+ dst_format=is16?Sample::FORMAT_PCM16:Sample::FORMAT_PCM8;
+ dst_data.resize( data.size() * (is16?2:1));
+ {
+ DVector<uint8_t>::Write w = dst_data.write();
+
+ int ds=data.size();
+ for(int i=0;i<ds;i++) {
+
+ if (is16) {
+ int16_t v = CLAMP(data[i]*32767,-32768,32767);
+ encode_uint16(v,&w[i*2]);
+ } else {
+ int8_t v = CLAMP(data[i]*127,-128,127);
+ w[i]=v;
+ }
}
}
}
@@ -603,7 +625,7 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI
target = smp;
}
- target->create(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<ResourceI
}
+void EditorSampleImportPlugin::_compress_ima_adpcm(const Vector<float>& p_data,DVector<uint8_t>& 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<uint8_t>::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<datalen;i++) {
+ int step,diff,vpdiff,signed_nibble,p,mask;
+ uint8_t nibble;
+ int16_t xm_sample;
+
+ if (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<float>& p_data,DVector<uint8_t>& 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<Triangle> 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<DirLight> directional_lights;
+ int max_bounces;
+
+
+
+ void _add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& 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<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform) {
+
+
+ for(int i=0;i<p_mesh->get_surface_count();i++) {
+
+ if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES)
+ continue;
+ Ref<Material> 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<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
+ DVector<Vector3>::Read vr=vertices.read();
+
+ if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) {
+
+ DVector<int> indices = a[Mesh::ARRAY_INDEX];
+ DVector<int>::Read ir = indices.read();
+
+ for(int i=0;i<facecount;i++) {
+ Triangle &t=triangles[tbase+i];
+ t.vertices[0]=p_xform.xform(vr[ ir[i*3+0] ]);
+ t.vertices[1]=p_xform.xform(vr[ ir[i*3+1] ]);
+ t.vertices[2]=p_xform.xform(vr[ ir[i*3+2] ]);
+ }
+
+ } else {
+
+ for(int i=0;i<facecount;i++) {
+ Triangle &t=triangles[tbase+i];
+ t.vertices[0]=p_xform.xform(vr[ i*3+0 ]);
+ t.vertices[1]=p_xform.xform(vr[ i*3+1 ]);
+ t.vertices[2]=p_xform.xform(vr[ i*3+2 ]);
+ }
+ }
+ }
+
+}
+
+
+void BakedLightBaker::_parse_geometry(Node* p_node) {
+
+ if (p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *meshi=p_node->cast_to<MeshInstance>();
+ Ref<Mesh> 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>()) {
+
+ DirectionalLight *dl=p_node->cast_to<DirectionalLight>();
+
+ 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;i<p_node->get_child_count();i++) {
+
+ _parse_geometry(p_node->get_child(i));
+ }
+}
+
+
+void BakedLightBaker::_fix_lights() {
+
+
+ for(int i=0;i<directional_lights.size();i++) {
+
+ DirLight &dl=directional_lights[i];
+ float up_max=-1e10;
+ float dir_max=-1e10;
+ float left_max=-1e10;
+ float up_min=1e10;
+ float dir_min=1e10;
+ float left_min=1e10;
+
+ for(int j=0;j<triangles.size();j++) {
+
+ for(int k=0;k<3;k++) {
+
+ Vector3 v = triangles[j].vertices[j];
+
+ float up_d = dl.up.dot(v);
+ float dir_d = dl.dir.dot(v);
+ float left_d = dl.left.dot(v);
+
+ if (up_d>up_max)
+ up_max=up_d;
+ if (up_d<up_min)
+ up_min=up_d;
+
+ if (left_d>left_max)
+ left_max=left_d;
+ if (left_d<left_min)
+ left_min=left_d;
+
+ if (dir_d>dir_max)
+ dir_max=dir_d;
+ if (dir_d<dir_min)
+ dir_min=dir_d;
+
+ }
+ }
+
+ //make a center point, then the upvector and leftvector
+ dl.pos = dl.left*( left_max+left_min )*0.5 + dl.up*( up_max+up_min )*0.5 + dl.dir*(dir_min-(dir_max-dir_min));
+ dl.left*=(left_max-left_min)*0.5;
+ dl.up*=(up_max-up_min)*0.5;
+ dl.length = (dir_max - dir_min)*10; //arbitrary number to keep it in scale
+
+ }
+}
+
+BakedLightBaker::BVH* BakedLightBaker::_parse_bvh(BVH** p_children, int p_size, int p_depth, int &max_depth) {
+
+ if (p_depth>max_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;i<p_size;i++) {
+
+ aabb.merge_with(p_children[i]->aabb);
+ }
+
+ int li=aabb.get_longest_axis_index();
+
+ switch(li) {
+
+ case Vector3::AXIS_X: {
+ SortArray<BVH*,BVHCmpX> 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<BVH*,BVHCmpY> 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<BVH*,BVHCmpZ> 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<BVH*> bases;
+ bases.resize(triangles.size());
+ int max_depth=0;
+ for(int i=0;i<triangles.size();i++) {
+ bases[i]=memnew( BVH );
+ bases[i]->leaf=&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<Vector3> 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;i<poly.size();i++) {
+ p_octant->surface_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;i<triangles.size();i++) {
+
+ _octree_insert(octree_aabb,octree,&triangles[i],octree_depth-1);
+ }
+
+}
+
+
+void BakedLightBaker::_plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light) {
+
+
+ if (p_octant->leaf) {
+
+ 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;i<max_depth;i++)
+ // stack[i]=0;
+
+ int level=0;
+ //AABB ray_aabb;
+ //ray_aabb.pos=p_begin;
+ //ray_aabb.expand_to(p_end);
+
+
+ const BVH *bvhptr = bvh;
+
+ bstack[0]=bvh;
+ stack[0]=TEST_AABB_BIT;
+
+
+ while(true) {
+
+ uint32_t mode = stack[level];
+ const BVH &b = *bstack[level];
+ bool done=false;
+
+ switch(mode) {
+ case TEST_AABB_BIT: {
+
+ if (b.leaf) {
+
+
+ Face3 f3(b.leaf->vertices[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 (nd<d) {
+
+ d=nd;
+ r_point=res;
+ r_normal=f3.get_plane().get_normal();
+ inters=true;
+ }
+
+ }
+
+ stack[level]=VISIT_DONE_BIT;
+ } else {
+
+
+ bool valid = b.aabb.intersects_segment(p_begin,p_end);
+ // bool valid = b.aabb.intersects(ray_aabb);
+
+ if (!valid) {
+
+ stack[level]=VISIT_DONE_BIT;
+
+ } else {
+
+ stack[level]=VISIT_LEFT_BIT;
+ }
+ }
+
+ } continue;
+ case VISIT_LEFT_BIT: {
+
+ stack[level]=VISIT_RIGHT_BIT;
+ bstack[level+1]=b.children[0];
+ stack[level+1]=TEST_AABB_BIT;
+ level++;
+
+ } continue;
+ case VISIT_RIGHT_BIT: {
+
+ stack[level]=VISIT_DONE_BIT;
+ bstack[level+1]=b.children[1];
+ stack[level+1]=TEST_AABB_BIT;
+ level++;
+ } continue;
+ case VISIT_DONE_BIT: {
+
+ if (level==0) {
+ done=true;
+ break;
+ } else
+ level--;
+
+ } continue;
+ }
+
+
+ if (done)
+ break;
+ }
+
+
+ if (inters) {
+
+ //print_line("collision!");
+ if (n.dot(r_normal)>0)
+ 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;i<directional_lights.size();i++) {
+
+ const DirLight &dl=directional_lights[i];
+ float total_area = dl.left.length()*2*dl.up.length()*2;
+ float cell_area = cell_size*cell_size;;
+ nrg+= dl.energy * (dl.rays_thrown * cell_area / total_area);
+ nrg*=5;
+ }
+
+ return nrg;
+}
+
+void BakedLightBaker::throw_rays(int p_amount) {
+
+
+
+ for(int i=0;i<directional_lights.size();i++) {
+
+ DirLight &dl=directional_lights[i];
+
+ float sr = Math::sqrt(p_amount);
+ float aspect = dl.up.length()/dl.left.length();
+
+
+ for(int j=0;j<p_amount;j++) {
+ Vector3 from = dl.pos;
+ from+=dl.up*(Math::randf()*2.0-1.0);
+ from+=dl.left*(Math::randf()*2.0-1.0);
+ Vector3 to = from+dl.dir*dl.length;
+ Color col=dl.diffuse;
+ col.r*=dl.energy;
+ col.g*=dl.energy;
+ col.b*=dl.energy;
+ dl.rays_thrown++;
+ _throw_ray(from,to,col,NULL,0,max_bounces);
+ }
+
+
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+void BakedLightBaker::bake(Node* p_node) {
+
+ cell_count=0;
+
+ _parse_geometry(p_node);
+ _fix_lights();
+ _make_bvh();
+ _make_octree();
+
+}
+
+
+
+
+void BakedLightEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ p_node->remove_child(preview);
+ preview->set_mesh(Ref<Mesh>());
+ hide();
+ }
+
+}
+
+
+
+void BakedLightEditor::_menu_option(int p_option) {
+
+
+ switch(p_option) {
+
+
+ case MENU_OPTION_BAKE: {
+
+ ERR_FAIL_COND(!node);
+ preview->set_mesh(Ref<Mesh>());
+ 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<Color> colors;
+ DVector<Vector3> vertices;
+ colors.resize(baker->cell_count*36);
+ vertices.resize(baker->cell_count*36);
+
+
+ {
+ DVector<Color>::Write cw=colors.write();
+ DVector<Vector3>::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<FixedMaterial> 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<Mesh> 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<BakedLight>());
+}
+
+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 <reduzio@gmail.com>
+*/
+
+
+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<Sample>& p_sample,Ref<Imag
if (len<1)
return;
- for(int i=0;i<w;i++) {
- // i trust gcc will optimize this loop
- float max[2]={-1e10,-1e10};
- float min[2]={1e10,1e10};
- int c=stereo?2:1;
- int from = i*len/w;
- int to = (i+1)*len/w;
- if (to>=len)
- to=len-1;
-
- if (_16) {
- const int16_t*src =(const int16_t*)sdata;
-
- for(int j=0;j<c;j++) {
-
- for(int k=from;k<=to;k++) {
-
- float v = src[k*c+j]/32768.0;
- if (v>max[j])
- max[j]=v;
- if (v<min[j])
- min[j]=v;
+ if (p_sample->get_format()==Sample::FORMAT_IMA_ADPCM) {
+
+
+ } else {
+ for(int i=0;i<w;i++) {
+ // i trust gcc will optimize this loop
+ float max[2]={-1e10,-1e10};
+ float min[2]={1e10,1e10};
+ int c=stereo?2:1;
+ int from = i*len/w;
+ int to = (i+1)*len/w;
+ if (to>=len)
+ to=len-1;
+
+ if (_16) {
+ const int16_t*src =(const int16_t*)sdata;
+
+ for(int j=0;j<c;j++) {
+
+ for(int k=from;k<=to;k++) {
+
+ float v = src[k*c+j]/32768.0;
+ if (v>max[j])
+ max[j]=v;
+ if (v<min[j])
+ min[j]=v;
+ }
+
}
+ } else {
- }
- } else {
+ const int8_t*src =(const int8_t*)sdata;
- const int8_t*src =(const int8_t*)sdata;
+ for(int j=0;j<c;j++) {
- for(int j=0;j<c;j++) {
+ for(int k=from;k<=to;k++) {
- for(int k=from;k<=to;k++) {
+ float v = src[k*c+j]/128.0;
+ if (v>max[j])
+ max[j]=v;
+ if (v<min[j])
+ min[j]=v;
+ }
- float v = src[k*c+j]/128.0;
- if (v>max[j])
- max[j]=v;
- if (v<min[j])
- min[j]=v;
}
-
}
- }
- if (!stereo) {
- for(int j=0;j<h;j++) {
- float v = (j/(float)h) * 2.0 - 1.0;
- uint8_t* imgofs = &imgw[(j*w+i)*3];
- if (v>min[0] && v<max[0]) {
- imgofs[0]=255;
- imgofs[1]=150;
- imgofs[2]=80;
- } else {
- imgofs[0]=0;
- imgofs[1]=0;
- imgofs[2]=0;
+ if (!stereo) {
+ for(int j=0;j<h;j++) {
+ float v = (j/(float)h) * 2.0 - 1.0;
+ uint8_t* imgofs = &imgw[(j*w+i)*3];
+ if (v>min[0] && v<max[0]) {
+ imgofs[0]=255;
+ imgofs[1]=150;
+ imgofs[2]=80;
+ } else {
+ imgofs[0]=0;
+ imgofs[1]=0;
+ imgofs[2]=0;
+ }
}
- }
- } else {
-
- for(int j=0;j<h;j++) {
-
- int half,ofs;
- float v;
- if (j<(h/2)) {
- half=0;
- ofs=0;
- v = (j/(float)(h/2)) * 2.0 - 1.0;
- } else {
- half=1;
- ofs=h/2;
- v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0;
+ } else {
+
+ for(int j=0;j<h;j++) {
+
+ int half,ofs;
+ float v;
+ if (j<(h/2)) {
+ half=0;
+ ofs=0;
+ v = (j/(float)(h/2)) * 2.0 - 1.0;
+ } else {
+ half=1;
+ ofs=h/2;
+ v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0;
+ }
+
+ uint8_t* imgofs = &imgw[(j*w+i)*3];
+ if (v>min[half] && v<max[half]) {
+ imgofs[0]=255;
+ imgofs[1]=150;
+ imgofs[2]=80;
+ } else {
+ imgofs[0]=0;
+ imgofs[1]=0;
+ imgofs[2]=0;
+ }
}
- uint8_t* imgofs = &imgw[(j*w+i)*3];
- if (v>min[half] && v<max[half]) {
- imgofs[0]=255;
- imgofs[1]=150;
- imgofs[2]=80;
- } else {
- imgofs[0]=0;
- imgofs[1]=0;
- imgofs[2]=0;
- }
}
}
-
}
imgdata = DVector<uint8_t>::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<Sample> 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;