diff --git a/bin/tests/test_gui.cpp b/bin/tests/test_gui.cpp index f45fe358a605..f814b0282b89 100644 --- a/bin/tests/test_gui.cpp +++ b/bin/tests/test_gui.cpp @@ -305,7 +305,7 @@ public: richtext->push_color(Color(1,0.5,0.5)); richtext->add_text("leprechauns"); richtext->pop(); -#if 0 + richtext->add_text(" and "); richtext->push_color(Color(0,1.0,0.5)); richtext->add_text("faeries.\n"); @@ -329,7 +329,7 @@ public: richtext->pop(); richtext->add_text("of the rich text label for huge text (not like this text will really be huge but, you know).\nAs long as it is so long that it will work nicely for a test/demo, then it's welcomed in my book...\nChanging subject, the day is cloudy today and I'm wondering if I'll get che chance to travel somewhere nice. Sometimes, watching the clouds from satellite images may give a nice insight about how pressure zones in our planet work, althogh it also makes it pretty obvious to see why most weather forecasts get it wrong so often.\nClouds are so difficult to predict!\nBut it's pretty cool how our civilization has adapted to having water falling from the sky each time it rains..."); //richtext->add_text("Hello!\nGorgeous.."); -#endif + //richtext->push_meta("http://www.scrollingcapabilities.xz"); ///richtext->add_text("Hello!\n"); diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index c9952c6fb8c5..d660d02f6cd6 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -49,6 +49,12 @@ #define _GL_R16F_EXT 0x822D #define _GL_R32F_EXT 0x822E + +#define _GL_RED_EXT 0x1903 +#define _GL_RG_EXT 0x8227 +#define _GL_R8_EXT 0x8229 +#define _GL_RG8_EXT 0x822B + #define _DEPTH_COMPONENT24_OES 0x81A6 #ifdef GLEW_ENABLED @@ -7874,6 +7880,7 @@ void RasterizerGLES2::_update_framebuffer() { glDeleteFramebuffers(1,&framebuffer.luminance[i].fbo); } + for(int i=0;i<3;i++) { glDeleteTextures(1,&framebuffer.blur[i].color); @@ -7925,12 +7932,15 @@ void RasterizerGLES2::_update_framebuffer() { #endif //color - GLuint format_rgba = use_fp16_fb?_GL_RGBA16F_EXT:GL_RGBA; +// GLuint format_rgba = use_fp16_fb?_GL_RGBA16F_EXT:GL_RGBA; + GLuint format_rgba = GL_RGBA; GLuint format_rgb = use_fp16_fb?_GL_RGB16F_EXT:GL_RGB; GLuint format_type = use_fp16_fb?_GL_HALF_FLOAT_OES:GL_UNSIGNED_BYTE; - GLuint format_luminance = use_fp16_fb?_GL_R32F_EXT:GL_RGBA; - GLuint format_luminance_type = use_fp16_fb?GL_FLOAT:GL_UNSIGNED_BYTE; - GLuint format_luminance_components = use_fp16_fb?GL_RED:GL_RGBA; + GLuint format_luminance = use_fp16_fb?_GL_RED_EXT:GL_RGBA; + GLuint format_luminance_type = use_fp16_fb?(full_float_fb_supported?GL_FLOAT:_GL_HALF_FLOAT_OES):GL_UNSIGNED_BYTE; + GLuint format_luminance_components = use_fp16_fb?_GL_RED_EXT:GL_RGBA; + + glGenTextures(1, &framebuffer.color); glBindTexture(GL_TEXTURE_2D, framebuffer.color); @@ -8085,10 +8095,12 @@ void RasterizerGLES2::_update_framebuffer() { GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glBindFramebuffer(GL_FRAMEBUFFER, 0); + + base_size/=3; + DEBUG_TEST_ERROR("Shadow Buffer Init"); ERR_CONTINUE( status != GL_FRAMEBUFFER_COMPLETE ); - base_size/=3; framebuffer.luminance.push_back(lb); } @@ -8239,6 +8251,7 @@ void RasterizerGLES2::init() { // use_attribute_instancing=true; use_texture_instancing=false; use_attribute_instancing=true; + full_float_fb_supported=true; #ifdef OSX_ENABLED use_rgba_shadowmaps=true; use_fp16_fb=false; @@ -8291,9 +8304,11 @@ void RasterizerGLES2::init() { } if (use_fp16_fb) { - use_fp16_fb=extensions.has("GL_OES_texture_half_float") && extensions.has("GL_EXT_color_buffer_half_float"); + use_fp16_fb=extensions.has("GL_OES_texture_half_float") && extensions.has("GL_EXT_color_buffer_half_float") && extensions.has("GL_EXT_texture_rg"); } + full_float_fb_supported=extensions.has("GL_EXT_color_buffer_float"); + //etc_supported=false; use_hw_skeleton_xform=false; diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index dce096b29e86..cf4c8717e94c 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -79,6 +79,7 @@ class RasterizerGLES2 : public Rasterizer { bool npo2_textures_available; bool read_depth_supported; bool use_framebuffers; + bool full_float_fb_supported; bool use_shadow_mapping; bool use_fp16_fb; ShadowFilterTechnique shadow_filter; @@ -90,6 +91,7 @@ class RasterizerGLES2 : public Rasterizer { bool use_texture_instancing; bool use_attribute_instancing; bool use_rgba_shadowmaps; + bool use_half_float; diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index 6d78c69e50ae..f96ec1d1bd3a 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -440,7 +440,7 @@ void main() { highp float vd_lum = dot(texture2D( source_vd_lum, vec2(0.0) ), _multcv ); lum_accum = clamp( vd_lum + (lum_accum-vd_lum)*hdr_time_delta*hdr_exp_adj_speed,min_luminance*(1.0/LUM_RANGE),max_luminance*(1.0/LUM_RANGE)); #else - highp float vd_lum=texture2D( source_vd_lum, vec2(0.0) ); + highp float vd_lum=texture2D( source_vd_lum, vec2(0.0) ).r; lum_accum = clamp( vd_lum + (lum_accum-vd_lum)*hdr_time_delta*hdr_exp_adj_speed,min_luminance,max_luminance); #endif diff --git a/platform/android/globals/global_defaults.cpp b/platform/android/globals/global_defaults.cpp index 9bde79e63c71..84a586d22dcc 100644 --- a/platform/android/globals/global_defaults.cpp +++ b/platform/android/globals/global_defaults.cpp @@ -6,6 +6,7 @@ void register_android_global_defaults() { GLOBAL_DEF("rasterizer.Android/use_fragment_lighting",false); + GLOBAL_DEF("rasterizer.Android/fp16_framebuffer",false); GLOBAL_DEF("display.Android/driver","GLES2"); // GLOBAL_DEF("rasterizer.Android/trilinear_mipmap_filter",false); diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index de1fd7e8c01c..c52503870f1d 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -494,6 +494,17 @@ Ref Spatial::get_world() const { } +#ifdef TOOLS_ENABLED +void Spatial::set_import_transform(const Transform& p_transform) { + data.import_transform=p_transform; +} + +Transform Spatial::get_import_transform() const { + + return data.import_transform; +} +#endif + void Spatial::_bind_methods() { @@ -517,6 +528,9 @@ void Spatial::_bind_methods() { #ifdef TOOLS_ENABLED ObjectTypeDB::bind_method(_MD("_update_gizmo"), &Spatial::_update_gizmo); + ObjectTypeDB::bind_method(_MD("_set_import_transform"), &Spatial::set_import_transform); + ObjectTypeDB::bind_method(_MD("_get_import_transform"), &Spatial::get_import_transform); + ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"_import_transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_import_transform"),_SCS("_get_import_transform")); #endif ObjectTypeDB::bind_method(_MD("update_gizmo"), &Spatial::update_gizmo); diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index e10629f7de1f..e1119be515ba 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -95,6 +95,7 @@ class Spatial : public Node { Ref gizmo; bool gizmo_disabled; bool gizmo_dirty; + Transform import_transform; #endif } data; @@ -158,6 +159,11 @@ public: Transform get_relative_transform(const Node *p_parent) const; +#ifdef TOOLS_ENABLED + void set_import_transform(const Transform& p_transform) ; + Transform get_import_transform() const; +#endif + Spatial(); ~Spatial(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 241d66fce415..94df42fc8fec 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1561,8 +1561,9 @@ RichTextLabel::RichTextLabel() { scroll_active=true; scroll_w=0; - vscroll = memnew( VScrollBar ); + vscroll = memnew( VScrollBar ); add_child(vscroll); + vscroll->set_drag_slave(String("..")); vscroll->set_step(1); vscroll->set_anchor_and_margin( MARGIN_TOP, ANCHOR_BEGIN, 0); vscroll->set_anchor_and_margin( MARGIN_BOTTOM, ANCHOR_END, 0); diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index b13fdabea945..c661a804b354 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -29,7 +29,7 @@ #include "scroll_bar.h" #include "os/keyboard.h" #include "print_string.h" - +#include "os/os.h" bool ScrollBar::focus_by_default=false; @@ -293,6 +293,117 @@ void ScrollBar::_notification(int p_what) { } + if (p_what==NOTIFICATION_ENTER_SCENE) { + + + if (has_node(drag_slave_path)) { + Node *n = get_node(drag_slave_path); + drag_slave=n->cast_to(); + } + + if (drag_slave) { + drag_slave->connect("input_event",this,"_drag_slave_input"); + drag_slave->connect("exit_scene",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); + } + + + } + if (p_what==NOTIFICATION_EXIT_SCENE) { + + if (drag_slave) { + drag_slave->disconnect("input_event",this,"_drag_slave_input"); + drag_slave->disconnect("exit_scene",this,"_drag_slave_exit"); + } + + drag_slave=NULL; + + } + + if (p_what==NOTIFICATION_FIXED_PROCESS) { + + if (drag_slave_touching) { + + if (drag_slave_touching_deaccel) { + + Vector2 pos = Vector2(orientation==HORIZONTAL?get_val():0,orientation==VERTICAL?get_val():0); + pos+=drag_slave_speed*get_fixed_process_delta_time(); + + bool turnoff=false; + + if (orientation==HORIZONTAL) { + + if (pos.x<0) { + pos.x=0; + turnoff=true; + } + + if (pos.x > (get_max()-get_page())) { + pos.x=get_max()-get_page(); + turnoff=true; + } + + set_val(pos.x); + + float sgn_x = drag_slave_speed.x<0? -1 : 1; + float val_x = Math::abs(drag_slave_speed.x); + val_x-=1000*get_fixed_process_delta_time(); + + if (val_x<0) { + turnoff=true; + } + + drag_slave_speed.x=sgn_x*val_x; + + } else { + + + if (pos.y<0) { + pos.y=0; + turnoff=true; + } + + if (pos.y > (get_max()-get_page())) { + pos.y=get_max()-get_page(); + turnoff=true; + } + + set_val(pos.y); + + float sgn_y = drag_slave_speed.y<0? -1 : 1; + float val_y = Math::abs(drag_slave_speed.y); + val_y-=1000*get_fixed_process_delta_time(); + + if (val_y<0) { + turnoff=true; + } + drag_slave_speed.y=sgn_y*val_y; + } + + + if (turnoff) { + set_fixed_process(false); + drag_slave_touching=false; + drag_slave_touching_deaccel=false; + } + + + } else { + + + if (time_since_motion==0 || time_since_motion>0.1) { + + Vector2 diff = drag_slave_accum - last_drag_slave_accum; + last_drag_slave_accum=drag_slave_accum; + drag_slave_speed=diff/get_fixed_process_delta_time(); + } + + time_since_motion+=get_fixed_process_delta_time(); + } + } + + + } + if (p_what==NOTIFICATION_MOUSE_EXIT) { hilite=HILITE_NONE; @@ -434,34 +545,119 @@ float ScrollBar::get_custom_step() const { void ScrollBar::_drag_slave_exit() { - + if (drag_slave) { + drag_slave->disconnect("input_event",this,"_drag_slave_input"); + } + drag_slave=NULL; } void ScrollBar::_drag_slave_input(const InputEvent& p_input) { + switch(p_input.type) { + case InputEvent::MOUSE_BUTTON: { + + const InputEventMouseButton &mb=p_input.mouse_button; + + if (mb.button_index!=1) + break; + + if (mb.pressed) { + + if (drag_slave_touching) { + set_fixed_process(false); + drag_slave_touching_deaccel=false; + drag_slave_touching=false; + drag_slave_speed=Vector2(); + drag_slave_accum=Vector2(); + last_drag_slave_accum=Vector2(); + drag_slave_from=Vector2(); + } + + if (true) { + drag_slave_speed=Vector2(); + drag_slave_accum=Vector2(); + last_drag_slave_accum=Vector2(); + //drag_slave_from=Vector2(h_scroll->get_val(),v_scroll->get_val()); + drag_slave_from= Vector2(orientation==HORIZONTAL?get_val():0,orientation==VERTICAL?get_val():0); + + drag_slave_touching=OS::get_singleton()->has_touchscreen_ui_hint(); + drag_slave_touching_deaccel=false; + time_since_motion=0; + if (drag_slave_touching) { + set_fixed_process(true); + time_since_motion=0; + + } + } + + } else { + + if (drag_slave_touching) { + + if (drag_slave_speed==Vector2()) { + drag_slave_touching_deaccel=false; + drag_slave_touching=false; + set_fixed_process(false); + } else { + + drag_slave_touching_deaccel=true; + } + } + } + } break; + case InputEvent::MOUSE_MOTION: { + + const InputEventMouseMotion &mm=p_input.mouse_motion; + + if (drag_slave_touching && ! drag_slave_touching_deaccel) { + + Vector2 motion = Vector2(mm.relative_x,mm.relative_y); + + drag_slave_accum-=motion; + Vector2 diff = drag_slave_from+drag_slave_accum; + + if (orientation==HORIZONTAL) + set_val(diff.x); + //else + // drag_slave_accum.x=0; + if (orientation==VERTICAL) + set_val(diff.y); + //else + // drag_slave_accum.y=0; + time_since_motion=0; + } + + } break; + } } void ScrollBar::set_drag_slave(const NodePath& p_path) { - if (drag_slave) { - drag_slave->disconnect("input_event",this,"_drag_slave_input"); - drag_slave->disconnect("exit_scene",this,"_drag_slave_exit"); + if (is_inside_scene()) { + + if (drag_slave) { + drag_slave->disconnect("input_event",this,"_drag_slave_input"); + drag_slave->disconnect("exit_scene",this,"_drag_slave_exit"); + } } drag_slave=NULL; drag_slave_path=p_path; - if (has_node(p_path)) { - Node *n = get_node(p_path); - drag_slave=n->cast_to(); - } - if (drag_slave) { - drag_slave->connect("input_event",this,"_drag_slave_input"); - drag_slave->connect("exit_scene",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); - } + if (is_inside_scene()) { + if (has_node(p_path)) { + Node *n = get_node(p_path); + drag_slave=n->cast_to(); + } + + if (drag_slave) { + drag_slave->connect("input_event",this,"_drag_slave_input"); + drag_slave->connect("exit_scene",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); + } + } } NodePath ScrollBar::get_drag_slave() const{ @@ -629,7 +825,11 @@ ScrollBar::ScrollBar(Orientation p_orientation) drag_slave=NULL; drag.active=false; - + + drag_slave_speed=Vector2(); + drag_slave_touching=false; + drag_slave_touching_deaccel=false; + if (focus_by_default) set_focus_mode( FOCUS_ALL ); diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h index 0c2098208363..ad3d1a7f588e 100644 --- a/scene/gui/scroll_bar.h +++ b/scene/gui/scroll_bar.h @@ -74,6 +74,16 @@ class ScrollBar : public Range { Node* drag_slave; NodePath drag_slave_path; + Vector2 drag_slave_speed; + Vector2 drag_slave_accum; + Vector2 drag_slave_from; + Vector2 last_drag_slave_accum; + float last_drag_slave_time; + float time_since_motion; + bool drag_slave_touching; + bool drag_slave_touching_deaccel; + bool click_handled; + void _drag_slave_exit(); void _drag_slave_input(const InputEvent& p_input); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 817833083e2f..c8f9ed16b5c2 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -235,7 +235,7 @@ void ScrollContainer::_notification(int p_what) { } if (pos.y<0) { - pos.x=0; + pos.y=0; turnoff_v=true; } if (pos.y > (v_scroll->get_max()-v_scroll->get_page())) { diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 042666988ac8..b90fd489b32a 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1698,6 +1698,20 @@ Array Node::_get_children() const { return arr; } +#ifdef TOOLS_ENABLED +void Node::set_import_path(const NodePath& p_import_path) { + + + data.import_path=p_import_path; +} + +NodePath Node::get_import_path() const { + + return data.import_path; +} + +#endif + void Node::_bind_methods() { @@ -1760,6 +1774,12 @@ void Node::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_viewport"),&Node::get_viewport); ObjectTypeDB::bind_method(_MD("queue_free"),&Node::queue_delete); +#ifdef TOOLS_ENABLED + ObjectTypeDB::bind_method(_MD("_set_import_path","import_path"),&Node::set_import_path); + ObjectTypeDB::bind_method(_MD("_get_import_path"),&Node::get_import_path); + ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"_import_path",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_import_path"),_SCS("_get_import_path")); + +#endif BIND_CONSTANT( NOTIFICATION_ENTER_SCENE ); BIND_CONSTANT( NOTIFICATION_EXIT_SCENE ); diff --git a/scene/main/node.h b/scene/main/node.h index 32c5d8ef3836..f1ecf497e027 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -82,6 +82,9 @@ private: StringName name; SceneMainLoop *scene; bool inside_scene; +#ifdef TOOLS_ENABLED + NodePath import_path; //path used when imported, used by scene editors to keep tracking +#endif Viewport *viewport; @@ -269,11 +272,18 @@ public: void queue_delete(); +//shitty hacks for speed static void set_human_readable_collision_renaming(bool p_enabled); static void init_node_hrcr(); void force_parent_owned() { data.parent_owned=true; } //hack to avoid duplicate nodes +#ifdef TOOLS_ENABLED + void set_import_path(const NodePath& p_import_path); //path used when imported, used by scene editors to keep tracking + NodePath get_import_path() const; +#endif + + _FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; } /* CANVAS */ diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 27a5ddbeaf95..afd5ee66c5db 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -3046,6 +3046,33 @@ void EditorNode::_load_error_notify(void* p_ud,const String& p_text) { } + +bool EditorNode::_find_scene_in_use(Node* p_node,const String& p_path) const { + + if (p_node->get_filename()==p_path) { + return true; + } + + for(int i=0;iget_child_count();i++) { + + if (_find_scene_in_use(p_node->get_child(i),p_path)) { + return true; + } + } + + return false; +} + + +bool EditorNode::is_scene_in_use(const String& p_path) { + + Node *es = get_edited_scene(); + if (es) + return _find_scene_in_use(es,p_path); + return false; + +} + void EditorNode::register_editor_types() { ObjectTypeDB::register_type(); @@ -3212,6 +3239,7 @@ Error EditorNode::export_platform(const String& p_platform, const String& p_path } + EditorNode::EditorNode() { EditorHelp::generate_doc(); //before any editor classes are crated diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 8b481ac20adf..2cec301cf616 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -398,6 +398,9 @@ class EditorNode : public Node { static Vector _init_callbacks; + bool _find_scene_in_use(Node* p_node,const String& p_path) const; + + protected: void _notification(int p_what); static void _bind_methods(); @@ -485,6 +488,10 @@ public: static void progress_task_step_bg(const String& p_task,int p_step=-1); static void progress_end_task_bg(const String& p_task); + void save_scene(String p_file) { _save_scene(p_file); } + + bool is_scene_in_use(const String& p_path); + void scan_import_changes(); EditorNode(); ~EditorNode(); diff --git a/tools/editor/editor_reimport_dialog.cpp b/tools/editor/editor_reimport_dialog.cpp index 7136731846c5..034ac58a8ef1 100644 --- a/tools/editor/editor_reimport_dialog.cpp +++ b/tools/editor/editor_reimport_dialog.cpp @@ -42,6 +42,9 @@ void EditorReImportDialog::popup_reimport() { List ril; EditorFileSystem::get_singleton()->get_changed_sources(&ril); + scene_must_save=false; + + TreeItem *root = tree->create_item(); for(List::Element *E=ril.front();E;E=E->next()) { @@ -52,11 +55,34 @@ void EditorReImportDialog::popup_reimport() { item->set_tooltip(0,E->get()); item->set_checked(0,true); item->set_editable(0,true); - items.push_back(item); + + String name = E->get(); + + if (EditorFileSystem::get_singleton()->get_file_type(name)=="PackedScene" && EditorNode::get_singleton()->is_scene_in_use(name)) { + + scene_must_save=true; + } } + if (scene_must_save) { + if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->get_filename()=="") { + + error->set_text("Current scene must be saved to re-import."); + error->popup_centered(Size2(250,100)); + get_ok()->set_text("Re-Import"); + get_ok()->set_disabled(true); + return; + + } + get_ok()->set_disabled(false); + get_ok()->set_text("Save & Re-Import"); + } else { + get_ok()->set_text("Re-Import"); + get_ok()->set_disabled(false); + } + popup_centered(Size2(600,400)); @@ -70,7 +96,17 @@ void EditorReImportDialog::ok_pressed() { error->popup_centered(Size2(250,100)); return; } + + + EditorProgress ep("reimport","Re-Importing",items.size()); + String reload_fname; + if (scene_must_save && EditorNode::get_singleton()->get_edited_scene()) { + reload_fname = EditorNode::get_singleton()->get_edited_scene()->get_filename(); + EditorNode::get_singleton()->save_scene(reload_fname); + EditorNode::get_singleton()->clear_scene(); + } + for(int i=0;iget_metadata(0); @@ -87,6 +123,9 @@ void EditorReImportDialog::ok_pressed() { } } + if (reload_fname!="") { + EditorNode::get_singleton()->load_scene(reload_fname); + } EditorFileSystem::get_singleton()->scan_sources(); } @@ -100,5 +139,6 @@ EditorReImportDialog::EditorReImportDialog() { set_title("Re-Import Changed Resources"); error = memnew( AcceptDialog); add_child(error); + scene_must_save=false; } diff --git a/tools/editor/editor_reimport_dialog.h b/tools/editor/editor_reimport_dialog.h index fdb03cb70b0f..a5fac262fcf3 100644 --- a/tools/editor/editor_reimport_dialog.h +++ b/tools/editor/editor_reimport_dialog.h @@ -39,6 +39,7 @@ class EditorReImportDialog : public ConfirmationDialog { Tree *tree; Vector items; AcceptDialog *error; + bool scene_must_save; void ok_pressed(); public: diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.cpp b/tools/editor/io_plugins/editor_scene_import_plugin.cpp index 22a6543ab0d9..78280c32fa29 100644 --- a/tools/editor/io_plugins/editor_scene_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_scene_import_plugin.cpp @@ -36,6 +36,8 @@ #include "io/resource_saver.h" #include "scene/3d/mesh_instance.h" #include "scene/3d/room_instance.h" +#include "scene/3d/body_shape.h" +#include "scene/3d/physics_body.h" #include "scene/3d/portal.h" #include "os/os.h" @@ -104,7 +106,9 @@ class EditorSceneImportDialog : public ConfirmationDialog { struct FlagInfo { int value; + const char *category; const char *text; + bool defval; }; static const FlagInfo scene_flag_names[]; @@ -626,22 +630,24 @@ void EditorSceneImportDialog::_bind_methods() { const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_names[]={ - {EditorSceneImportPlugin::SCENE_FLAG_CREATE_COLLISIONS,"Create Collisions (-col},-colonly)"}, - {EditorSceneImportPlugin::SCENE_FLAG_CREATE_PORTALS,"Create Portals (-portal)"}, - {EditorSceneImportPlugin::SCENE_FLAG_CREATE_ROOMS,"Create Rooms (-room)"}, - {EditorSceneImportPlugin::SCENE_FLAG_SIMPLIFY_ROOMS,"Simplify Rooms"}, - {EditorSceneImportPlugin::SCENE_FLAG_CREATE_BILLBOARDS,"Create Billboards (-bb)"}, - {EditorSceneImportPlugin::SCENE_FLAG_CREATE_IMPOSTORS,"Create Impostors (-imp:dist)"}, - {EditorSceneImportPlugin::SCENE_FLAG_CREATE_LODS,"Create LODs (-lod:dist)"}, - {EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create Cars (-car)"}, - {EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,"Create Car Wheels (-wheel)"}, - {EditorSceneImportPlugin::SCENE_FLAG_DETECT_ALPHA,"Set Alpha in Materials (-alpha)"}, - {EditorSceneImportPlugin::SCENE_FLAG_DETECT_VCOLOR,"Set Vert. Color in Materials (-vcol)"}, - {EditorSceneImportPlugin::SCENE_FLAG_REMOVE_NOIMP,"Remove Nodes (-noimp)"}, - {EditorSceneImportPlugin::SCENE_FLAG_IMPORT_ANIMATIONS,"Import Animations"}, - {EditorSceneImportPlugin::SCENE_FLAG_COMPRESS_GEOMETRY,"Compress Geometry"}, - {EditorSceneImportPlugin::SCENE_FLAG_GENERATE_TANGENT_ARRAYS,"Force Generation of Tangent Arrays"}, - {-1,NULL} + {EditorSceneImportPlugin::SCENE_FLAG_REMOVE_NOIMP,"Actions","Remove Nodes (-noimp)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_IMPORT_ANIMATIONS,"Actions","Import Animations",true}, + {EditorSceneImportPlugin::SCENE_FLAG_COMPRESS_GEOMETRY,"Actions","Compress Geometry",false}, + {EditorSceneImportPlugin::SCENE_FLAG_GENERATE_TANGENT_ARRAYS,"Actions","Force Generation of Tangent Arrays",false}, + {EditorSceneImportPlugin::SCENE_FLAG_DETECT_ALPHA,"Materials","Set Alpha in Materials (-alpha)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_DETECT_VCOLOR,"Materials","Set Vert. Color in Materials (-vcol)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES,"Actions","SRGB->Linear Of Diffuse Textures",false}, + {EditorSceneImportPlugin::SCENE_FLAG_CREATE_COLLISIONS,"Create","Create Collisions (-col},-colonly)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_CREATE_PORTALS,"Create","Create Portals (-portal)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_CREATE_ROOMS,"Create","Create Rooms (-room)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_SIMPLIFY_ROOMS,"Create","Simplify Rooms",false}, + {EditorSceneImportPlugin::SCENE_FLAG_CREATE_BILLBOARDS,"Create","Create Billboards (-bb)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_CREATE_IMPOSTORS,"Create","Create Impostors (-imp:dist)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_CREATE_LODS,"Create","Create LODs (-lod:dist)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create","Create Cars (-car)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,"Create","Create Car Wheels (-wheel)",true}, + {EditorSceneImportPlugin::SCENE_FLAG_CREATE_NAVMESH,"Create","Create Navigation Meshes (-navmesh)",true}, + {-1,NULL,NULL,false} }; @@ -717,19 +723,25 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce TreeItem *root = import_options->create_item(NULL); import_options->set_hide_root(true); - - - - TreeItem *importopts = import_options->create_item(root); - importopts->set_text(0,"Import:"); - const FlagInfo* fn=scene_flag_names; + Map categories; + while(fn->text) { - TreeItem *opt = import_options->create_item(importopts); + String cat = fn->category; + TreeItem *parent; + if (!categories.has(cat)) { + parent = import_options->create_item(root); + parent->set_text(0,cat); + categories[cat]=parent; + } else { + parent=categories[cat]; + } + + TreeItem *opt = import_options->create_item(parent); opt->set_cell_mode(0,TreeItem::CELL_MODE_CHECK); - opt->set_checked(0,true); + opt->set_checked(0,fn->defval); opt->set_editable(0,true); opt->set_text(0,fn->text); opt->set_metadata(0,fn->value); @@ -875,7 +887,7 @@ static String _fixstr(const String& p_what,const String& p_str) { -void EditorSceneImportPlugin::_find_resources(const Variant& p_var,Set >& image_map) { +void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map, bool> &image_map) { switch(p_var.get_type()) { @@ -885,9 +897,9 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var,Set res = p_var; if (res.is_valid()) { - if (res->is_type("Texture")) { + if (res->is_type("Texture") && !image_map.has(res)) { - image_map.insert(res); + image_map.insert(res,false); } else { @@ -898,7 +910,17 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var,Set::Element *E=pl.front();E;E=E->next()) { if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) { - _find_resources(res->get(E->get().name),image_map); + if (E->get().type==Variant::OBJECT && res->cast_to() && (E->get().name=="textures/diffuse" || E->get().name=="textures/detail" || E->get().name=="textures/emission")) { + + Ref tex =res->get(E->get().name); + if (tex.is_valid()) { + + image_map.insert(tex,true); + } + + } else { + _find_resources(res->get(E->get().name),image_map); + } } } @@ -938,7 +960,7 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var,Set,Ref > &collision_map,uint32_t p_flags,Set >& image_map) { +Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map,Ref > &collision_map,uint32_t p_flags,Map,bool >& image_map) { // children first.. for(int i=0;iget_child_count();i++) { @@ -1010,6 +1032,36 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map } } + + if (p_flags&(SCENE_FLAG_DETECT_ALPHA|SCENE_FLAG_DETECT_VCOLOR) && p_node->cast_to()) { + + MeshInstance *mi = p_node->cast_to(); + + Ref m = mi->get_mesh(); + + if (m.is_valid()) { + + for(int i=0;iget_surface_count();i++) { + + Ref mat = m->surface_get_material(i); + if (!mat.is_valid()) + continue; + + if (p_flags&SCENE_FLAG_DETECT_ALPHA && _teststr(mat->get_name(),"alpha")) { + + mat->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); + mat->set_name(_fixstr(mat->get_name(),"alpha")); + } + if (p_flags&SCENE_FLAG_DETECT_VCOLOR && _teststr(mat->get_name(),"vcol")) { + + mat->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true); + mat->set_name(_fixstr(mat->get_name(),"vcol")); + } + + } + } + } + if (p_flags&SCENE_FLAG_REMOVE_NOIMP && p_node->cast_to()) { //remove animations referencing non-importable nodes AnimationPlayer *ap = p_node->cast_to(); @@ -1141,21 +1193,42 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map MeshInstance *mi = p_node->cast_to(); Node * col = mi->create_trimesh_collision_node(); - ERR_FAIL_COND_V(!col,NULL); + col->set_name(_fixstr(name,"colonly")); col->cast_to()->set_transform(mi->get_transform()); p_node->replace_by(col); memdelete(p_node); p_node=col; + StaticBody *sb = col->cast_to(); + CollisionShape *colshape = memnew( CollisionShape); + colshape->set_shape(sb->get_shape(0)); + colshape->set_name("shape"); + sb->add_child(colshape); + colshape->set_owner(p_node->get_owner()); + + } else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS &&_teststr(name,"col") && p_node->cast_to()) { MeshInstance *mi = p_node->cast_to(); mi->set_name(_fixstr(name,"col")); - mi->create_trimesh_collision(); + Node *col= mi->create_trimesh_collision_node(); + ERR_FAIL_COND_V(!col,NULL); + + col->set_name("col"); + p_node->add_child(col); + + + StaticBody *sb = col->cast_to(); + CollisionShape *colshape = memnew( CollisionShape); + colshape->set_shape(sb->get_shape(0)); + colshape->set_name("shape"); + sb->add_child(colshape); + colshape->set_owner(p_node->get_owner()); + } else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to()) { @@ -1346,92 +1419,122 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map } - - return p_node; } -void EditorSceneImportPlugin::_merge_node(Node *p_node,Node*p_root,Node *p_existing,Set >& checked_resources) { +void EditorSceneImportPlugin::_merge_existing_node(Node *p_node,Node *p_imported_scene,Set >& checked_resources,Set &checked_nodes) { - NodePath path = p_root->get_path_to(p_node); + NodePath path = p_node->get_import_path(); - bool valid=false; + if (!path.is_empty() && p_imported_scene->has_node(path)) { - if (p_existing->has_node(path)) { + Node *imported_node = p_imported_scene->get_node(path); - Node *existing = p_existing->get_node(path); - - if (existing->get_type()==p_node->get_type()) { + if (imported_node->get_type()==p_node->get_type()) { //same thing, check what it is - if (existing->get_type()=="MeshInstance") { + if (p_node->get_type()=="MeshInstance") { //merge mesh instance, this is a special case! - MeshInstance *mi_existing=existing->cast_to(); + MeshInstance *mi_imported=imported_node->cast_to(); MeshInstance *mi_node=p_node->cast_to(); - Ref mesh_existing = mi_existing->get_mesh(); + Ref mesh_imported = mi_imported->get_mesh(); Ref mesh_node = mi_node->get_mesh(); - if (mesh_existing.is_null() || checked_resources.has(mesh_node)) { + if (mesh_node.is_null() && mesh_imported.is_valid()) { - if (mesh_node.is_valid()) - mi_existing->set_mesh(mesh_node); - } else if (mesh_node.is_valid()) { + mi_node->set_mesh(mesh_imported); - //mesh will always be overwritten, so check materials from original + } else if (mesh_node.is_valid() && mesh_imported.is_valid()) { - for(int i=0;iget_surface_count();i++) { + if (checked_resources.has(mesh_imported)) { - String name = mesh_node->surface_get_name(i); + mi_node->set_mesh(mesh_imported); + } else { + //mix up meshes + //import new geometry but keep materials + for(int i=0;iget_surface_count();i++) { - if (name!="") { + String name = mesh_imported->surface_get_name(i); - for(int j=0;jget_surface_count();j++) { + for(int j=0;jget_surface_count();j++) { - Ref keep; + Ref mat = mesh_node->surface_get_material(j); + if (mat.is_valid() && mesh_node->surface_get_name(j)==name ) { - if (name==mesh_existing->surface_get_name(j)) { - - Ref mat = mesh_existing->surface_get_material(j); - - if (mat.is_valid()) { - if (mat->get_path()!="" && mat->get_path().begins_with("res://") && mat->get_path().find("::")==-1) { - keep=mat; //mat was loaded from file - } else if (mat->is_edited()) { - keep=mat; //mat was edited - } - } + mesh_imported->surface_set_material(i,mat); break; } - if (keep.is_valid()) - mesh_node->surface_set_material(i,keep); //kept } } + // was imported, do nothing further + checked_resources.insert(mesh_imported); + mi_node->set_mesh(mesh_imported); } - mi_existing->set_mesh(mesh_node); //always overwrite mesh - checked_resources.insert(mesh_node); - } - } else if (existing->get_type()=="Path") { - - Path *path_existing =existing->cast_to(); + } else if (p_node->get_type()=="Path") { + //for paths, overwrite path + Path *path_imported =imported_node->cast_to(); Path *path_node =p_node->cast_to(); - if (path_node->get_curve().is_valid()) { + if (path_imported->get_curve().is_valid()) { - if (!path_existing->get_curve().is_valid() || !path_existing->get_curve()->is_edited()) { - path_existing->set_curve(path_node->get_curve()); - } + path_node->set_curve(path_imported->get_curve()); } + } else if (p_node->get_type()=="Portal") { + //for paths, overwrite path + + Portal *portal_imported =imported_node->cast_to(); + Portal *portal_node =p_node->cast_to(); + + portal_node->set_shape( portal_imported->get_shape() ); + + } else if (p_node->get_type()=="Room") { + //for paths, overwrite path + + Room *room_imported =imported_node->cast_to(); + Room *room_node =p_node->cast_to(); + + room_node->set_room( room_imported->get_room() ); + + } else if (p_node->get_type()=="CollisionShape") { + //for paths, overwrite path + + CollisionShape *collision_imported =imported_node->cast_to(); + CollisionShape *collision_node =p_node->cast_to(); + + collision_node->set_shape( collision_imported->get_shape() ); } } - valid=true; - } else { + if (p_node->cast_to() && imported_node->cast_to()) { + //apply transform if changed + Spatial *snode = p_node->cast_to(); + Spatial *simp = imported_node->cast_to(); + + if (snode->get_import_transform() == snode->get_transform()) { + //not moved, apply new + snode->set_import_transform(simp->get_transform()); + snode->set_transform(simp->get_transform()); + } else if (snode->get_import_transform() == simp->get_import_transform()) { + //do nothing, nothing changed keep local changes + } else { + //changed both, imported and edited, merge + Transform local_xform = snode->get_import_transform().affine_inverse() * snode->get_transform(); + snode->set_import_transform(simp->get_import_transform()); + snode->set_transform(simp->get_import_transform() * local_xform); + } + } + + checked_nodes.insert(imported_node); + + } +#if 0 + else { if (p_node!=p_root && p_existing->has_node(p_root->get_path_to(p_node->get_parent()))) { @@ -1461,25 +1564,76 @@ void EditorSceneImportPlugin::_merge_node(Node *p_node,Node*p_root,Node *p_exist } } +#endif - - if (valid) { - - for(int i=0;iget_child_count();i++) { - _merge_node(p_node->get_child(i),p_root,p_existing,checked_resources); - } + for(int i=0;iget_child_count();i++) { + _merge_existing_node(p_node->get_child(i),p_imported_scene,checked_resources,checked_nodes); } - } -void EditorSceneImportPlugin::_merge_scenes(Node *p_existing,Node *p_new) { +void EditorSceneImportPlugin::_add_new_nodes(Node *p_node,Node *p_imported,Node *p_imported_scene,Set &checked_nodes) { + + + for(int i=0;iget_child_count();i++) { + + + Node *imported_node = p_imported->get_child(i); + + if (imported_node->get_owner()!=p_imported_scene) + continue; //end of the road + + Vector nn; + nn.push_back(imported_node->get_name()); + NodePath imported_path(nn,false); + + if (!p_node->has_node(imported_path) && !checked_nodes.has(imported_node)) { + //not there, re-add it + //add it.. because not existing in existing scene + Object *o = ObjectTypeDB::instance(imported_node->get_type()); + Node *n=NULL; + if (o) + n=o->cast_to(); + + if (n) { + + List pl; + imported_node->get_property_list(&pl); + for(List::Element *E=pl.front();E;E=E->next()) { + if (!(E->get().usage&PROPERTY_USAGE_STORAGE)) + continue; + n->set( E->get().name, imported_node->get(E->get().name) ); + } + + p_node->add_child(n); + } + + } + + + if (p_node->has_node(imported_path)) { + + Node *other_node = p_node->get_node(imported_path); + + _add_new_nodes(other_node,imported_node,p_imported_scene,checked_nodes); + + } + + } +} + + +void EditorSceneImportPlugin::_merge_scenes(Node *p_node,Node *p_imported) { Set > checked_resources; - _merge_node(p_new,p_new,p_existing,checked_resources); - + Set checked_nodes; + _merge_existing_node(p_node,p_imported,checked_resources,checked_nodes); + _add_new_nodes(p_node,p_imported,p_imported,checked_nodes); + //add existing.. ? } + + #if 0 Error EditorImport::import_scene(const String& p_path,const String& p_dest_path,const String& p_resource_path,uint32_t p_flags,ImageFormat p_image_format,ImageCompression p_image_compression,uint32_t p_image_flags,float p_quality,uint32_t animation_flags,Node **r_scene,Ref p_post_import) { @@ -1488,6 +1642,26 @@ Error EditorImport::import_scene(const String& p_path,const String& p_dest_path, } #endif +void EditorSceneImportPlugin::_tag_import_paths(Node *p_scene,Node *p_node) { + + if (p_scene!=p_node && p_node->get_owner()!=p_scene) + return; + + NodePath path = p_scene->get_path_to(p_node); + p_node->set_import_path( path ); + + Spatial *snode=p_node->cast_to(); + + if (snode) { + + snode->set_import_transform(snode->get_transform()); + } + + for(int i=0;iget_child_count();i++) { + _tag_import_paths(p_scene,p_node->get_child(i)); + } + +} Error EditorSceneImportPlugin::import1(const Ref& p_from,Node**r_node,List *r_missing) { @@ -1549,6 +1723,8 @@ Error EditorSceneImportPlugin::import1(const Ref& p_from return err; } + _tag_import_paths(scene,scene); + *r_node=scene; return OK; } @@ -1566,6 +1742,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c bool merge = !bool(from->get_option("reimport")); + from->set_source_md5(0,FileAccess::get_md5(src_path)); from->set_editor(get_name()); @@ -1576,7 +1753,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c Ref imd = memnew(ResourceImportMetadata); - Set< Ref > imagemap; + Map< Ref,bool > imagemap; scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap); @@ -1622,12 +1799,12 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c int image_flags = from->get_option("texture_flags"); float image_quality = from->get_option("texture_quality"); - for (Set< Ref >::Element *E=imagemap.front();E;E=E->next()) { + for (Map< Ref,bool >::Element *E=imagemap.front();E;E=E->next()) { //texture could be converted to something more useful for 3D, that could load individual mipmaps and stuff //but not yet.. - Ref texture = E->get(); + Ref texture = E->key(); ERR_CONTINUE(!texture.is_valid()); @@ -1657,7 +1834,10 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c Ref imd = memnew( ResourceImportMetadata ); print_line("flags: "+itos(image_flags)); - imd->set_option("flags",image_flags); + uint32_t flags = image_flags; + if (E->get()) + flags|=EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_TO_LINEAR; + imd->set_option("flags",flags); imd->set_option("format",image_format); imd->set_option("quality",image_quality); imd->set_option("atlas",false); @@ -1697,11 +1877,14 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c if (merge) { + print_line("MERGING?????"); progress.step("Merging..",103); - FileAccess *fa = FileAccess::create(FileAccess::ACCESS_FILESYSTEM); + FileAccess *fa = FileAccess::create(FileAccess::ACCESS_RESOURCES); + print_line("OPEN IN FS: "+p_dest_path); if (fa->file_exists(p_dest_path)) { + print_line("TRY REALLY TO MERGE?"); //try to merge Ref s = ResourceLoader::load(p_dest_path); @@ -1711,7 +1894,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c if (existing) { - _merge_scenes(scene,existing); + _merge_scenes(existing,scene); memdelete(scene); scene=existing; diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.h b/tools/editor/io_plugins/editor_scene_import_plugin.h index 9e08f8371b9d..928fff2afb20 100644 --- a/tools/editor/io_plugins/editor_scene_import_plugin.h +++ b/tools/editor/io_plugins/editor_scene_import_plugin.h @@ -99,11 +99,14 @@ class EditorSceneImportPlugin : public EditorImportPlugin { Vector > importers; - void _find_resources(const Variant& p_var,Set >& image_map); - Node* _fix_node(Node *p_node,Node *p_root,Map,Ref > &collision_map,uint32_t p_flags,Set >& image_map); - void _merge_node(Node *p_node,Node*p_root,Node *p_existing,Set >& checked_resources); - void _merge_scenes(Node *p_existing,Node *p_new); + void _find_resources(const Variant& p_var,Map,bool >& image_map); + Node* _fix_node(Node *p_node,Node *p_root,Map,Ref > &collision_map,uint32_t p_flags,Map,bool >& image_map); + void _merge_existing_node(Node *p_node,Node *p_imported_scene,Set >& checked_resources,Set &checked_nodes); + void _add_new_nodes(Node *p_node,Node *p_imported,Node *p_imported_scene,Set &checked_nodes); + void _merge_scenes(Node *p_node, Node *p_imported); + + void _tag_import_paths(Node *p_scene,Node *p_node); public: @@ -120,11 +123,13 @@ public: SCENE_FLAG_CREATE_WHEELS=1<<9, SCENE_FLAG_DETECT_ALPHA=1<<15, SCENE_FLAG_DETECT_VCOLOR=1<<16, + SCENE_FLAG_CREATE_NAVMESH=1<<17, SCENE_FLAG_REMOVE_NOIMP=1<<24, SCENE_FLAG_IMPORT_ANIMATIONS=1<<25, SCENE_FLAG_COMPRESS_GEOMETRY=1<<26, SCENE_FLAG_GENERATE_TANGENT_ARRAYS=1<<27, + SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES=1<<28, };