diff options
139 files changed, 4324 insertions, 1794 deletions
diff --git a/.travis.yml b/.travis.yml index 73b07acb7f..6dd21dae0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,4 +11,4 @@ before_script: - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi -script: scons bin/godot +script: scons platform=x11 diff --git a/SConstruct b/SConstruct index 7589ab3e6c..fc9c7dca35 100644 --- a/SConstruct +++ b/SConstruct @@ -99,6 +99,7 @@ opts.Add('vorbis','Build Ogg Vorbis Support: (yes/no)','yes') opts.Add('minizip','Build Minizip Archive Support: (yes/no)','yes') opts.Add('squish','Squish BC Texture Compression in editor (yes/no)','yes') opts.Add('theora','Theora Video (yes/no)','yes') +opts.Add('use_theoraplayer_binary', "Use precompiled binaries from libtheoraplayer for ogg/theora/vorbis (yes/no)", "no") opts.Add('freetype','Freetype support in editor','yes') opts.Add('speex','Speex Audio (yes/no)','yes') opts.Add('xml','XML Save/Load support (yes/no)','yes') diff --git a/core/globals.cpp b/core/globals.cpp index 5be53fd853..94fa331bed 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -566,9 +566,11 @@ static Variant _decode_variant(const String& p_string) { ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,Variant()); int scode=0; - if (params[0].is_numeric()) + if (params[0].is_numeric()) { scode=params[0].to_int(); - else + if (scode<10) + scode+=KEY_0; + } else scode=find_keycode(params[0]); InputEvent ie; diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 45e8cf69ab..b707fd9c13 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -471,9 +471,12 @@ static Variant _decode_variant(const String& p_string) { ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,Variant()); int scode=0; - if (params[0].is_numeric()) + if (params[0].is_numeric()) { scode=params[0].to_int(); - else + if (scode < 10) { + scode=KEY_0+scode; + } + } else scode=find_keycode(params[0]); InputEvent ie; diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 92236a374f..ad48ceaac0 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -76,7 +76,7 @@ void Math::seed(uint32_t x) { void Math::randomize() { OS::Time time = OS::get_singleton()->get_time(); - seed(OS::get_singleton()->get_ticks_usec()*time.hour*time.min*time.sec*rand()); /* *OS::get_singleton()->get_time().sec); // windows doesn't have get_time(), returns always 0 */ + seed(OS::get_singleton()->get_ticks_usec()*(time.hour+1)*(time.min+1)*(time.sec+1)*rand()); /* *OS::get_singleton()->get_time().sec); // windows doesn't have get_time(), returns always 0 */ } uint32_t Math::rand() { diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index ed30de6915..a417cdaddf 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -63,7 +63,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me Vector3 sp = p_points[i].snapped(0.0001); if (valid_cache.has(sp)) { valid_points[i]=false; - print_line("INVALIDATED: "+itos(i)); + //print_line("INVALIDATED: "+itos(i)); }else { valid_points[i]=true; valid_cache.insert(sp); @@ -428,6 +428,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me List<Geometry::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left; ERR_CONTINUE(O==E); + ERR_CONTINUE(O==NULL); if (O->get().plane.is_almost_like(f.plane)) { //merge and delete edge and contiguous face, while repointing edges (uuugh!) diff --git a/core/object.cpp b/core/object.cpp index b011d1ad3d..42d570042f 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -1489,7 +1489,7 @@ void Object::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_block_signals","enable"),&Object::set_block_signals); ObjectTypeDB::bind_method(_MD("is_blocking_signals"),&Object::is_blocking_signals); ObjectTypeDB::bind_method(_MD("set_message_translation","enable"),&Object::set_message_translation); - ObjectTypeDB::bind_method(_MD("can_translate_messages"),&Object::set_message_translation); + ObjectTypeDB::bind_method(_MD("can_translate_messages"),&Object::can_translate_messages); ObjectTypeDB::bind_method(_MD("property_list_changed_notify"),&Object::property_list_changed_notify); ObjectTypeDB::bind_method(_MD("XL_MESSAGE","message"),&Object::XL_MESSAGE); diff --git a/core/ustring.cpp b/core/ustring.cpp index cd33c276a8..d75c21d16e 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -555,6 +555,42 @@ String String::get_slice(String p_splitter, int p_slice) const { } + +Vector<String> String::split_spaces() const { + + Vector<String> ret; + int from=0; + int i=0; + int len = length(); + bool inside=false; + + while(true) { + + bool empty=operator[](i)<33; + + if (i==0) + inside=!empty; + + if (!empty && !inside) { + inside=true; + from=i; + } + + if (empty && inside) { + + ret.push_back(substr(from,i-from)); + inside=false; + } + + if (i==len) + break; + i++; + } + + return ret; + +} + Vector<String> String::split(const String &p_splitter,bool p_allow_empty) const { Vector<String> ret; diff --git a/core/ustring.h b/core/ustring.h index 4831341866..8fe3a95463 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -150,6 +150,7 @@ public: String get_slice(String p_splitter,int p_slice) const; Vector<String> split(const String &p_splitter,bool p_allow_empty=true) const; + Vector<String> split_spaces() const; Vector<float> split_floats(const String &p_splitter,bool p_allow_empty=true) const; Vector<float> split_floats_mk(const Vector<String> &p_splitters,bool p_allow_empty=true) const; Vector<int> split_ints(const String &p_splitter,bool p_allow_empty=true) const; diff --git a/demos/2d/kinematic_char/player.gd b/demos/2d/kinematic_char/player.gd index 5c56477758..9cff0269e8 100644 --- a/demos/2d/kinematic_char/player.gd +++ b/demos/2d/kinematic_char/player.gd @@ -74,6 +74,9 @@ func _fixed_process(delta): var floor_velocity=Vector2() if (is_colliding()): + # you can check which tile was collision against with this + # print(get_collider_metadata()) + #ran against something, is it the floor? get normal var n = get_collision_normal() diff --git a/demos/3d/platformer/tiles.res b/demos/3d/platformer/tiles.res Binary files differindex 53534788a1..d4fb779ff1 100644 --- a/demos/3d/platformer/tiles.res +++ b/demos/3d/platformer/tiles.res diff --git a/drivers/gles1/rasterizer_gles1.cpp b/drivers/gles1/rasterizer_gles1.cpp index 02de063bda..00fc85c41c 100644 --- a/drivers/gles1/rasterizer_gles1.cpp +++ b/drivers/gles1/rasterizer_gles1.cpp @@ -5365,6 +5365,18 @@ Variant RasterizerGLES1::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } +/* SAMPLED LIGHT */ + +RID RasterizerGLES1::sampled_light_dp_create(int p_width,int p_height) { + + return sampled_light_owner.make_rid(memnew(SampledLight)); +} + +void RasterizerGLES1::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + +} + /*MISC*/ bool RasterizerGLES1::is_texture(const RID& p_rid) const { @@ -5559,6 +5571,13 @@ void RasterizerGLES1::free(const RID& p_rid) { environment_owner.free(p_rid); memdelete( env ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); }; } diff --git a/drivers/gles1/rasterizer_gles1.h b/drivers/gles1/rasterizer_gles1.h index cca953eed0..0995089dd7 100644 --- a/drivers/gles1/rasterizer_gles1.h +++ b/drivers/gles1/rasterizer_gles1.h @@ -488,6 +488,13 @@ class RasterizerGLES1 : public Rasterizer { mutable RID_Owner<Environment> environment_owner; + struct SampledLight { + + int w,h; + }; + + mutable RID_Owner<SampledLight> sampled_light_owner; + struct ShadowBuffer; struct LightInstance { @@ -1190,6 +1197,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier); + /*MISC*/ diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index f876b1acd3..bb0fd2e593 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -403,19 +403,55 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.convert(Image::FORMAT_RGBA); r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; } break; case Image::FORMAT_RGB: { r_gl_components=3; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_EXT:GL_RGB; + + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_EXT; + } else { + r_gl_format=GL_RGB; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGB; + } } break; case Image::FORMAT_RGBA: { r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } + r_has_alpha_cache=true; } break; case Image::FORMAT_BC1: { @@ -426,7 +462,18 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; } else { @@ -445,7 +492,18 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; } else { @@ -465,7 +523,18 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; } else { @@ -484,7 +553,18 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; } else { @@ -503,7 +583,18 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; } else { @@ -520,7 +611,18 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; @@ -540,7 +642,18 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.decompress(); r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; @@ -561,7 +674,18 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.decompress(); r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; } else { @@ -578,7 +702,18 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.decompress(); r_gl_components=4; - r_gl_format=GL_RGBA; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_format=GL_RGBA; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGBA; + } r_has_alpha_cache=true; } else { @@ -590,12 +725,24 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } break; case Image::FORMAT_ETC: { - if (!etc_supported) { + if (!etc_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (!image.empty()) { image.decompress(); } r_gl_components=3; + if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { + + if (srgb_supported) { + r_gl_format=_GL_SRGB_EXT; + } else { + r_gl_format=GL_RGB; + if (!image.empty()) + image.srgb_to_linear(); + } + } else { + r_gl_format=GL_RGB; + } r_gl_format=GL_RGB; @@ -1458,6 +1605,7 @@ void RasterizerGLES2::material_set_flag(RID p_material, VS::MaterialFlag p_flag, Material *material = material_owner.get(p_material); ERR_FAIL_COND(!material); ERR_FAIL_INDEX(p_flag,VS::MATERIAL_FLAG_MAX); + material->flags[p_flag]=p_enabled; } @@ -4271,7 +4419,7 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { enablers.push_back("#define ENABLE_UV_INTERP\n"); if (fragment_flags.use_uv2_interp || vertex_flags.use_uv2_interp) enablers.push_back("#define ENABLE_UV2_INTERP\n"); - if (fragment_flags.use_tangent_interp || vertex_flags.use_tangent_interp) + if (fragment_flags.use_tangent_interp || vertex_flags.use_tangent_interp || fragment_flags.uses_normalmap) enablers.push_back("#define ENABLE_TANGENT_INTERP\n"); if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp) enablers.push_back("#define ENABLE_VAR1_INTERP\n"); @@ -4286,6 +4434,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (fragment_flags.uses_discard) { enablers.push_back("#define ENABLE_DISCARD\n"); } + if (fragment_flags.uses_normalmap) { + enablers.push_back("#define ENABLE_NORMALMAP\n"); + } if (light_flags.uses_light) { enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); } @@ -4715,6 +4866,7 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter==SHADOW_FILTER_PCF13); material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM); material_shader.set_conditional(MaterialShaderGLES2::USE_LIGHTMAP_ON_UV2,p_material->flags[VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2]); + material_shader.set_conditional(MaterialShaderGLES2::USE_COLOR_ATTRIB_SRGB_TO_LINEAR,p_material->flags[VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB] && current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]); if (p_opaque_pass && p_material->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA && p_material->shader_cache && p_material->shader_cache->has_alpha) { @@ -4956,7 +5108,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { if (li->near_shadow_buffer) { - glActiveTexture(GL_TEXTURE7); + glActiveTexture(GL_TEXTURE0+max_texture_units-1); //if (read_depth_supported) { glBindTexture(GL_TEXTURE_2D,li->near_shadow_buffer->depth); @@ -4967,7 +5119,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX,li->shadow_projection[0]); material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXEL_SIZE,Vector2(1.0,1.0)/li->near_shadow_buffer->size); - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,7); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,max_texture_units-1); if (shadow_filter==SHADOW_FILTER_ESM) material_shader.set_uniform(MaterialShaderGLES2::ESM_MULTIPLIER,float(li->base->vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER])); @@ -5011,7 +5163,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { } -template<bool USE_NORMAL, bool USE_TANGENT> +template<bool USE_NORMAL, bool USE_TANGENT,bool INPLACE> void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms) { uint32_t basesize = 3; @@ -5021,6 +5173,8 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str basesize+=4; uint32_t extra=(p_dst_stride-basesize*4); + const int dstvec_size=3+(USE_NORMAL?3:0)+(USE_TANGENT?4:0); + float dstcopy[dstvec_size]; for(int i=0;i<p_elements;i++) { @@ -5029,7 +5183,11 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str const uint16_t *bi = (const uint16_t*)&p_src_bones[ss]; const float *bw = (const float *)&p_src_weights[ss]; const float *src_vec=(const float *)&p_src_array[ss]; - float *dst_vec=(float*)&p_dst_array[ds]; + float *dst_vec; + if (INPLACE) + dst_vec=dstcopy; + else + dst_vec=(float*)&p_dst_array[ds]; dst_vec[0]=0.0; dst_vec[1]=0.0; @@ -5082,16 +5240,28 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str end: - //copy extra stuff - const uint8_t *esp =(const uint8_t*) &src_vec[basesize]; - uint8_t *edp =(uint8_t*) &dst_vec[basesize]; + if (INPLACE) { + const uint8_t *esp =(const uint8_t*) dstcopy; + uint8_t *edp =(uint8_t*)&p_dst_array[ds]; - for(uint32_t j=0;j<extra;j++) { - edp[j]=esp[j]; - } + for(uint32_t j=0;j<dstvec_size*4;j++) { + + edp[j]=esp[j]; + } + } else { + //copy extra stuff + const uint8_t *esp =(const uint8_t*) &src_vec[basesize]; + uint8_t *edp =(uint8_t*) &dst_vec[basesize]; + + + for(uint32_t j=0;j<extra;j++) { + + edp[j]=esp[j]; + } + } } } @@ -5166,6 +5336,8 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia } + int16_t coeffp = CLAMP(coef*255,0,255); + for(int i=0;i<VS::ARRAY_MAX-1;i++) { @@ -5175,9 +5347,13 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia int ofs = ad.ofs; int src_stride=surf->stride; - int dst_stride=surf->local_stride; + int dst_stride=skeleton_valid?surf->stride:surf->local_stride; int count = surf->array_len; + if (!skeleton_valid && i>=VS::ARRAY_MAX-3) + break; + + switch(i) { case VS::ARRAY_VERTEX: @@ -5193,7 +5369,21 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia dst[0]= src[0]*coef; dst[1]= src[1]*coef; dst[2]= src[2]*coef; - } break; + }; + + } break; + case VS::ARRAY_COLOR: { + + for(int k=0;k<count;k++) { + + const uint8_t *src = (const uint8_t*)&surf->array_local[ofs+k*src_stride]; + uint8_t *dst = (uint8_t*)&base[ofs+k*dst_stride]; + + dst[0]= (src[0]*coeffp)>>8; + dst[1]= (src[1]*coeffp)>>8; + dst[2]= (src[2]*coeffp)>>8; + dst[3]= (src[3]*coeffp)>>8; + } } break; case VS::ARRAY_TEX_UV: @@ -5206,16 +5396,32 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia dst[0]= src[0]*coef; dst[1]= src[1]*coef; - } break; + } } break; + case VS::ARRAY_BONES: + case VS::ARRAY_WEIGHTS: { + + for(int k=0;k<count;k++) { + + const float *src = (const float*)&surf->array_local[ofs+k*src_stride]; + float *dst = (float*)&base[ofs+k*dst_stride]; + + dst[0]= src[0]; + dst[1]= src[1]; + dst[2]= src[2]; + dst[3]= src[3]; + } + + } break; + } } for(int j=0;j<surf->morph_target_count;j++) { - for(int i=0;i<VS::ARRAY_MAX-1;i++) { + for(int i=0;i<VS::ARRAY_MAX-3;i++) { const Surface::ArrayData& ad=surf->array[i]; if (ad.size==0) @@ -5223,10 +5429,12 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia int ofs = ad.ofs; - int dst_stride=surf->local_stride; + int src_stride=surf->local_stride; + int dst_stride=skeleton_valid?surf->stride:surf->local_stride; int count = surf->array_len; const uint8_t *morph=surf->morph_targets_local[j].array; float w = p_morphs[j]; + int16_t wfp = CLAMP(w*255,0,255); switch(i) { @@ -5237,13 +5445,26 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia for(int k=0;k<count;k++) { - const float *src_morph = (const float*)&morph[ofs+k*dst_stride]; + const float *src_morph = (const float*)&morph[ofs+k*src_stride]; float *dst = (float*)&base[ofs+k*dst_stride]; dst[0]+= src_morph[0]*w; dst[1]+= src_morph[1]*w; dst[2]+= src_morph[2]*w; - } break; + } + + } break; + case VS::ARRAY_COLOR: { + for(int k=0;k<count;k++) { + + const uint8_t *src = (const uint8_t*)&morph[ofs+k*src_stride]; + uint8_t *dst = (uint8_t*)&base[ofs+k*dst_stride]; + + dst[0]= (src[0]*wfp)>>8; + dst[1]= (src[1]*wfp)>>8; + dst[2]= (src[2]*wfp)>>8; + dst[3]= (src[3]*wfp)>>8; + } } break; case VS::ARRAY_TEX_UV: @@ -5251,18 +5472,43 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia for(int k=0;k<count;k++) { - const float *src_morph = (const float*)&morph[ofs+k*dst_stride]; + const float *src_morph = (const float*)&morph[ofs+k*src_stride]; float *dst = (float*)&base[ofs+k*dst_stride]; dst[0]+= src_morph[0]*w; dst[1]+= src_morph[1]*w; - } break; + } } break; } } } + + + if (skeleton_valid) { + + + + const uint8_t *src_weights=&surf->array_local[surf->array[VS::ARRAY_WEIGHTS].ofs]; + const uint8_t *src_bones=&surf->array_local[surf->array[VS::ARRAY_BONES].ofs]; + const Skeleton::Bone *skeleton = &p_skeleton->bones[0]; + + + if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT) + _skeleton_xform<true,true,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton); + else if (surf->format&(VS::ARRAY_FORMAT_NORMAL)) + _skeleton_xform<true,false,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton); + else if (surf->format&(VS::ARRAY_FORMAT_TANGENT)) + _skeleton_xform<false,true,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton); + else + _skeleton_xform<false,false,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton); + + } + + stride=skeleton_valid?surf->stride:surf->local_stride; + + #if 0 { //in-place skeleton tansformation, only used for morphs, slow. @@ -5356,14 +5602,14 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia const uint8_t *src_bones=&surf->array_local[surf->array[VS::ARRAY_BONES].ofs]; const Skeleton::Bone *skeleton = &p_skeleton->bones[0]; - if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT) - _skeleton_xform<true,true>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); + if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT) + _skeleton_xform<true,true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); else if (surf->format&(VS::ARRAY_FORMAT_NORMAL)) - _skeleton_xform<true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); + _skeleton_xform<true,false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); else if (surf->format&(VS::ARRAY_FORMAT_TANGENT)) - _skeleton_xform<false,true>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); + _skeleton_xform<false,true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); else - _skeleton_xform<false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); + _skeleton_xform<false,false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton); stride=dst_stride; @@ -5493,9 +5739,10 @@ void RasterizerGLES2::_render(const Geometry *p_geometry,const Material *p_mater float twd=(1.0/mm->tw)*4.0; float thd=1.0/mm->th; float parm[3]={0.0,01.0,(1.0f/mm->tw)}; - glActiveTexture(GL_TEXTURE6); + glActiveTexture(GL_TEXTURE0+max_texture_units-2); glDisableVertexAttribArray(6); glBindTexture(GL_TEXTURE_2D,mm->tex_id); + material_shader.set_uniform(MaterialShaderGLES2::INSTANCE_MATRICES,GL_TEXTURE0+max_texture_units-2); if (s->index_array_len>0) { @@ -5796,7 +6043,7 @@ void RasterizerGLES2::_setup_skeleton(const Skeleton *p_skeleton) { material_shader.set_conditional(MaterialShaderGLES2::USE_SKELETON,p_skeleton!=NULL); if (p_skeleton && p_skeleton->tex_id) { - glActiveTexture(GL_TEXTURE6); + glActiveTexture(GL_TEXTURE0+max_texture_units-2); glBindTexture(GL_TEXTURE_2D,p_skeleton->tex_id); } @@ -5845,7 +6092,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans bool stores_glow = !shadow && (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) && !p_alpha_pass; - + float sampled_light_dp_multiplier=1.0; bool prev_blend=false; glDisable(GL_BLEND); @@ -5864,6 +6111,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans bool bind_baked_light_octree=false; bool bind_baked_lightmap=false; bool additive=false; + bool bind_dp_sampler=false; if (!shadow) { @@ -5985,6 +6233,22 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,false); material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false); + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,false); + + if (e->instance->sampled_light.is_valid()) { + + SampledLight *sl = sampled_light_owner.get(e->instance->sampled_light); + if (sl) { + + baked_light=NULL; //can't mix + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,true); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); + glBindTexture(GL_TEXTURE_2D,sl->texture); //bind the texture + sampled_light_dp_multiplier=sl->multiplier; + bind_dp_sampler=true; + } + } + if (!additive && baked_light) { @@ -5995,9 +6259,16 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans Texture *tex=texture_owner.get(baked_light->octree_texture); if (tex) { - glActiveTexture(GL_TEXTURE5); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); glBindTexture(tex->target,tex->tex_id); //bind the texture } + if (baked_light->light_texture.is_valid()) { + Texture *texl=texture_owner.get(baked_light->light_texture); + if (texl) { + glActiveTexture(GL_TEXTURE0+max_texture_units-4); + glBindTexture(texl->target,texl->tex_id); //bind the light texture + } + } } } else if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) { @@ -6020,7 +6291,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans Texture *tex = texture_owner.get(texid); if (tex) { - glActiveTexture(GL_TEXTURE5); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); glBindTexture(tex->target,tex->tex_id); //bind the texture } @@ -6096,7 +6367,15 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_SIZE, baked_light->octree_lattice_size); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_DIVIDE, baked_light->octree_lattice_divide); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_STEPS, baked_light->octree_steps); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX,5); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX,max_texture_units-3); + if (baked_light->light_texture.is_valid()) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX,max_texture_units-4); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE,baked_light->light_tex_pixel_size); + } else { + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX,max_texture_units-3); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE,baked_light->octree_tex_pixel_size); + } material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_MULTIPLIER,baked_light->texture_multiplier); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_PIX_SIZE,baked_light->octree_tex_pixel_size); @@ -6105,11 +6384,16 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (bind_baked_lightmap && (baked_light!=prev_baked_light || rebind)) { - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, 5); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, max_texture_units-3); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP_MULTIPLIER, baked_light->lightmap_multiplier); } + if (bind_dp_sampler) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER_MULTIPLIER,sampled_light_dp_multiplier); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER,max_texture_units-3); + } _set_cull(e->mirror,p_reverse_cull); @@ -6118,13 +6402,13 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_uniform(MaterialShaderGLES2::CAMERA_INVERSE_TRANSFORM, p_view_transform_inverse); material_shader.set_uniform(MaterialShaderGLES2::PROJECTION_TRANSFORM, p_projection); if (skeleton && use_hw_skeleton_xform) { - //material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES,6); + material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES,GL_TEXTURE0+max_texture_units-2); material_shader.set_uniform(MaterialShaderGLES2::SKELTEX_PIXEL_SIZE,skeleton->pixel_size); } if (!shadow) { if (!additive && current_env && current_env->fx_enabled[VS::ENV_FX_AMBIENT_LIGHT]) { - Color ambcolor = current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_COLOR]; + Color ambcolor = _convert_color(current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_COLOR]); float ambnrg = current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_ENERGY]; material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHT,Vector3(ambcolor.r*ambnrg,ambcolor.g*ambnrg,ambcolor.b*ambnrg)); } else { @@ -6852,6 +7136,7 @@ void RasterizerGLES2::end_scene() { _debug_shadows(); } // _debug_luminances(); + _debug_samplers(); } @@ -7252,6 +7537,38 @@ void RasterizerGLES2::_debug_luminances() { } +void RasterizerGLES2::_debug_samplers() { + canvas_shader.set_conditional(CanvasShaderGLES2::DEBUG_ENCODED_32,false); + canvas_begin(); + glDisable(GL_BLEND); + _set_color_attrib(Color(1,1,1,1)); + canvas_shader.bind(); + + + List<RID> samplers; + sampled_light_owner.get_owned_list(&samplers); + + Size2 debug_size(128,128); + Size2 ofs; + + + for (List<RID>::Element *E=samplers.front();E;E=E->next()) { + + SampledLight *sl=sampled_light_owner.get(E->get()); + + _debug_draw_shadow(sl->texture, Rect2( ofs, debug_size )); + + ofs.x+=debug_size.x/2; + if ( (ofs.x+debug_size.x) > viewport.width ) { + + ofs.x=0; + ofs.y+=debug_size.y; + } + } + + + +} void RasterizerGLES2::_debug_shadows() { canvas_begin(); @@ -7869,6 +8186,78 @@ Variant RasterizerGLES2::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } + + +RID RasterizerGLES2::sampled_light_dp_create(int p_width,int p_height) { + + SampledLight *slight = memnew(SampledLight); + slight->w=p_width; + slight->h=p_height; + slight->multiplier=1.0; + slight->is_float=float_linear_supported; + + glActiveTexture(GL_TEXTURE0); + glGenTextures(1,&slight->texture); + glBindTexture(GL_TEXTURE_2D, slight->texture); +// for debug, but glitchy +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Remove artifact on the edges of the shadowmap + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + + if (slight->is_float) { +#ifdef GLEW_ENABLED + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, p_width, p_height, 0, GL_RGBA, GL_FLOAT,NULL); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_FLOAT,NULL); +#endif + } else { + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + } + + return sampled_light_owner.make_rid(slight); +} + +void RasterizerGLES2::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + SampledLight *slight = sampled_light_owner.get(p_sampled_light); + ERR_FAIL_COND(!slight); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, slight->texture); + + if (slight->is_float) { + +#ifdef GLEW_ENABLED + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_FLOAT,p_data); +#else + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_FLOAT,p_data); +#endif + + } else { + //convert to bytes + uint8_t *tex8 = (uint8_t*)alloca(slight->w*slight->h*4); + const float* src=(const float*)p_data; + + for(int i=0;i<slight->w*slight->h*4;i++) { + + tex8[i]=Math::fast_ftoi(CLAMP(src[i]*255.0,0.0,255.0)); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_UNSIGNED_BYTE,p_data); + } + + slight->multiplier=p_multiplier; + +} + /*MISC*/ bool RasterizerGLES2::is_texture(const RID& p_rid) const { @@ -8088,6 +8477,13 @@ void RasterizerGLES2::free(const RID& p_rid) { memdelete(render_target->texture_ptr); render_target_owner.free(p_rid); memdelete( render_target ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + glDeleteTextures(1,&sampled_light->texture); + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); }; } @@ -8680,6 +9076,9 @@ void RasterizerGLES2::init() { latc_supported=true; s3tc_srgb_supported=true; use_anisotropic_filter=true; + float_linear_supported=true; + float_supported=true; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&anisotropic_level); anisotropic_level=MIN(anisotropic_level,float(GLOBAL_DEF("rasterizer/anisotropic_filter_level",4.0))); #ifdef OSX_ENABLED @@ -8724,7 +9123,10 @@ void RasterizerGLES2::init() { GLint vtf; glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,&vtf); - use_hw_skeleton_xform=vtf>0 && extensions.has("GL_OES_texture_float"); + float_supported = extensions.has("GL_OES_texture_float"); + use_hw_skeleton_xform=vtf>0 && float_supported; + float_linear_supported = extensions.has("GL_OES_texture_float_linear"); + //if (extensions.has("GL_QCOM_tiled_rendering")) // use_hw_skeleton_xform=false; GLint mva; @@ -8762,7 +9164,7 @@ void RasterizerGLES2::init() { - + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units); //read_depth_supported=false; { diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index 4b56775b88..91395054d9 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -86,6 +86,8 @@ class RasterizerGLES2 : public Rasterizer { bool use_shadow_mapping; bool use_fp16_fb; bool srgb_supported; + bool float_supported; + bool float_linear_supported; ShadowFilterTechnique shadow_filter; @@ -608,7 +610,7 @@ class RasterizerGLES2 : public Rasterizer { mutable SelfList<Skeleton>::List _skeleton_dirty_list; - template<bool USE_NORMAL, bool USE_TANGENT> + template<bool USE_NORMAL, bool USE_TANGENT,bool INPLACE> void _skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms); struct Light { @@ -704,6 +706,18 @@ class RasterizerGLES2 : public Rasterizer { mutable RID_Owner<Environment> environment_owner; + + struct SampledLight { + + int w,h; + GLuint texture; + float multiplier; + bool is_float; + }; + + mutable RID_Owner<SampledLight> sampled_light_owner; + + struct ViewportData { //1x1 fbo+texture for storing previous HDR value @@ -801,6 +815,7 @@ class RasterizerGLES2 : public Rasterizer { RID shadow_material; Material *shadow_mat_ptr; + int max_texture_units; GLuint base_framebuffer; GLuint gui_quad_buffer; @@ -1071,6 +1086,8 @@ class RasterizerGLES2 : public Rasterizer { void _debug_draw_shadows_type(Vector<ShadowBuffer>& p_shadows,Point2& ofs); void _debug_shadows(); void _debug_luminances(); + void _debug_samplers(); + /***********/ @@ -1531,6 +1548,9 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier); /*MISC*/ diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index ada9efa4b3..50b63e1aa0 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -176,6 +176,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a if (vnode->name==vname_discard) { uses_discard=true; } + if (vnode->name==vname_normalmap) { + uses_normalmap=true; + } if (vnode->name==vname_screen_uv) { uses_screen_uv=true; } @@ -546,6 +549,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT uses_screen_uv=false; uses_light=false; uses_time=false; + uses_normalmap=false; vertex_code_writes_vertex=false; uniforms=r_uniforms; flags=&r_flags; @@ -555,6 +559,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.use_tangent_interp=false; r_flags.use_var1_interp=false; r_flags.use_var2_interp=false; + r_flags.uses_normalmap=false; String error; int errline,errcol; @@ -576,8 +581,10 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.uses_screen_uv=uses_screen_uv; r_flags.uses_light=uses_light; r_flags.uses_time=uses_time; + r_flags.uses_normalmap=uses_normalmap; r_code_line=code; r_globals_line=global_code; + return OK; } @@ -670,6 +677,8 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[1]["NORMAL"]="normal"; mode_replace_table[1]["TANGENT"]="tangent"; mode_replace_table[1]["BINORMAL"]="binormal"; + mode_replace_table[1]["NORMALMAP"]="normalmap"; + mode_replace_table[1]["NORMALMAP_DEPTH"]="normaldepth"; mode_replace_table[1]["VAR1"]="var1_interp"; mode_replace_table[1]["VAR2"]="var2_interp"; mode_replace_table[1]["UV"]="uv"; @@ -728,5 +737,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { vname_vertex="VERTEX"; vname_light="LIGHT"; vname_time="TIME"; + vname_normalmap="NORMALMAP"; } diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index 3dfdd81c0d..5012414c8b 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -50,6 +50,7 @@ private: bool uses_discard; bool uses_time; bool uses_screen_uv; + bool uses_normalmap; bool vertex_code_writes_vertex; Flags *flags; @@ -66,6 +67,7 @@ private: StringName vname_vertex; StringName vname_light; StringName vname_time; + StringName vname_normalmap; Map<StringName,ShaderLanguage::Uniform> *uniforms; @@ -87,6 +89,7 @@ public: bool uses_alpha; bool uses_texscreen; bool uses_texpos; + bool uses_normalmap; bool vertex_code_writes_vertex; bool uses_discard; bool uses_screen_uv; diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index ad8a364ac1..7d9aca4b4d 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -60,7 +60,7 @@ uniform float normal_mult; #ifdef USE_SKELETON attribute vec4 bone_indices; // attrib:6 attribute vec4 bone_weights; // attrib:7 -uniform highp sampler2D skeleton_matrices; // texunit:6 +uniform highp sampler2D skeleton_matrices; uniform highp float skeltex_pixel_size; #endif @@ -76,7 +76,7 @@ attribute highp vec4 instance_row3; // attrib:11 #ifdef USE_TEXTURE_INSTANCING attribute highp vec3 instance_uv; // attrib:6 -uniform highp sampler2D instance_matrices; // texunit:6 +uniform highp sampler2D instance_matrices; #endif @@ -292,11 +292,21 @@ void main() { normal_interp = normalize((modelview * vec4(normal_in,0.0)).xyz); #if defined(ENABLE_COLOR_INTERP) +#ifdef USE_COLOR_ATTRIB_SRGB_TO_LINEAR + + color_interp = vec4( + color_attrib.r<0.04045 ? color_attrib.r * (1.0 / 12.92) : pow((color_attrib.r + 0.055) * (1.0 / (1 + 0.055)), 2.4), + color_attrib.g<0.04045 ? color_attrib.g * (1.0 / 12.92) : pow((color_attrib.g + 0.055) * (1.0 / (1 + 0.055)), 2.4), + color_attrib.b<0.04045 ? color_attrib.b * (1.0 / 12.92) : pow((color_attrib.b + 0.055) * (1.0 / (1 + 0.055)), 2.4), + color_attrib.a + ); +#else color_interp = color_attrib; #endif +#endif #if defined(ENABLE_TANGENT_INTERP) - tangent_interp=normalize(tangent_in); + tangent_interp=normalize((modelview * vec4(tangent_in,0.0)).xyz); binormal_interp = normalize( cross(normal_interp,tangent_interp) * binormalf ); #endif @@ -585,8 +595,10 @@ uniform float time; varying highp vec3 ambient_octree_coords; uniform highp float ambient_octree_lattice_size; uniform highp vec2 ambient_octree_pix_size; +uniform highp vec2 ambient_octree_light_pix_size; uniform highp float ambient_octree_lattice_divide; uniform highp sampler2D ambient_octree_tex; +uniform highp sampler2D ambient_octree_light_tex; uniform float ambient_octree_multiplier; uniform int ambient_octree_steps; @@ -599,6 +611,12 @@ uniform float ambient_lightmap_multiplier; #endif +#ifdef ENABLE_AMBIENT_DP_SAMPLER + +uniform highp sampler2D ambient_dp_sampler; +uniform float ambient_dp_sampler_multiplier; + +#endif FRAGMENT_SHADER_GLOBALS @@ -809,6 +827,12 @@ void main() { vec4 color = color_interp; #endif +#if defined(ENABLE_NORMALMAP) + + vec3 normalmap = vec3(0.0); +#endif + + float normaldepth=1.0; @@ -823,6 +847,12 @@ FRAGMENT_SHADER_CODE } +#if defined(ENABLE_NORMALMAP) + + normal = normalize( mix(normal_interp,tangent_interp * normalmap.x + binormal_interp * normalmap.y + normal_interp * normalmap.z,normaldepth) ) * side; + +#endif + #if defined(ENABLE_DISCARD) if (discard_) { //easy to eliminate dead code @@ -896,12 +926,12 @@ FRAGMENT_SHADER_CODE } //sample color - octant_uv=(octant_uv+0.5)*ambient_octree_pix_size; + octant_uv=(octant_uv+0.5)*ambient_octree_light_pix_size; highp vec3 sub=(mod(ambient_octree_coords,ld)/ld); - octant_uv.xy+=sub.xy*ambient_octree_pix_size.xy; - vec3 col_up=texture2D(ambient_octree_tex,octant_uv).rgb; - octant_uv.y+=ambient_octree_pix_size.y*2.0; - vec3 col_down=texture2D(ambient_octree_tex,octant_uv).rgb; + octant_uv.xy+=sub.xy*ambient_octree_light_pix_size.xy; + vec3 col_up=texture2D(ambient_octree_light_tex,octant_uv).rgb; + octant_uv.y+=ambient_octree_light_pix_size.y*2.0; + vec3 col_down=texture2D(ambient_octree_light_tex,octant_uv).rgb; ambientmap_color=mix(col_up,col_down,sub.z)*ambient_octree_multiplier; ambientmap_color*=diffuse.rgb; @@ -912,6 +942,26 @@ FRAGMENT_SHADER_CODE +#ifdef ENABLE_AMBIENT_DP_SAMPLER + + vec3 ambientmap_color = vec3(0.0,0.0,0.0); + + { + + vec3 dp_normal = normalize((vec4(normal,0) * camera_inverse_transform).xyz); + vec2 ambient_uv = (dp_normal.xy / (1.0+abs(dp_normal.z)))*0.5+0.5; //dual paraboloid + ambient_uv.y*=0.5; + if (dp_normal.z<0) { + + ambient_uv.y=(0.5-ambient_uv.y)+0.5; + + } + + ambientmap_color = texture2D(ambient_dp_sampler,ambient_uv ).rgb * ambient_dp_sampler_multiplier; + ambientmap_color*=diffuse.rgb; + } + +#endif @@ -1202,7 +1252,7 @@ LIGHT_SHADER_CODE #endif -#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP) +#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP) || defined(ENABLE_AMBIENT_DP_SAMPLER) diffuse.rgb+=ambientmap_color; #endif diff --git a/drivers/ogg/SCsub b/drivers/ogg/SCsub index 5cdc3ea1c0..dd59890064 100644 --- a/drivers/ogg/SCsub +++ b/drivers/ogg/SCsub @@ -6,5 +6,6 @@ ogg_sources = [ "ogg/framing.c", ] -env.drivers_sources+=ogg_sources +if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes": + env.drivers_sources+=ogg_sources diff --git a/drivers/theora/SCsub b/drivers/theora/SCsub index d3e5838276..ecabce6c9d 100644 --- a/drivers/theora/SCsub +++ b/drivers/theora/SCsub @@ -32,6 +32,7 @@ sources = [ "theora/video_stream_theora.cpp", ] -env.drivers_sources += sources +if env['use_theoraplayer_binary'] != "yes": + env.drivers_sources += sources diff --git a/drivers/theoraplayer/SCsub b/drivers/theoraplayer/SCsub index 023b2c928b..979ff2ed1b 100644 --- a/drivers/theoraplayer/SCsub +++ b/drivers/theoraplayer/SCsub @@ -59,7 +59,6 @@ src/YUV/C/yuv420_grey_c.c src/YUV/C/yuv420_yuv_c.c src/YUV/C/yuv420_rgb_c.c src/TheoraVideoFrame.cpp -video_stream_theoraplayer.cpp """) if env["platform"] == "iphone": @@ -79,7 +78,18 @@ if env["platform"] == "android": env_theora.Append(CPPPATH=["#drivers/theoraplayer/include/theoraplayer", "#drivers/theoraplayer/src/YUV", "#drivers/theoraplayer/src/YUV/libyuv/include", "#drivers/theoraplayer/src/Theora", "#drivers/theoraplayer/src/AVFoundation"]) objs = [] -env_theora.add_source_files(objs, sources) + +env_theora.add_source_files(objs, ["video_stream_theoraplayer.cpp"]) + +if env['use_theoraplayer_binary'] == "yes": + if env["platform"] == "iphone": + env.Append(LIBPATH=['#drivers/theoraplayer/lib/ios']) + env.Append(LIBS=['theoraplayer', 'ogg', 'theora', 'tremor']) + if env["platform"] == "windows": + env.Append(LIBPATH=['#drivers/theoraplayer/lib/windows']) + env.Append(LINKFLAGS=['libtheoraplayer_static.lib', 'libogg.lib', 'libtheora.lib', 'libvorbis.lib']) +else: + env_theora.add_source_files(objs, sources) env.drivers_sources += objs diff --git a/drivers/vorbis/SCsub b/drivers/vorbis/SCsub index 1c7cccc427..2c137629ac 100644 --- a/drivers/vorbis/SCsub +++ b/drivers/vorbis/SCsub @@ -3,6 +3,9 @@ Import('env') sources = [ "vorbis/audio_stream_ogg_vorbis.cpp", +] + +sources_lib = [ "vorbis/analysis.c", #"vorbis/barkmel.c", "vorbis/bitrate.c", @@ -32,3 +35,6 @@ sources = [ env.drivers_sources += sources +if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes": + env.drivers_sources += sources_lib + diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp index d9b7b1d161..996f75d165 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp +++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp @@ -215,7 +215,7 @@ AudioStreamOGGVorbis::UpdateMode AudioStreamOGGVorbis::get_update_mode() const { bool AudioStreamOGGVorbis::is_playing() const { - return playing; + return playing || (get_total() - get_todo() -1 > 0); } float AudioStreamOGGVorbis::get_pos() const { diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index aefec59ce0..df6cc6c5e2 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -189,10 +189,10 @@ Error DirAccessWindows::change_dir(String p_dir) { current_dir=real_current_dir_name; // TODO, utf8 parser current_dir=current_dir.replace("\\","/"); - } else { + } //else { SetCurrentDirectoryW(prev_dir.c_str()); - } + //} return worked?OK:ERR_INVALID_PARAMETER; } else { @@ -210,10 +210,10 @@ Error DirAccessWindows::change_dir(String p_dir) { current_dir=real_current_dir_name; // TODO, utf8 parser current_dir=current_dir.replace("\\","/"); - } else { + }// else { SetCurrentDirectoryA(prev_dir.ascii().get_data()); - } + //} return worked?OK:ERR_INVALID_PARAMETER; @@ -352,7 +352,7 @@ bool DirAccessWindows::dir_exists(String p_dir) { DWORD fileAttr; fileAttr = GetFileAttributesExW(p_dir.c_str(), GetFileExInfoStandard, &fileInfo); - if (0xFFFFFFFF == fileAttr) + if (0 == fileAttr) return false; return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); @@ -361,7 +361,7 @@ bool DirAccessWindows::dir_exists(String p_dir) { DWORD fileAttr; fileAttr = GetFileAttributesExA(p_dir.ascii().get_data(), GetFileExInfoStandard, &fileInfo); - if (0xFFFFFFFF == fileAttr) + if (0 == fileAttr) return false; return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index 45eac23450..4c56468297 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -179,7 +179,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre //static function if (codegen.script->member_indices.has(identifier)) { - int idx = codegen.script->member_indices[identifier]; + int idx = codegen.script->member_indices[identifier].index; return idx|(GDFunction::ADDR_TYPE_MEMBER<<GDFunction::ADDR_BITS); //argument (stack root) } } @@ -1507,8 +1507,12 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars #endif } - int new_idx = p_script->member_indices.size(); - p_script->member_indices[name]=new_idx; + //int new_idx = p_script->member_indices.size(); + GDScript::MemberInfo minfo; + minfo.index = p_script->member_indices.size(); + minfo.setter = p_class->variables[i].setter; + minfo.getter = p_class->variables[i].getter; + p_script->member_indices[name]=minfo; p_script->members.insert(name); } diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index a98b07ab92..d1f511b46e 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -114,6 +114,7 @@ int GDScriptLanguage::find_function(const String& p_function,const String& p_cod if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE) { indent=tokenizer.get_token_line_indent(); } + //print_line("TOKEN: "+String(GDTokenizer::get_token_name(tokenizer.get_token()))); if (indent==0 && tokenizer.get_token()==GDTokenizer::TK_PR_FUNCTION && tokenizer.get_token(1)==GDTokenizer::TK_IDENTIFIER) { String identifier = tokenizer.get_token_identifier(1); @@ -122,6 +123,8 @@ int GDScriptLanguage::find_function(const String& p_function,const String& p_cod } } tokenizer.advance(); + //print_line("NEXT: "+String(GDTokenizer::get_token_name(tokenizer.get_token()))); + } return -1; } @@ -247,12 +250,12 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level,List<String> *p ERR_FAIL_COND( script.is_null() ); - const Map<StringName,int>& mi = script->debug_get_member_indices(); + const Map<StringName,GDScript::MemberInfo>& mi = script->debug_get_member_indices(); - for(const Map<StringName,int>::Element *E=mi.front();E;E=E->next()) { + for(const Map<StringName,GDScript::MemberInfo>::Element *E=mi.front();E;E=E->next()) { p_members->push_back(E->key()); - p_values->push_back( instance->debug_get_member_by_index(E->get())); + p_values->push_back( instance->debug_get_member_by_index(E->get().index)); } } diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index 46eade0b7c..659e19a9d0 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -372,10 +372,26 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ } else if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { //identifier (reference) - IdentifierNode *id = alloc_node<IdentifierNode>(); - id->name=tokenizer->get_token_identifier(); - tokenizer->advance(); - expr=id; + const ClassNode* cln = static_cast<const ClassNode*>(get_parse_tree()); + bool bfn = false; + StringName idn( tokenizer->get_token_identifier() ); + + for( int i=0; i<cln->constant_expressions.size(); ++i ) { + + if( cln->constant_expressions[i].identifier == idn ) { + tokenizer->advance(); + expr = cln->constant_expressions[i].expression; + bfn = true; + break; + } + } + + if( !bfn ) { + IdentifierNode *id = alloc_node<IdentifierNode>(); + id->name = idn; + tokenizer->advance(); + expr = id; + } } else if (/*tokenizer->get_token()==GDTokenizer::TK_OP_ADD ||*/ tokenizer->get_token()==GDTokenizer::TK_OP_SUB || tokenizer->get_token()==GDTokenizer::TK_OP_NOT || tokenizer->get_token()==GDTokenizer::TK_OP_BIT_INVERT) { @@ -1179,7 +1195,7 @@ GDParser::Node* GDParser::_reduce_expression(Node *p_node,bool p_to_const) { case OperatorNode::OP_ASSIGN_BIT_XOR: { if (op->arguments[0]->type==Node::TYPE_CONSTANT) { - _set_error("Can't assign to constant"); + _set_error("Can't assign to constant",tokenizer->get_token_line()-1); return op; } @@ -2360,80 +2376,113 @@ void GDParser::_parse_class(ClassNode *p_class) { member._export.name=member.identifier; tokenizer->advance(); - p_class->variables.push_back(member); + if (tokenizer->get_token()==GDTokenizer::TK_OP_ASSIGN) { - if (tokenizer->get_token()!=GDTokenizer::TK_OP_ASSIGN) { +#ifdef DEBUG_ENABLED + int line = tokenizer->get_token_line(); +#endif + tokenizer->advance(); - if (autoexport) { + Node *subexpr=NULL; - _set_error("Type-less export needs a constant expression assigned to infer type."); + subexpr = _parse_and_reduce_expression(p_class,false); + if (!subexpr) return; - } - break; - } -#ifdef DEBUG_ENABLED - int line = tokenizer->get_token_line(); -#endif - tokenizer->advance(); - Node *subexpr=NULL; + if (autoexport) { + if (subexpr->type==Node::TYPE_ARRAY) { - subexpr = _parse_and_reduce_expression(p_class,false); - if (!subexpr) - return; + member._export.type=Variant::ARRAY; - if (autoexport) { - if (subexpr->type==Node::TYPE_ARRAY) { + } else if (subexpr->type==Node::TYPE_DICTIONARY) { - p_class->variables[p_class->variables.size()-1]._export.type=Variant::ARRAY; + member._export.type=Variant::DICTIONARY; - } else if (subexpr->type==Node::TYPE_DICTIONARY) { + } else { - p_class->variables[p_class->variables.size()-1]._export.type=Variant::DICTIONARY; + if (subexpr->type!=Node::TYPE_CONSTANT) { - } else { + _set_error("Type-less export needs a constant expression assigned to infer type."); + return; + } - if (subexpr->type!=Node::TYPE_CONSTANT) { + ConstantNode *cn = static_cast<ConstantNode*>(subexpr); + if (cn->value.get_type()==Variant::NIL) { - _set_error("Type-less export needs a constant expression assigned to infer type."); - return; + _set_error("Can't accept a null constant expression for infering export type."); + return; + } + member._export.type=cn->value.get_type(); } + } +#ifdef TOOLS_ENABLED + if (subexpr->type==Node::TYPE_CONSTANT && member._export.type!=Variant::NIL) { ConstantNode *cn = static_cast<ConstantNode*>(subexpr); - if (cn->value.get_type()==Variant::NIL) { - - _set_error("Can't accept a null constant expression for infering export type."); - return; + if (cn->value.get_type()!=Variant::NIL) { + member.default_value=cn->value; } - p_class->variables[p_class->variables.size()-1]._export.type=cn->value.get_type(); } - } -#ifdef TOOLS_ENABLED - if (subexpr->type==Node::TYPE_CONSTANT && p_class->variables[p_class->variables.size()-1]._export.type!=Variant::NIL) { +#endif + + IdentifierNode *id = alloc_node<IdentifierNode>(); + id->name=member.identifier; + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=OperatorNode::OP_ASSIGN; + op->arguments.push_back(id); + op->arguments.push_back(subexpr); - ConstantNode *cn = static_cast<ConstantNode*>(subexpr); - if (cn->value.get_type()!=Variant::NIL) { - p_class->variables[p_class->variables.size()-1].default_value=cn->value; +#ifdef DEBUG_ENABLED + NewLineNode *nl = alloc_node<NewLineNode>(); + nl->line=line; + p_class->initializer->statements.push_back(nl); +#endif + p_class->initializer->statements.push_back(op); + + + + } else { + + if (autoexport) { + + _set_error("Type-less export needs a constant expression assigned to infer type."); + return; } + } -#endif + if (tokenizer->get_token()==GDTokenizer::TK_PR_SETGET) { - IdentifierNode *id = alloc_node<IdentifierNode>(); - id->name=member.identifier; + tokenizer->advance(); - OperatorNode *op = alloc_node<OperatorNode>(); - op->op=OperatorNode::OP_ASSIGN; - op->arguments.push_back(id); - op->arguments.push_back(subexpr); + if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) { + //just comma means using only getter + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { + _set_error("Expected identifier for setter function after 'notify'."); + } -#ifdef DEBUG_ENABLED - NewLineNode *nl = alloc_node<NewLineNode>(); - nl->line=line; - p_class->initializer->statements.push_back(nl); -#endif - p_class->initializer->statements.push_back(op); + member.setter=tokenizer->get_token_identifier(); + + tokenizer->advance(); + } + + if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { + //there is a getter + tokenizer->advance(); + + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { + _set_error("Expected identifier for getter function after ','."); + } + + member.getter=tokenizer->get_token_identifier(); + tokenizer->advance(); + + } + } + + p_class->variables.push_back(member); _end_statement(); diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index 50b84d389a..16a9a85290 100644 --- a/modules/gdscript/gd_parser.h +++ b/modules/gdscript/gd_parser.h @@ -82,6 +82,8 @@ public: Variant default_value; #endif StringName identifier; + StringName setter; + StringName getter; }; struct Constant { StringName identifier; diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index 196e328769..b20fc51a03 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -1537,7 +1537,7 @@ void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) { _GDScriptMemberSort ms; ERR_CONTINUE(!scr->member_indices.has(E->key())); - ms.index=scr->member_indices[E->key()]; + ms.index=scr->member_indices[E->key()].index; ms.name=E->key(); msort.push_back(ms); @@ -1626,9 +1626,11 @@ void GDScript::set_source_code(const String& p_code) { source=p_code; } -void GDScript::update_exports() { + +void GDScript::_update_exports(Set<PlaceHolderScriptInstance*> *p_instances) { #ifdef TOOLS_ENABLED + String basedir=path; if (basedir=="") @@ -1645,8 +1647,20 @@ void GDScript::update_exports() { const GDParser::Node* root = parser.get_parse_tree(); ERR_FAIL_COND(root->type!=GDParser::Node::TYPE_CLASS); + + const GDParser::ClassNode *c = static_cast<const GDParser::ClassNode*>(root); + if (c->extends_used && String(c->extends_file)!="") { + + Ref<GDScript> bf = ResourceLoader::load(c->extends_file); + if (bf.is_valid()) { + + bf->_update_exports(p_instances); + + } + } + List<PropertyInfo> plist; Map<StringName,Variant> default_values; @@ -1660,10 +1674,19 @@ void GDScript::update_exports() { } - for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) { + for (Set<PlaceHolderScriptInstance*>::Element *E=p_instances->front();E;E=E->next()) { E->get()->update(plist,default_values); } +#endif +} + +void GDScript::update_exports() { + +#ifdef TOOLS_ENABLED + + _update_exports(&placeholders); + #endif } @@ -1938,9 +1961,9 @@ const Map<StringName,GDFunction>& GDScript::debug_get_member_functions() const { StringName GDScript::debug_get_member_by_index(int p_idx) const { - for(const Map<StringName,int>::Element *E=member_indices.front();E;E=E->next()) { + for(const Map<StringName,MemberInfo>::Element *E=member_indices.front();E;E=E->next()) { - if (E->get()==p_idx) + if (E->get().index==p_idx) return E->key(); } @@ -1979,11 +2002,18 @@ bool GDInstance::set(const StringName& p_name, const Variant& p_value) { //member { - const Map<StringName,int>::Element *E = script->member_indices.find(p_name); + const Map<StringName,GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name); if (E) { - members[E->get()]=p_value; + members[E->get().index]=p_value; + if (E->get().setter) { + const Variant *val=&p_value; + Variant::CallError err; + call(E->get().setter,&val,1,err); + if (err.error==Variant::CallError::CALL_OK) { + return true; //function exists, call was successful + } + } return true; - } } @@ -2016,9 +2046,16 @@ bool GDInstance::get(const StringName& p_name, Variant &r_ret) const { while(sptr) { { - const Map<StringName,int>::Element *E = script->member_indices.find(p_name); + const Map<StringName,GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name); if (E) { - r_ret=members[E->get()]; + if (E->get().getter) { + Variant::CallError err; + r_ret=const_cast<GDInstance*>(this)->call(E->get().getter,NULL,0,err); + if (err.error==Variant::CallError::CALL_OK) { + return true; + } + } + r_ret=members[E->get().index]; return true; //index found } @@ -2108,7 +2145,7 @@ void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const { _GDScriptMemberSort ms; ERR_CONTINUE(!sptr->member_indices.has(E->key())); - ms.index=sptr->member_indices[E->key()]; + ms.index=sptr->member_indices[E->key()].index; ms.name=E->key(); msort.push_back(ms); @@ -2418,6 +2455,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "false" , "tool", "var", + "setget", "pass", "and", "or", diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 2088606271..3b183a41b6 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -220,11 +220,18 @@ class GDScript : public Script { bool valid; + struct MemberInfo { + int index; + StringName setter; + StringName getter; + }; friend class GDInstance; friend class GDFunction; friend class GDCompiler; friend class GDFunctions; +friend class GDScriptLanguage; + Variant _static_ref; //used for static call Ref<GDNativeClass> native; Ref<GDScript> base; @@ -234,7 +241,7 @@ friend class GDFunctions; Set<StringName> members; //members are just indices to the instanced script. Map<StringName,Variant> constants; Map<StringName,GDFunction> member_functions; - Map<StringName,int> member_indices; //members are just indices to the instanced script. + Map<StringName,MemberInfo> member_indices; //members are just indices to the instanced script. Map<StringName,Ref<GDScript> > subclasses; #ifdef TOOLS_ENABLED @@ -263,6 +270,9 @@ friend class GDFunctions; #endif + + void _update_exports(Set<PlaceHolderScriptInstance *> *p_instances); + protected: bool _get(const StringName& p_name,Variant &r_ret) const; bool _set(const StringName& p_name, const Variant& p_value); @@ -285,7 +295,7 @@ public: bool is_tool() const { return tool; } Ref<GDScript> get_base() const; - const Map<StringName,int>& debug_get_member_indices() const { return member_indices; } + const Map<StringName,MemberInfo>& debug_get_member_indices() const { return member_indices; } const Map<StringName,GDFunction>& debug_get_member_functions() const; //this is debug only StringName debug_get_member_by_index(int p_idx) const; diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index 7a1d6814ba..0fa83b9eb4 100644 --- a/modules/gdscript/gd_tokenizer.cpp +++ b/modules/gdscript/gd_tokenizer.cpp @@ -91,6 +91,7 @@ const char* GDTokenizer::token_names[TK_MAX]={ "tool", "static", "export", +"setget", "const", "var", "preload", @@ -237,7 +238,9 @@ void GDTokenizerText::_advance() { while (true) { - bool is_node_path=false; + bool is_node_path = false; + bool is_string = false; + bool is_string_alt = false; switch(GETCHAR(0)) { case 0: @@ -527,13 +530,17 @@ void GDTokenizerText::_advance() { } } break; case '@': - if (CharType(GETCHAR(1))!='"') { + if( CharType(GETCHAR(1))!='"' && CharType(GETCHAR(1))!='\'' ) { _make_error("Unexpected '@'"); return; } INCPOS(1); is_node_path=true; + + case '\'': + is_string_alt = true; case '"': { + is_string = is_string_alt ? false : true; int i=1; String str; @@ -542,8 +549,10 @@ void GDTokenizerText::_advance() { _make_error("Unterminated String"); return; - } else if (CharType(GETCHAR(i)=='"')) { + } else if( CharType(GETCHAR(i)=='"') && is_string ) { break; + } else if( CharType(GETCHAR(i)=='\'') && is_string_alt ) { + break; } else if (CharType(GETCHAR(i)=='\\')) { //escaped characters... i++; @@ -823,6 +832,7 @@ void GDTokenizerText::_advance() { {TK_PR_TOOL,"tool"}, {TK_PR_STATIC,"static"}, {TK_PR_EXPORT,"export"}, + {TK_PR_SETGET,"setget"}, {TK_PR_VAR,"var"}, {TK_PR_PRELOAD,"preload"}, {TK_PR_ASSERT,"assert"}, @@ -1007,7 +1017,7 @@ void GDTokenizerText::advance(int p_amount) { ////////////////////////////////////////////////////////////////////////////////////////////////////// -#define BYTECODE_VERSION 2 +#define BYTECODE_VERSION 3 Error GDTokenizerBuffer::set_code_buffer(const Vector<uint8_t> & p_buffer) { diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h index 1dd538867e..4f9522fb56 100644 --- a/modules/gdscript/gd_tokenizer.h +++ b/modules/gdscript/gd_tokenizer.h @@ -98,6 +98,7 @@ public: TK_PR_TOOL, TK_PR_STATIC, TK_PR_EXPORT, + TK_PR_SETGET, TK_PR_CONST, TK_PR_VAR, TK_PR_PRELOAD, diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 8b46773502..543eecdf8b 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -121,16 +121,16 @@ static void register_editor_plugin() { void register_gdscript_types() { + ObjectTypeDB::register_type<GDScript>(); + ObjectTypeDB::register_virtual_type<GDFunctionState>(); script_language_gd=memnew( GDScriptLanguage ); script_language_gd->init(); ScriptServer::register_language(script_language_gd); - ObjectTypeDB::register_type<GDScript>(); resource_loader_gd=memnew( ResourceFormatLoaderGDScript ); ResourceLoader::add_resource_format_loader(resource_loader_gd); resource_saver_gd=memnew( ResourceFormatSaverGDScript ); ResourceSaver::add_resource_format_saver(resource_saver_gd); - ObjectTypeDB::register_virtual_type<GDFunctionState>(); #ifdef TOOLS_ENABLED diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index d258e26a0e..7c10c474c3 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -1041,7 +1041,7 @@ void GridMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_clip","enabled","clipabove","floor","axis"),&GridMap::set_clip,DEFVAL(true),DEFVAL(0),DEFVAL(Vector3::AXIS_X)); - ObjectTypeDB::bind_method(_MD("crate_area","id","area"),&GridMap::create_area); + ObjectTypeDB::bind_method(_MD("create_area","id","area"),&GridMap::create_area); ObjectTypeDB::bind_method(_MD("area_get_bounds","area","bounds"),&GridMap::area_get_bounds); ObjectTypeDB::bind_method(_MD("area_set_exterior_portal","area","enable"),&GridMap::area_set_exterior_portal); ObjectTypeDB::bind_method(_MD("area_set_name","area","name"),&GridMap::area_set_name); diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index aef223470a..bcc818dac8 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -184,6 +184,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String cmdline; bool _signed; bool apk_expansion; + bool remove_prev; String apk_expansion_salt; String apk_expansion_pkey; int orientation; @@ -258,7 +259,9 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& String n=p_name; - if (n=="custom_package/debug") + if (n=="one_click_deploy/clear_previous_install") + remove_prev=p_value; + else if (n=="custom_package/debug") custom_debug_package=p_value; else if (n=="custom_package/release") custom_release_package=p_value; @@ -321,7 +324,9 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) const{ String n=p_name; - if (n=="custom_package/debug") + if (n=="one_click_deploy/clear_previous_install") + r_ret=remove_prev; + else if (n=="custom_package/debug") r_ret=custom_debug_package; else if (n=="custom_package/release") r_ret=custom_release_package; @@ -378,6 +383,7 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list) const{ + p_list->push_back( PropertyInfo( Variant::BOOL, "one_click_deploy/clear_previous_install")); p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE,"apk")); p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE,"apk")); p_list->push_back( PropertyInfo( Variant::STRING, "command_line/extra_args")); @@ -392,8 +398,9 @@ void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_normal") ); p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_large") ); p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_xlarge") ); - p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release",PROPERTY_HINT_FILE,"keystore") ); + p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release",PROPERTY_HINT_GLOBAL_FILE,"keystore") ); p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_user" ) ); + p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_password" ) ); p_list->push_back( PropertyInfo( Variant::BOOL, "apk_expansion/enable" ) ); p_list->push_back( PropertyInfo( Variant::STRING, "apk_expansion/SALT" ) ); p_list->push_back( PropertyInfo( Variant::STRING, "apk_expansion/public_key",PROPERTY_HINT_MULTILINE_TEXT ) ); @@ -1231,6 +1238,11 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d args.push_back("SHA1"); args.push_back("-sigalg"); args.push_back("MD5withRSA"); + String tsa_url=EditorSettings::get_singleton()->get("android/timestamping_authority_url"); + if (tsa_url != "") { + args.push_back("-tsa"); + args.push_back(tsa_url); + } args.push_back("-verbose"); args.push_back("-keystore"); args.push_back(keystore); @@ -1448,16 +1460,20 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) { return err; } - ep.step("Uninstalling..",1); - - print_line("Uninstalling previous version: "+devices[p_device].name); List<String> args; - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("uninstall"); - args.push_back(package); int rv; - err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv); + + if (remove_prev) { + ep.step("Uninstalling..",1); + + print_line("Uninstalling previous version: "+devices[p_device].name); + + args.push_back("-s"); + args.push_back(devices[p_device].id); + args.push_back("uninstall"); + args.push_back(package); + + err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv); #if 0 if (err || rv!=0) { EditorNode::add_io_error("Could not install to device."); @@ -1465,6 +1481,8 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) { return ERR_CANT_CREATE; } #endif + } + print_line("Installing into device (please wait..): "+devices[p_device].name); ep.step("Installing to Device (please wait..)..",2); @@ -1473,7 +1491,7 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) { args.push_back(devices[p_device].id); args.push_back("install"); args.push_back(export_to); - rv; + err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv); if (err || rv!=0) { EditorNode::add_io_error("Could not install to device."); @@ -1515,6 +1533,7 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() { device_lock = Mutex::create(); quit_request=false; orientation=0; + remove_prev=false; device_thread=Thread::create(_device_poll_thread,this); devices_changed=true; @@ -1613,6 +1632,7 @@ void register_android_exporter() { //EDITOR_DEF("android/release_keystore",""); //EDITOR_DEF("android/release_username",""); //EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/release_keystore",PROPERTY_HINT_GLOBAL_FILE,"*.keystore")); + EDITOR_DEF("android/timestamping_authority_url",""); Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>( memnew(EditorExportPlatformAndroid) ); EditorImportExport::get_singleton()->add_export_platform(exporter); diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index 96b8dcb134..c25742a854 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -120,6 +120,10 @@ def configure(env): env.Append(CPPFLAGS=['-fno-exceptions']) #env['neon_enabled']=True env['S_compiler'] = '$IPHONEPATH/Developer/usr/bin/gcc' - + + import methods + env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) + env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) + env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) # /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c-header -arch armv7s -fmessage-length=0 -std=gnu99 -fobjc-arc -Wno-trigraphs -fpascal-strings -Os -Wno-missing-field-initializers -Wno-missing-prototypes -Wreturn-type -Wno-implicit-atomic-properties -Wno-receiver-is-weak -Wduplicate-method-match -Wformat -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-shorten-64-to-32 -Wpointer-sign -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector -Wno-deprecated-implementations -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk -Wprotocol -Wdeprecated-declarations -g -fvisibility=hidden -Wno-sign-conversion "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -iquote /Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-generated-files.hmap -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-own-target-headers.hmap -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-all-target-headers.hmap -iquote /Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-project-headers.hmap -I/Users/lucasgondolo/test/build/Release-iphoneos/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/DerivedSources/armv7s -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/DerivedSources -F/Users/lucasgondolo/test/build/Release-iphoneos -DNS_BLOCK_ASSERTIONS=1 --serialize-diagnostics /var/folders/9r/_65jj9457bgb4n4nxcsm0xl80000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/test-Prefix-esrzoamhgruxcxbhemvvlrjmmvoh/test-Prefix.pch.dia -c /Users/lucasgondolo/test/test/test-Prefix.pch -o /var/folders/9r/_65jj9457bgb4n4nxcsm0xl80000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/test-Prefix-esrzoamhgruxcxbhemvvlrjmmvoh/test-Prefix.pch.pth -MMD -MT dependencies -MF /var/folders/9r/_65jj9457bgb4n4nxcsm0xl80000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/test-Prefix-esrzoamhgruxcxbhemvvlrjmmvoh/test-Prefix.pch.d diff --git a/platform/isim/SCsub b/platform/isim/SCsub index e7de935b2e..07761486a9 100644 --- a/platform/isim/SCsub +++ b/platform/isim/SCsub @@ -34,11 +34,4 @@ if env['ios_appirater'] == "yes": obj = env_ios.Object('#platform/iphone/godot_iphone.cpp') prog = None -if env["target"]=="release": - prog = env_ios.Program('#bin/godot_opt', [obj] + iphone_lib) - #action = "dsymutil "+File(prog)[0].path+" -o ../build/script_exec/build/Debug-iphoneos/script_exec.app.dSYM" - #env.AddPostAction(prog, action) -else: - prog = env_ios.Program('#bin/godot', [obj] + iphone_lib) - #action = "dsymutil "+File(prog)[0].path+" -o ../build/script_exec/build/Debug-iphoneos/script_exec.app.dSYM" - #env.AddPostAction(prog, action) +prog = env_ios.Program('#bin/godot', [obj] + iphone_lib) diff --git a/platform/isim/detect.py b/platform/isim/detect.py index c89ca81167..f4a17838f9 100644 --- a/platform/isim/detect.py +++ b/platform/isim/detect.py @@ -22,7 +22,7 @@ def get_opts(): return [ ('ISIMPLATFORM', 'name of the iphone platform', 'iPhoneSimulator'), ('ISIMPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Platforms/${ISIMPLATFORM}.platform'), - ('ISIMSDK', 'path to the iphone SDK', '$ISIMPATH/Developer/SDKs/${ISIMPLATFORM}7.0.sdk'), + ('ISIMSDK', 'path to the iphone SDK', '$ISIMPATH/Developer/SDKs/${ISIMPLATFORM}7.1.sdk'), ('game_center', 'Support for game center', 'yes'), ('store_kit', 'Support for in-app store', 'yes'), ('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'), @@ -34,9 +34,7 @@ def get_opts(): def get_flags(): return [ - ('lua', 'no'), ('tools', 'yes'), - ('nedmalloc', 'no'), ('webp', 'yes'), ] @@ -46,10 +44,6 @@ def configure(env): env.Append(CPPPATH=['#platform/iphone']) - env['OBJSUFFIX'] = ".isim.o" - env['LIBSUFFIX'] = ".isim.a" - env['PROGSUFFIX'] = ".isim" - env['ENV']['PATH'] = env['ISIMPATH']+"/Developer/usr/bin/:"+env['ENV']['PATH'] env['CC'] = '$ISIMPATH/Developer/usr/bin/gcc' @@ -83,8 +77,6 @@ def configure(env): env.Append(CCFLAGS=['-O3', '-ffast-math']) env.Append(LINKFLAGS=['-O3', '-ffast-math']) - env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX'] - env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX'] elif (env["target"]=="debug"): @@ -99,8 +91,6 @@ def configure(env): env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.6' env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate' - env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-fno-exceptions']) + env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-fexceptions']) - if env['lua'] == "yes": - env.Append(CCFLAGS=['-DLUA_USE_FLOAT']) diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 744891b8e5..16f70b60d0 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -64,6 +64,7 @@ def get_flags(): return [
('freetype','builtin'), #use builtin freetype
('openssl','builtin'), #use builtin openssl
+ ('theora','no'),
]
@@ -137,6 +138,8 @@ def configure(env): #build using mingw
if (os.name=="nt"):
env['ENV']['TMP'] = os.environ['TMP'] #way to go scons, you can be so stupid sometimes
+ else:
+ env["PROGSUFFIX"]=env["PROGSUFFIX"]+".exe"
mingw_prefix=""
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 81a96ccb13..7c2385e103 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -982,8 +982,11 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_ DEVMODE current; memset(¤t,0,sizeof(current)); EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, ¤t); + + WindowRect.right = current.dmPelsWidth; + WindowRect.bottom = current.dmPelsHeight; - DEVMODE dmScreenSettings; +/* DEVMODE dmScreenSettings; memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); dmScreenSettings.dmSize=sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = video_mode.width; @@ -995,7 +998,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_ if (err!=DISP_CHANGE_SUCCESSFUL) { video_mode.fullscreen=false; - } + }*/ } DWORD dwExStyle; diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 8616a20486..03de91fa2f 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -54,6 +54,7 @@ def get_flags(): return [ ('builtin_zlib', 'no'), ("openssl", "yes"), + ("theora","no"), ] @@ -77,6 +78,10 @@ def configure(env): if (env["use_sanitizer"]=="yes"): env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer']) env.Append(LINKFLAGS=['-fsanitize=address']) + env.extra_suffix=".llvms" + else: + env.extra_suffix=".llvm" + diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index ded86702ef..819b06e095 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -507,7 +507,13 @@ void Particles2D::_notification(int p_what) { } - for(int i=0;i<particle_count;i++) { + int start_particle = (int)(time * (float)particle_count / lifetime); + + for (int id=0;id<particle_count;++id) { + int i = start_particle + id; + if (i >= particle_count) { + i -= particle_count; + } Particle &p=pdata[i]; if (!p.active) diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 7678cb980c..308aa8402f 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -925,6 +925,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { normal=rest_info.normal; collider=rest_info.collider_id; collider_vel=rest_info.linear_velocity; + collider_shape=rest_info.shape; + collider_metadata=rest_info.metadata; } } @@ -1013,6 +1015,20 @@ ObjectID KinematicBody2D::get_collider() const { return collider; } + +int KinematicBody2D::get_collider_shape() const { + + ERR_FAIL_COND_V(!colliding,0); + return collider_shape; +} + +Variant KinematicBody2D::get_collider_metadata() const { + + ERR_FAIL_COND_V(!colliding,0); + return collider_metadata; + +} + void KinematicBody2D::set_collide_with_static_bodies(bool p_enable) { collide_static=p_enable; @@ -1076,6 +1092,8 @@ void KinematicBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_collision_normal"),&KinematicBody2D::get_collision_normal); ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&KinematicBody2D::get_collider_velocity); ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody2D::_get_collider); + ObjectTypeDB::bind_method(_MD("get_collider_shape"),&KinematicBody2D::get_collider_shape); + ObjectTypeDB::bind_method(_MD("get_collider_metadata"),&KinematicBody2D::get_collider_metadata); ObjectTypeDB::bind_method(_MD("set_collide_with_static_bodies","enable"),&KinematicBody2D::set_collide_with_static_bodies); @@ -1112,6 +1130,8 @@ KinematicBody2D::KinematicBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_KI colliding=false; collider=0; + collider_shape=0; + margin=0.08; } KinematicBody2D::~KinematicBody2D() { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index b2625c3d97..e429ca1432 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -254,7 +254,8 @@ class KinematicBody2D : public PhysicsBody2D { Vector2 normal; Vector2 collider_vel; ObjectID collider; - + int collider_shape; + Variant collider_metadata; Variant _get_collider() const; @@ -273,6 +274,8 @@ public: Vector2 get_collision_normal() const; Vector2 get_collider_velocity() const; ObjectID get_collider() const; + int get_collider_shape() const; + Variant get_collider_metadata() const; void set_collide_with_static_bodies(bool p_enable); bool can_collide_with_static_bodies() const; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 7d033ed87f..8c3bbfdfc9 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -64,20 +64,20 @@ void Sprite::_notification(int p_what) { break; */ - Size2i s; - Rect2i src_rect; + Size2 s; + Rect2 src_rect; if (region) { s=region_rect.size; src_rect=region_rect; } else { - s = texture->get_size(); - s=s/Size2i(hframes,vframes); + s = Size2(texture->get_size()); + s=s/Size2(hframes,vframes); src_rect.size=s; - src_rect.pos.x+=(frame%hframes)*s.x; - src_rect.pos.y+=(frame/hframes)*s.y; + src_rect.pos.x+=float(frame%hframes)*s.x; + src_rect.pos.y+=float(frame/hframes)*s.y; } @@ -85,7 +85,7 @@ void Sprite::_notification(int p_what) { if (centered) ofs-=s/2; - Rect2i dst_rect(ofs,s); + Rect2 dst_rect(ofs,s); if (hflip) dst_rect.size.x=-dst_rect.size.x; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 72ef653d14..eb04ca924f 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -179,6 +179,7 @@ void TileMap::_update_dirty_quadrants() { vs->canvas_item_clear(q.canvas_item); ps->body_clear_shapes(q.static_body); + int shape_idx=0; for(int i=0;i<q.cells.size();i++) { @@ -259,6 +260,8 @@ void TileMap::_update_dirty_quadrants() { ps->body_add_shape(q.static_body,shape->get_rid(),xform); + ps->body_set_shape_metadata(q.static_body,shape_idx++,Vector2(E->key().x,E->key().y)); + } } } diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp index c1cc1f6b68..b55093a779 100644 --- a/scene/3d/baked_light_instance.cpp +++ b/scene/3d/baked_light_instance.cpp @@ -63,3 +63,81 @@ BakedLightInstance::BakedLightInstance() { } +///////////////////////// + + +void BakedLightSampler::set_param(Param p_param,float p_value) { + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params[p_param]=p_value; + VS::get_singleton()->baked_light_sampler_set_param(base,VS::BakedLightSamplerParam(p_param),p_value); +} + +float BakedLightSampler::get_param(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params[p_param]; + +} + +void BakedLightSampler::set_resolution(int p_resolution){ + + ERR_FAIL_COND(p_resolution<4 && p_resolution>32); + resolution=p_resolution; + VS::get_singleton()->baked_light_sampler_set_resolution(base,resolution); +} +int BakedLightSampler::get_resolution() const { + + return resolution; +} + +AABB BakedLightSampler::get_aabb() const { + + float r = get_param(PARAM_RADIUS); + return AABB( Vector3(-r,-r,-r),Vector3(r*2,r*2,r*2)); +} +DVector<Face3> BakedLightSampler::get_faces(uint32_t p_usage_flags) const { + return DVector<Face3>(); +} + +void BakedLightSampler::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_param","param","value"),&BakedLightSampler::set_param); + ObjectTypeDB::bind_method(_MD("get_param","param"),&BakedLightSampler::get_param); + + ObjectTypeDB::bind_method(_MD("set_resolution","resolution"),&BakedLightSampler::set_resolution); + ObjectTypeDB::bind_method(_MD("get_resolution"),&BakedLightSampler::get_resolution); + + + BIND_CONSTANT( PARAM_RADIUS ); + BIND_CONSTANT( PARAM_STRENGTH ); + BIND_CONSTANT( PARAM_ATTENUATION ); + BIND_CONSTANT( PARAM_DETAIL_RATIO ); + BIND_CONSTANT( PARAM_MAX ); + + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_RADIUS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/strength",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_STRENGTH); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/attenuation",PROPERTY_HINT_EXP_EASING),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0.01,1.0,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO); +// ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0,20,1"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/resolution",PROPERTY_HINT_RANGE,"4,32,1"),_SCS("set_resolution"),_SCS("get_resolution")); + +} + +BakedLightSampler::BakedLightSampler() { + + base = VS::get_singleton()->baked_light_sampler_create(); + set_base(base); + + params[PARAM_RADIUS]=1.0; + params[PARAM_STRENGTH]=1.0; + params[PARAM_ATTENUATION]=1.0; + params[PARAM_DETAIL_RATIO]=0.1; + resolution=16; + + +} + +BakedLightSampler::~BakedLightSampler(){ + + VS::get_singleton()->free(base); +} diff --git a/scene/3d/baked_light_instance.h b/scene/3d/baked_light_instance.h index b904ced9a7..0694c813ce 100644 --- a/scene/3d/baked_light_instance.h +++ b/scene/3d/baked_light_instance.h @@ -30,4 +30,46 @@ public: BakedLightInstance(); }; + + +class BakedLightSampler : public VisualInstance { + OBJ_TYPE(BakedLightSampler,VisualInstance); + + +public: + + enum Param { + PARAM_RADIUS=VS::BAKED_LIGHT_SAMPLER_RADIUS, + PARAM_STRENGTH=VS::BAKED_LIGHT_SAMPLER_STRENGTH, + PARAM_ATTENUATION=VS::BAKED_LIGHT_SAMPLER_ATTENUATION, + PARAM_DETAIL_RATIO=VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO, + PARAM_MAX=VS::BAKED_LIGHT_SAMPLER_MAX + }; + + + +protected: + + RID base; + float params[PARAM_MAX]; + int resolution; + static void _bind_methods(); +public: + + virtual AABB get_aabb() const; + virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; + + void set_param(Param p_param,float p_value); + float get_param(Param p_param) const; + + void set_resolution(int p_resolution); + int get_resolution() const; + + BakedLightSampler(); + ~BakedLightSampler(); +}; + +VARIANT_ENUM_CAST( BakedLightSampler::Param ); + + #endif // BAKED_LIGHT_H diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index c85ad70c63..ab28c0c8d4 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -219,11 +219,14 @@ void Camera::_notification(int p_what) { } + camera_group = "_vp_cameras"+itos(get_viewport()->get_instance_ID()); + add_to_group(camera_group); if (viewport_ptr) viewport_ptr->cameras.insert(this); if (current) make_current(); + } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -241,6 +244,8 @@ void Camera::_notification(int p_what) { if (viewport_ptr) viewport_ptr->cameras.erase(this); viewport_ptr=NULL; + remove_from_group(camera_group); + } break; case NOTIFICATION_BECAME_CURRENT: { @@ -314,6 +319,20 @@ void Camera::make_current() { //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this); } + +void Camera::_camera_make_next_current(Node *p_exclude) { + + if (this==p_exclude) + return; + if (!is_inside_scene()) + return; + if (get_viewport()->get_camera()!=NULL) + return; + + make_current(); +} + + void Camera::clear_current() { current=false; @@ -321,8 +340,12 @@ void Camera::clear_current() { return; if (viewport_ptr) { - if (viewport_ptr->get_camera()==this) + if (viewport_ptr->get_camera()==this) { viewport_ptr->_set_camera(NULL); + //a group is used beause this needs to be in order to be deterministic + get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_next_current",this); + + } } } @@ -444,7 +467,15 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); } + +#if 0 Size2 viewport_size = viewport_ptr->get_visible_rect().size; + Vector2 cpos = p_pos; +#else + + Size2 viewport_size = viewport_ptr->get_camera_rect_size(); + Vector2 cpos = viewport_ptr->get_camera_coords(p_pos); +#endif Vector3 ray; @@ -456,10 +487,9 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); float screen_w,screen_h; cm.get_viewport_size(screen_w,screen_h); - ray=Vector3( ((p_pos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(p_pos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); + ray=Vector3( ((cpos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(cpos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); } - return ray; }; @@ -471,8 +501,14 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); } +#if 0 Size2 viewport_size = viewport_ptr->get_visible_rect().size; + Vector2 cpos = p_pos; +#else + Size2 viewport_size = viewport_ptr->get_camera_rect_size(); + Vector2 cpos = viewport_ptr->get_camera_coords(p_pos); +#endif ERR_FAIL_COND_V( viewport_size.y == 0, Vector3() ); // float aspect = viewport_size.x / viewport_size.y; @@ -482,7 +518,7 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { return get_camera_transform().origin; } else { - Vector2 pos = p_pos / viewport_size; + Vector2 pos = cpos / viewport_size; float vsize,hsize; if (keep_aspect==KEEP_WIDTH) { vsize = size/viewport_size.get_aspect(); @@ -636,6 +672,7 @@ void Camera::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment); ObjectTypeDB::bind_method(_MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode); ObjectTypeDB::bind_method(_MD("get_keep_aspect_mode"),&Camera::get_keep_aspect_mode); + ObjectTypeDB::bind_method(_MD("_camera_make_next_current"),&Camera::_camera_make_next_current); //ObjectTypeDB::bind_method( _MD("_camera_make_current"),&Camera::_camera_make_current ); BIND_CONSTANT( PROJECTION_PERSPECTIVE ); @@ -732,7 +769,8 @@ Camera::Camera() { mode=PROJECTION_PERSPECTIVE; set_perspective(60.0,0.1,100.0); keep_aspect=KEEP_HEIGHT; - layers=0xFFFFFFFF; + layers=0xfffff; + VisualServer::get_singleton()->camera_set_visible_layers(camera,layers); //active=false; } diff --git a/scene/3d/camera.h b/scene/3d/camera.h index 014c7cb520..bac8173bb7 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -66,6 +66,8 @@ private: RID camera; RID scenario_id; + String camera_group; + uint32_t layers; Viewport *viewport_ptr; @@ -74,6 +76,7 @@ private: virtual bool _can_gizmo_scale() const; virtual RES _get_gizmo_geometry() const; + void _camera_make_next_current(Node *p_exclude); //void _camera_make_current(Node *p_camera); diff --git a/scene/3d/follow_camera.cpp b/scene/3d/follow_camera.cpp deleted file mode 100644 index e7ced6c2ba..0000000000 --- a/scene/3d/follow_camera.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/*************************************************************************/ -/* follow_camera.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "follow_camera.h" - - -#include "physics_body.h" -#include "scene/resources/surface_tool.h" - -void FollowCamera::_set_initial_orbit(const Vector2& p_orbit) { - - initial_orbit=p_orbit; - set_orbit(p_orbit); -} - - - -void FollowCamera::_clear_queries() { - - if (!queries_active) - return; -#if 0 - for(int i=0;i<3;i++) - PhysicsServer::get_singleton()->query_clear(clip_ray[i].query); -#endif - queries_active=false; - -} - -void FollowCamera::_compute_camera() { - - // update the transform with the next proposed transform (camera is 1 logic frame delayed) - - /* - float time = get_root_node()->get_frame_time(); - Vector3 oldp = accepted.get_origin(); - Vector3 newp = proposed.get_origin(); - - float frame_dist = time * - if (oldp.distance_to(newp) > - */ - - float time = get_process_delta_time(); - bool noblend=false; - - if (clip) { - - if ((clip_ray[0].clipped==clip_ray[2].clipped || fullclip) && clip_ray[1].clipped) { - //all have been clipped - proposed_pos=clip_ray[1].clip_pos-extraclip*(proposed_pos-target_pos).normalized(); - if (clip_ray[0].clipped) - fullclip=true; - noblend=true; - - - } else { - - - //Vector3 rel=follow_pos-target_pos; - - if (clip_ray[0].clipped && !clip_ray[2].clipped) { - - float distance = target_pos.distance_to(clip_ray[0].clip_pos); - real_t amount = 1.0-(distance/clip_len); - amount = CLAMP(amount,0,1)*autoturn_speed*time; - if (clip_ray[1].clipped) - amount*=2.0; - //rotate_rel=Matrix3(Vector3(0,1,0),amount).xform(rel); - rotate_orbit(Vector2(0,amount)); - - } else if (clip_ray[2].clipped && !clip_ray[0].clipped) { - - float distance = target_pos.distance_to(clip_ray[2].clip_pos); - real_t amount = 1.0-(distance/clip_len); - amount = CLAMP(amount,0,1)*autoturn_speed*time; - if (clip_ray[1].clipped) - amount*=2.0; - rotate_orbit(Vector2(0,-amount)); - } - - fullclip=false; - - } - } - - - Vector3 base_pos = get_global_transform().origin; - Vector3 pull_from = base_pos; - pull_from.y+=height; // height compensate - - - - Vector3 camera_target; - if (use_lookat_target) { - - camera_target = lookat_target; - } else { - camera_target = base_pos; - }; - - Transform proposed; - proposed.set_look_at(proposed_pos,camera_target,up_vector); - proposed = proposed * Transform(Matrix3(Vector3(1,0,0),Math::deg2rad(inclination)),Vector3()); //inclination - - - accepted=proposed; - if (smooth && !noblend) { - - - Vector3 vec1 = accepted.origin; - Vector3 vec2 = final.origin; - final.origin = vec2.linear_interpolate(vec1, MIN(1,smooth_pos_ratio * time));; - - Quat q1 = accepted.basis; - Quat q2 = final.basis; - final.basis = q2.slerp(q1, MIN(1,smooth_rot_ratio * time)); - - } else { - final=accepted; - } - - _update_camera(); - - // calculate the next proposed transform - - - Vector3 new_pos; - - { /*follow code*/ - - - - /* calculate some variables */ - - Vector3 rel = follow_pos - pull_from; - - float l = rel.length(); - Vector3 rel_n = (l > 0) ? (rel/l) : Vector3(); - float ang = Math::acos(rel_n.dot( Vector3(0,1,0) )); - - Vector3 tangent = rel_n; - tangent.y=0; // get rid of y - if (tangent.length_squared() < CMP_EPSILON2) - tangent=Vector3(0,0,1); // use Z as tangent if rel is parallel to y - else - tangent.normalize(); - - /* now start applying the rules */ - - //clip distance - if (l > max_distance) - l=max_distance; - if (l < min_distance) - l=min_distance; - - //fix angle - - float ang_min = Math_PI * 0.5 + Math::deg2rad(min_orbit_x); - float ang_max = Math_PI * 0.5 + Math::deg2rad(max_orbit_x); - - if (ang<ang_min) - ang=ang_min; - if (ang>ang_max) - ang=ang_max; - - /* finally, rebuild the validated camera position */ - - new_pos=Vector3(0,Math::cos(ang),0); - new_pos+=tangent*Math::sin(ang); - new_pos*=l; - new_pos+=pull_from; - follow_pos=new_pos; - - } - - proposed_pos=new_pos; - - Vector3 rel = new_pos-camera_target; - - - if (clip) { - - Vector<RID> exclude; - exclude.push_back(target_body); - - for(int i=0;i<3;i++) { - - clip_ray[i].clipped=false; - clip_ray[i].clip_pos=Vector3(); - clip_ray[i].cast_pos=camera_target; - - Vector3 cast_to = camera_target+Matrix3(Vector3(0,1,0),Math::deg2rad(autoturn_tolerance*(i-1.0))).xform(rel); - - - if (i!=1) { - - Vector3 side = rel.cross(Vector3(0,1,0)).normalized()*(i-1.0); - clip_ray[i].cast_pos+side*target_width+rel.normalized()*target_width; - - Vector3 d = -rel; - d.rotate(Vector3(0,1,0),Math::deg2rad(get_fov())*(i-1.0)); - Plane p(new_pos,new_pos+d,new_pos+Vector3(0,1,0)); //fov clipping plane, build a face and use it as plane, facing doesn't matter - Vector3 intersect; - if (p.intersects_segment(clip_ray[i].cast_pos,cast_to,&intersect)) - cast_to=intersect; - - } else { - - cast_to+=rel.normalized()*extraclip; - } - - // PhysicsServer::get_singleton()->query_intersection(clip_ray[i].query,get_world()->get_space(),exclude); - // PhysicsServer::get_singleton()->query_intersection_segment(clip_ray[i].query,clip_ray[i].cast_pos,cast_to); - - - - - } - - queries_active=true; - } else { - - _clear_queries(); - } - target_pos=camera_target; - clip_len=rel.length(); - -} - -void FollowCamera::set_use_lookat_target(bool p_use, const Vector3 &p_lookat) { - - use_lookat_target = p_use; - lookat_target = p_lookat; -}; - - -void FollowCamera::_notification(int p_what) { - - switch(p_what) { - - case NOTIFICATION_PROCESS: { - - - _compute_camera(); - } break; - - case NOTIFICATION_ENTER_WORLD: { - - set_orbit(orbit); - set_distance(distance); - - accepted=final=get_global_transform(); - proposed_pos=accepted.origin; - - target_body = RID(); -/* - Node* parent = get_parent(); - while (parent) { - PhysicsBody* p = parent->cast_to<PhysicsBody>(); - if (p) { - target_body = p->get_body(); - break; - }; - parent = parent->get_parent(); - }; -*/ - set_process(true); - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - } break; - case NOTIFICATION_EXIT_WORLD: { - - distance=get_distance(); - orbit=get_orbit(); - _clear_queries(); - - } break; - case NOTIFICATION_BECAME_CURRENT: { - - set_process(true); - } break; - case NOTIFICATION_LOST_CURRENT: { - - set_process(false); - _clear_queries(); - - } break; - } - -} - - - -void FollowCamera::set_orbit(const Vector2& p_orbit) { - - orbit=p_orbit; - - if(is_inside_scene()) { - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - float d = char_pos.distance_to(follow_pos); - - Matrix3 m; - m.rotate(Vector3(0,1,0),orbit.y); - m.rotate(Vector3(1,0,0),orbit.x); - - follow_pos=char_pos + m.get_axis(2) * d; - - } - - update_gizmo(); - -} -void FollowCamera::set_orbit_x(float p_x) { - - orbit.x=p_x; - if(is_inside_scene()) - set_orbit(Vector2( p_x, get_orbit().y )); -} -void FollowCamera::set_orbit_y(float p_y) { - - - orbit.y=p_y; - if(is_inside_scene()) - set_orbit(Vector2( get_orbit().x, p_y )); - -} -Vector2 FollowCamera::get_orbit() const { - - - if (is_inside_scene()) { - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - Vector3 rel = (follow_pos - char_pos).normalized(); - Vector2 ret_orbit; - ret_orbit.x = Math::acos( Vector3(0,1,0).dot( rel ) ) - Math_PI * 0.5; - ret_orbit.y = Math::atan2(rel.x,rel.z); - return ret_orbit; - } - return orbit; -} - -void FollowCamera::rotate_orbit(const Vector2& p_relative) { - - if (is_inside_scene()) { - - Matrix3 m; - m.rotate(Vector3(0,1,0),Math::deg2rad(p_relative.y)); - m.rotate(Vector3(1,0,0),Math::deg2rad(p_relative.x)); - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - Vector3 rel = (follow_pos - char_pos); - rel = m.xform(rel); - follow_pos=char_pos+rel; - - } - - orbit+=p_relative; - update_gizmo(); -} - -void FollowCamera::set_height(float p_height) { - - - height=p_height; - update_gizmo(); -} - -float FollowCamera::get_height() const { - - return height; - -} - -void FollowCamera::set_max_orbit_x(float p_max) { - - max_orbit_x=p_max; - update_gizmo(); -} - -float FollowCamera::get_max_orbit_x() const { - - return max_orbit_x; -} - -void FollowCamera::set_min_orbit_x(float p_min) { - - min_orbit_x=p_min; - update_gizmo(); -} - -float FollowCamera::get_min_orbit_x() const { - - return min_orbit_x; -} - -float FollowCamera::get_min_distance() const { - - return min_distance; -} -float FollowCamera::get_max_distance() const { - - return max_distance; -} - -void FollowCamera::set_min_distance(float p_min) { - - min_distance=p_min; - update_gizmo(); -} - -void FollowCamera::set_max_distance(float p_max) { - - max_distance = p_max; - update_gizmo(); -} - - -void FollowCamera::set_distance(float p_distance) { - - if (is_inside_scene()) { - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - Vector3 rel = (follow_pos - char_pos).normalized(); - rel*=p_distance; - follow_pos=char_pos+rel; - - } - - distance=p_distance; -} - -float FollowCamera::get_distance() const { - - if (is_inside_scene()) { - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - return (follow_pos - char_pos).length(); - - } - - return distance; -} - -void FollowCamera::set_clip(bool p_enabled) { - - - clip=p_enabled; - - if (!p_enabled) - _clear_queries(); -} - -bool FollowCamera::has_clip() const { - - return clip; - -} - - -void FollowCamera::set_autoturn(bool p_enabled) { - - - autoturn=p_enabled; -} - -bool FollowCamera::has_autoturn() const { - - return autoturn; - -} - -void FollowCamera::set_autoturn_tolerance(float p_degrees) { - - - autoturn_tolerance=p_degrees; -} -float FollowCamera::get_autoturn_tolerance() const { - - - return autoturn_tolerance; -} - -void FollowCamera::set_inclination(float p_degrees) { - - - inclination=p_degrees; -} -float FollowCamera::get_inclination() const { - - - return inclination; -} - - -void FollowCamera::set_autoturn_speed(float p_speed) { - - - autoturn_speed=p_speed; -} - -float FollowCamera::get_autoturn_speed() const { - - return autoturn_speed; - -} - - -RES FollowCamera::_get_gizmo_geometry() const { - - Ref<SurfaceTool> surface_tool( memnew( SurfaceTool )); - - Ref<FixedMaterial> mat( memnew( FixedMaterial )); - - mat->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(1.0,0.5,1.0,0.3) ); - mat->set_line_width(4); - mat->set_flag(Material::FLAG_DOUBLE_SIDED,true); - mat->set_flag(Material::FLAG_UNSHADED,true); -// mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true); - - surface_tool->begin(Mesh::PRIMITIVE_LINES); - surface_tool->set_material(mat); - - - int steps=16; - - Vector3 base_up = Matrix3(Vector3(1,0,0),Math::deg2rad(max_orbit_x)).get_axis(2); - Vector3 base_down = Matrix3(Vector3(1,0,0),Math::deg2rad(min_orbit_x)).get_axis(2); - - Vector3 ofs(0,height,0); - - for(int i=0;i<steps;i++) { - - - Matrix3 rot(Vector3(0,1,0),Math_PI*2*float(i)/steps); - Matrix3 rot2(Vector3(0,1,0),Math_PI*2*float(i+1)/steps); - - Vector3 up = rot.xform(base_up); - Vector3 up2 = rot2.xform(base_up); - - Vector3 down = rot.xform(base_down); - Vector3 down2 = rot2.xform(base_down); - - surface_tool->add_vertex(ofs+up*min_distance); - surface_tool->add_vertex(ofs+up*max_distance); - surface_tool->add_vertex(ofs+up*min_distance); - surface_tool->add_vertex(ofs+up2*min_distance); - surface_tool->add_vertex(ofs+up*max_distance); - surface_tool->add_vertex(ofs+up2*max_distance); - - surface_tool->add_vertex(ofs+down*min_distance); - surface_tool->add_vertex(ofs+down*max_distance); - surface_tool->add_vertex(ofs+down*min_distance); - surface_tool->add_vertex(ofs+down2*min_distance); - surface_tool->add_vertex(ofs+down*max_distance); - surface_tool->add_vertex(ofs+down2*max_distance); - - int substeps = 8; - - for(int j=0;j<substeps;j++) { - - Vector3 a = up.linear_interpolate(down,float(j)/substeps).normalized()*max_distance; - Vector3 b = up.linear_interpolate(down,float(j+1)/substeps).normalized()*max_distance; - Vector3 am = up.linear_interpolate(down,float(j)/substeps).normalized()*min_distance; - Vector3 bm = up.linear_interpolate(down,float(j+1)/substeps).normalized()*min_distance; - - surface_tool->add_vertex(ofs+a); - surface_tool->add_vertex(ofs+b); - surface_tool->add_vertex(ofs+am); - surface_tool->add_vertex(ofs+bm); - - } - } - - - return surface_tool->commit(); - - -} - - -void FollowCamera::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("_set_initial_orbit","orbit"),&FollowCamera::_set_initial_orbit); - ObjectTypeDB::bind_method(_MD("set_orbit","orbit"),&FollowCamera::set_orbit); - ObjectTypeDB::bind_method(_MD("get_orbit"),&FollowCamera::get_orbit); - ObjectTypeDB::bind_method(_MD("set_orbit_x","x"),&FollowCamera::set_orbit_x); - ObjectTypeDB::bind_method(_MD("set_orbit_y","y"),&FollowCamera::set_orbit_y); - ObjectTypeDB::bind_method(_MD("set_min_orbit_x","x"),&FollowCamera::set_min_orbit_x); - ObjectTypeDB::bind_method(_MD("get_min_orbit_x"),&FollowCamera::get_min_orbit_x); - ObjectTypeDB::bind_method(_MD("set_max_orbit_x","x"),&FollowCamera::set_max_orbit_x); - ObjectTypeDB::bind_method(_MD("get_max_orbit_x"),&FollowCamera::get_max_orbit_x); - ObjectTypeDB::bind_method(_MD("set_height","height"),&FollowCamera::set_height); - ObjectTypeDB::bind_method(_MD("get_height"),&FollowCamera::get_height); - ObjectTypeDB::bind_method(_MD("set_inclination","inclination"),&FollowCamera::set_inclination); - ObjectTypeDB::bind_method(_MD("get_inclination"),&FollowCamera::get_inclination); - - ObjectTypeDB::bind_method(_MD("rotate_orbit"),&FollowCamera::rotate_orbit); - ObjectTypeDB::bind_method(_MD("set_distance","distance"),&FollowCamera::set_distance); - ObjectTypeDB::bind_method(_MD("get_distance"),&FollowCamera::get_distance); - ObjectTypeDB::bind_method(_MD("set_max_distance","max_distance"),&FollowCamera::set_max_distance); - ObjectTypeDB::bind_method(_MD("get_max_distance"),&FollowCamera::get_max_distance); - ObjectTypeDB::bind_method(_MD("set_min_distance","min_distance"),&FollowCamera::set_min_distance); - ObjectTypeDB::bind_method(_MD("get_min_distance"),&FollowCamera::get_min_distance); - ObjectTypeDB::bind_method(_MD("set_clip","enable"),&FollowCamera::set_clip); - ObjectTypeDB::bind_method(_MD("has_clip"),&FollowCamera::has_clip); - ObjectTypeDB::bind_method(_MD("set_autoturn","enable"),&FollowCamera::set_autoturn); - ObjectTypeDB::bind_method(_MD("has_autoturn"),&FollowCamera::has_autoturn); - ObjectTypeDB::bind_method(_MD("set_autoturn_tolerance","degrees"),&FollowCamera::set_autoturn_tolerance); - ObjectTypeDB::bind_method(_MD("get_autoturn_tolerance"),&FollowCamera::get_autoturn_tolerance); - ObjectTypeDB::bind_method(_MD("set_autoturn_speed","speed"),&FollowCamera::set_autoturn_speed); - ObjectTypeDB::bind_method(_MD("get_autoturn_speed"),&FollowCamera::get_autoturn_speed); - ObjectTypeDB::bind_method(_MD("set_smoothing","enable"),&FollowCamera::set_smoothing); - ObjectTypeDB::bind_method(_MD("has_smoothing"),&FollowCamera::has_smoothing); - ObjectTypeDB::bind_method(_MD("set_rotation_smoothing","amount"),&FollowCamera::set_rotation_smoothing); - ObjectTypeDB::bind_method(_MD("get_rotation_smoothing"),&FollowCamera::get_rotation_smoothing); - ObjectTypeDB::bind_method(_MD("set_translation_smoothing","amount"),&FollowCamera::set_translation_smoothing); - ObjectTypeDB::bind_method(_MD("get_translation_smoothing"),&FollowCamera::get_translation_smoothing); - ObjectTypeDB::bind_method(_MD("set_use_lookat_target","use","lookat"),&FollowCamera::set_use_lookat_target, DEFVAL(Vector3())); - ObjectTypeDB::bind_method(_MD("set_up_vector","vector"),&FollowCamera::set_up_vector); - ObjectTypeDB::bind_method(_MD("get_up_vector"),&FollowCamera::get_up_vector); - - ObjectTypeDB::bind_method(_MD("_ray_collision"),&FollowCamera::_ray_collision); - - ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "orbit" ), _SCS("_set_initial_orbit"),_SCS("get_orbit") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "height", PROPERTY_HINT_RANGE,"-1024,1024,0.01" ), _SCS("set_height"), _SCS("get_height") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "inclination", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_inclination"), _SCS("get_inclination") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_max_orbit_x"), _SCS("get_max_orbit_x") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_min_orbit_x"), _SCS("get_min_orbit_x") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ), _SCS("set_min_distance"), _SCS("get_min_distance") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ), _SCS("set_max_distance"), _SCS("get_max_distance") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "distance", PROPERTY_HINT_RANGE,"0.01,1024,0,01"), _SCS("set_distance"), _SCS("get_distance") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "clip"), _SCS("set_clip"), _SCS("has_clip") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "autoturn"), _SCS("set_autoturn"), _SCS("has_autoturn") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "autoturn_tolerance", PROPERTY_HINT_RANGE,"1,90,0.01") , _SCS("set_autoturn_tolerance"), _SCS("get_autoturn_tolerance") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "autoturn_speed", PROPERTY_HINT_RANGE,"1,90,0.01"), _SCS("set_autoturn_speed"), _SCS("get_autoturn_speed") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "smoothing"), _SCS("set_smoothing"), _SCS("has_smoothing") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "translation_smooth", PROPERTY_HINT_RANGE,"0.01,128,0.01"), _SCS("set_translation_smoothing"), _SCS("get_translation_smoothing") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "rotation_smooth", PROPERTY_HINT_RANGE,"0.01,128,0.01"), _SCS("set_rotation_smoothing"), _SCS("get_rotation_smoothing") ); - - -} - -void FollowCamera::_ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx) { - - clip_ray[p_idx].clip_pos=p_point; - clip_ray[p_idx].clipped=true; - -}; - -Transform FollowCamera::get_camera_transform() const { - - return final; -} - -void FollowCamera::set_smoothing(bool p_enable) { - - smooth=p_enable; -} - -bool FollowCamera::has_smoothing() const { - - return smooth; -} - -void FollowCamera::set_translation_smoothing(float p_amount) { - - smooth_pos_ratio=p_amount; -} -float FollowCamera::get_translation_smoothing() const { - - return smooth_pos_ratio; -} - -void FollowCamera::set_rotation_smoothing(float p_amount) { - - smooth_rot_ratio=p_amount; - -} - -void FollowCamera::set_up_vector(const Vector3& p_up) { - - up_vector=p_up; -} - -Vector3 FollowCamera::get_up_vector() const{ - - return up_vector; -} - -float FollowCamera::get_rotation_smoothing() const { - - return smooth_pos_ratio; - -} - - -FollowCamera::FollowCamera() { - - - height=1; - - orbit=Vector2(0,0); - up_vector=Vector3(0,1,0); - - distance=3; - min_distance=2; - max_distance=5; - - autoturn=true; - autoturn_tolerance=10; - autoturn_speed=80; - - min_orbit_x=-50; - max_orbit_x=70; - inclination=0; - target_width=0.3; - - clip=true; - use_lookat_target = false; - extraclip=0.3; - fullclip=false; - - smooth=true; - smooth_rot_ratio=10; - smooth_pos_ratio=10; - - - for(int i=0;i<3;i++) { -// clip_ray[i].query=PhysicsServer::get_singleton()->query_create(this, "_ray_collision", i, true); - clip_ray[i].clipped=false; - } - - queries_active=false; - - -} - -FollowCamera::~FollowCamera() { - - for(int i=0;i<3;i++) { - PhysicsServer::get_singleton()->free(clip_ray[i].query); - } - - -} diff --git a/scene/3d/follow_camera.h b/scene/3d/follow_camera.h deleted file mode 100644 index 10912eb606..0000000000 --- a/scene/3d/follow_camera.h +++ /dev/null @@ -1,180 +0,0 @@ -/*************************************************************************/ -/* follow_camera.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef FOLLOW_CAMERA_H -#define FOLLOW_CAMERA_H - -#include "scene/3d/camera.h" - -class FollowCamera : public Camera { - - OBJ_TYPE( FollowCamera, Camera ); - -private: - - - //used for follow - Vector3 follow_pos; - //used for fixed - Vector2 initial_orbit; - Vector2 orbit; - float distance; - - float height; - float target_width; - - float min_distance; - float max_distance; - - float max_orbit_x; - float min_orbit_x; - - float inclination; - float extraclip; - bool fullclip; - - bool clip; - bool autoturn; - float autoturn_tolerance; - float autoturn_speed; - - bool smooth; - float smooth_rot_ratio; - float smooth_pos_ratio; - - - - struct ClipRay { - RID query; - bool clipped; - Vector3 cast_pos; - Vector3 clip_pos; - }; - - ClipRay clip_ray[3]; - Vector3 target_pos; - float clip_len; - - Vector3 up_vector; - - - virtual RES _get_gizmo_geometry() const; - - Transform ted; - Vector3 proposed_pos; - Transform accepted; - Transform final; - RID target_body; - - bool use_lookat_target; - Vector3 lookat_target; - - void _compute_camera(); - - bool queries_active; - void _clear_queries(); - - void _set_initial_orbit(const Vector2& p_orbit); - -protected: - - virtual void _request_camera_update() {} //ignore - - void _notification(int p_what); - - static void _bind_methods(); - - void _ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx); - -public: - - - void set_orbit(const Vector2& p_orbit); - void set_orbit_x(float p_x); - void set_orbit_y(float p_y); - Vector2 get_orbit() const; - - void set_height(float p_height); - float get_height() const; - - void set_inclination(float p_degrees); - float get_inclination() const; - - void set_max_orbit_x(float p_max); - float get_max_orbit_x() const; - - void set_min_orbit_x(float p_min); - float get_min_orbit_x() const; - - void rotate_orbit(const Vector2& p_relative); - - void set_distance(float p_distance); - float get_distance() const; - - float get_min_distance() const; - float get_max_distance() const; - void set_min_distance(float p_min); - void set_max_distance(float p_max); - - /** FINISH THIS AND CLEAN IT UP */ - - void set_clip(bool p_enabled); - bool has_clip() const; - - void set_autoturn(bool p_enabled); - bool has_autoturn() const; - - void set_autoturn_tolerance(float p_degrees); - float get_autoturn_tolerance() const; - - void set_autoturn_speed(float p_speed); - float get_autoturn_speed() const; - - void set_smoothing(bool p_enable); - bool has_smoothing() const; - - void set_translation_smoothing(float p_amount); - float get_translation_smoothing() const; - - void set_rotation_smoothing(float p_amount); - float get_rotation_smoothing() const; - - void set_use_lookat_target(bool p_use, const Vector3 &p_lookat = Vector3()); - - void set_up_vector(const Vector3& p_up); - Vector3 get_up_vector() const; - - virtual Transform get_camera_transform() const; - - FollowCamera(); - ~FollowCamera(); -}; - - - -#endif // FOLLOW_CAMERA_H diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index 1459f2c362..a4206894ff 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -72,6 +72,53 @@ DVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const { return DVector<Face3>(); } + + +void ImmediateGeometry::add_sphere(int p_lats,int p_lons,float p_radius) { + + for(int i = 1; i <= p_lats; i++) { + double lat0 = Math_PI * (-0.5 + (double) (i - 1) / p_lats); + double z0 = Math::sin(lat0); + double zr0 = Math::cos(lat0); + + double lat1 = Math_PI * (-0.5 + (double) i / p_lats); + double z1 = Math::sin(lat1); + double zr1 = Math::cos(lat1); + + for(int j = p_lons; j >= 1; j--) { + + double lng0 = 2 * Math_PI * (double) (j - 1) / p_lons; + double x0 = Math::cos(lng0); + double y0 = Math::sin(lng0); + + double lng1 = 2 * Math_PI * (double) (j) / p_lons; + double x1 = Math::cos(lng1); + double y1 = Math::sin(lng1); + + + Vector3 v[4]={ + Vector3(x1 * zr0, z0, y1 *zr0), + Vector3(x1 * zr1, z1, y1 *zr1), + Vector3(x0 * zr1, z1, y0 *zr1), + Vector3(x0 * zr0, z0, y0 *zr0) + }; + +#define ADD_POINT(m_idx)\ + set_normal(v[m_idx]);\ + add_vertex(v[m_idx]*p_radius); + + ADD_POINT(0); + ADD_POINT(1); + ADD_POINT(2); + + ADD_POINT(2); + ADD_POINT(3); + ADD_POINT(0); + } + } + +} + void ImmediateGeometry::_bind_methods() { ObjectTypeDB::bind_method(_MD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin); @@ -81,11 +128,14 @@ void ImmediateGeometry::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv); ObjectTypeDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2); ObjectTypeDB::bind_method(_MD("add_vertex","color"),&ImmediateGeometry::add_vertex); + ObjectTypeDB::bind_method(_MD("add_sphere","lats","lons","radius"),&ImmediateGeometry::add_sphere); ObjectTypeDB::bind_method(_MD("end"),&ImmediateGeometry::end); ObjectTypeDB::bind_method(_MD("clear"),&ImmediateGeometry::clear); } + + ImmediateGeometry::ImmediateGeometry() { im = VisualServer::get_singleton()->immediate_create(); diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h index 2db81134c6..beb8ea8214 100644 --- a/scene/3d/immediate_geometry.h +++ b/scene/3d/immediate_geometry.h @@ -31,6 +31,11 @@ public: void end(); void clear(); + + void add_sphere(int p_lats,int p_lons,float p_radius); + + + virtual AABB get_aabb() const; virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 0d571b77cd..e51a9764f6 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -429,10 +429,42 @@ void Light::approximate_opengl_attenuation(float p_constant, float p_linear, flo } + +void Light::_update_visibility() { + + if (!is_inside_scene()) + return; + + +bool editor_ok=true; + +#ifdef TOOLS_ENABLED + if (editor_only) { + if (!get_scene()->is_editor_hint()) { + editor_ok=false; + } else { + editor_ok = (get_scene()->get_edited_scene_root() && (this==get_scene()->get_edited_scene_root() || get_owner()==get_scene()->get_edited_scene_root())); + } + } +#endif + + VS::get_singleton()->instance_light_set_enabled(get_instance(),is_visible() && enabled && editor_ok); + _change_notify("geometry/visible"); + +} + + +void Light::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_SCENE || p_what==NOTIFICATION_VISIBILITY_CHANGED) { + _update_visibility(); + } +} + void Light::set_enabled(bool p_enabled) { enabled=p_enabled; - VS::get_singleton()->instance_light_set_enabled(get_instance(),enabled); + _update_visibility(); } bool Light::is_enabled() const{ @@ -440,6 +472,17 @@ bool Light::is_enabled() const{ return enabled; } +void Light::set_editor_only(bool p_editor_only) { + + editor_only=p_editor_only; + _update_visibility(); +} + +bool Light::is_editor_only() const{ + + return editor_only; +} + void Light::_bind_methods() { @@ -457,9 +500,12 @@ void Light::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_bake_mode"), &Light::get_bake_mode ); ObjectTypeDB::bind_method(_MD("set_enabled","enabled"), &Light::set_enabled ); ObjectTypeDB::bind_method(_MD("is_enabled"), &Light::is_enabled ); + ObjectTypeDB::bind_method(_MD("set_editor_only","editor_only"), &Light::set_editor_only ); + ObjectTypeDB::bind_method(_MD("is_editor_only"), &Light::is_editor_only ); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "params/enabled"), _SCS("set_enabled"), _SCS("is_enabled")); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "params/editor_only"), _SCS("set_editor_only"), _SCS("is_editor_only")); ADD_PROPERTY( PropertyInfo( Variant::INT, "params/bake_mode",PROPERTY_HINT_ENUM,"Disabled,Indirect,Indirect+Shadows,Full"), _SCS("set_bake_mode"), _SCS("get_bake_mode")); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/energy", PROPERTY_HINT_EXP_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ENERGY ); /* @@ -531,6 +577,7 @@ Light::Light(VisualServer::LightType p_type) { set_project_shadows( false ); set_base(light); enabled=true; + editor_only=false; bake_mode=BAKE_MODE_DISABLED; } diff --git a/scene/3d/light.h b/scene/3d/light.h index 8e7395fd84..6fb57a269b 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -92,8 +92,10 @@ private: VisualServer::LightType type; bool shadows; bool enabled; + bool editor_only; Operator op; - + + void _update_visibility(); // bind helpers protected: @@ -104,6 +106,7 @@ protected: virtual RES _get_gizmo_geometry() const; static void _bind_methods(); + void _notification(int p_what); Light(VisualServer::LightType p_type); @@ -132,6 +135,9 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const; + void set_editor_only(bool p_editor_only); + bool is_editor_only() const; + virtual AABB get_aabb() const; virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index 40981d468e..72d63fa006 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -30,7 +30,7 @@ #include "skeleton.h" #include "physics_body.h" - +#include "body_shape.h" bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) { @@ -181,6 +181,11 @@ void MeshInstance::create_trimesh_collision() { add_child(static_body); if (get_owner()) static_body->set_owner( get_owner() ); + CollisionShape *cshape = memnew( CollisionShape ); + cshape->set_shape(static_body->get_shape(0)); + static_body->add_child(cshape); + if (get_owner()) + cshape->set_owner( get_owner() ); } @@ -210,6 +215,12 @@ void MeshInstance::create_convex_collision() { add_child(static_body); if (get_owner()) static_body->set_owner( get_owner() ); + CollisionShape *cshape = memnew( CollisionShape ); + cshape->set_shape(static_body->get_shape(0)); + static_body->add_child(cshape); + if (get_owner()) + cshape->set_owner( get_owner() ); + } @@ -229,9 +240,9 @@ void MeshInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_skeleton_path:NodePath"),&MeshInstance::get_skeleton_path); ObjectTypeDB::bind_method(_MD("get_aabb"),&MeshInstance::get_aabb); ObjectTypeDB::bind_method(_MD("create_trimesh_collision"),&MeshInstance::create_trimesh_collision); - ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT); ObjectTypeDB::bind_method(_MD("create_convex_collision"),&MeshInstance::create_convex_collision); - ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "mesh/mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh" ), _SCS("set_mesh"), _SCS("get_mesh")); ADD_PROPERTY( PropertyInfo (Variant::NODE_PATH, "mesh/skeleton"), _SCS("set_skeleton_path"), _SCS("get_skeleton_path")); } diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 831e1c95c2..15ec60514a 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -967,6 +967,7 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { normal=rest.normal; collider=rest.collider_id; collider_vel=rest.linear_velocity; + collider_shape=rest.shape; } } @@ -1055,7 +1056,12 @@ ObjectID KinematicBody::get_collider() const { ERR_FAIL_COND_V(!colliding,0); return collider; } +int KinematicBody::get_collider_shape() const { + ERR_FAIL_COND_V(!colliding,-1); + return collider_shape; + +} void KinematicBody::set_collide_with_static_bodies(bool p_enable) { collide_static=p_enable; @@ -1119,6 +1125,7 @@ void KinematicBody::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_collision_normal"),&KinematicBody::get_collision_normal); ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&KinematicBody::get_collider_velocity); ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody::_get_collider); + ObjectTypeDB::bind_method(_MD("get_collider_shape"),&KinematicBody::get_collider_shape); ObjectTypeDB::bind_method(_MD("set_collide_with_static_bodies","enable"),&KinematicBody::set_collide_with_static_bodies); @@ -1155,6 +1162,7 @@ KinematicBody::KinematicBody() : PhysicsBody(PhysicsServer::BODY_MODE_KINEMATIC) colliding=false; collider=0; margin=0.001; + collider_shape=0; } KinematicBody::~KinematicBody() { diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 951aaf4da3..a19ad48c87 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -266,6 +266,8 @@ class KinematicBody : public PhysicsBody { Vector3 normal; Vector3 collider_vel; ObjectID collider; + int collider_shape; + Variant _get_collider() const; @@ -291,6 +293,7 @@ public: Vector3 get_collision_normal() const; Vector3 get_collider_velocity() const; ObjectID get_collider() const; + int get_collider_shape() const; void set_collide_with_static_bodies(bool p_enable); bool can_collide_with_static_bodies() const; diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 858ee4e4ad..737f7d2dce 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -237,6 +237,21 @@ Transform Skeleton::get_bone_transform(int p_bone) const { return bones[p_bone].pose_global * bones[p_bone].rest_global_inverse; } + +void Skeleton::set_bone_global_pose(int p_bone,const Transform& p_pose) { + + ERR_FAIL_INDEX(p_bone,bones.size()); + if (bones[p_bone].parent==-1) { + + set_bone_pose(p_bone,bones[p_bone].rest.inverse() * p_pose); + } else { + + set_bone_pose(p_bone, bones[p_bone].rest.inverse() * (get_bone_global_pose(bones[p_bone].parent).affine_inverse() * p_pose)); + + } + +} + Transform Skeleton::get_bone_global_pose(int p_bone) const { ERR_FAIL_INDEX_V(p_bone,bones.size(),Transform()); @@ -519,6 +534,7 @@ void Skeleton::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_bone_pose","bone_idx"),&Skeleton::get_bone_pose); ObjectTypeDB::bind_method(_MD("set_bone_pose","bone_idx","pose"),&Skeleton::set_bone_pose); + ObjectTypeDB::bind_method(_MD("set_bone_global_pose","bone_idx","pose"),&Skeleton::set_bone_global_pose); ObjectTypeDB::bind_method(_MD("get_bone_global_pose","bone_idx"),&Skeleton::get_bone_global_pose); ObjectTypeDB::bind_method(_MD("get_bone_custom_pose","bone_idx"),&Skeleton::get_bone_custom_pose); diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 3e0ab0afd7..c61946a4c7 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -118,6 +118,8 @@ public: Transform get_bone_transform(int p_bone) const; Transform get_bone_global_pose(int p_bone) const; + void set_bone_global_pose(int p_bone,const Transform& p_pose); + void set_bone_enabled(int p_bone, bool p_enabled); bool is_bone_enabled(int p_bone) const; diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index af535e139f..398fbdea82 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -50,17 +50,24 @@ void VisualInstance::_notification(int p_what) { // CHECK ROOM Spatial * parent = get_parent_spatial(); Room *room=NULL; + bool is_geom = cast_to<GeometryInstance>(); while(parent) { room = parent->cast_to<Room>(); if (room) break; - else - parent=parent->get_parent_spatial(); + + if (is_geom && parent->cast_to<BakedLightSampler>()) { + VS::get_singleton()->instance_geometry_set_baked_light_sampler(get_instance(),parent->cast_to<BakedLightSampler>()->get_instance()); + break; + } + + parent=parent->get_parent_spatial(); } + if (room) { VisualServer::get_singleton()->instance_set_room(instance,room->get_instance()); @@ -85,6 +92,7 @@ void VisualInstance::_notification(int p_what) { VisualServer::get_singleton()->instance_set_scenario( instance, RID() ); VisualServer::get_singleton()->instance_set_room(instance,RID()); VisualServer::get_singleton()->instance_attach_skeleton( instance, RID() ); + VS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() ); } break; diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index bbb49a2e78..e9fefe1ba0 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -47,6 +47,7 @@ class VisualInstance : public Spatial { RID _get_visual_instance_rid() const; + protected: diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 88fabb3489..9a3c7e71ec 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -927,7 +927,7 @@ void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float StringName next=animation_get_next(p_name); - if (next!=StringName()) { + if (next!=StringName() && animation_set.has(next)) { queue(next); } } diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index ac2417d539..7745ce11fc 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -55,6 +55,9 @@ void BaseButton::_input_event(InputEvent p_event) { if (b.pressed) { if (!toggle_mode) { //mouse press attempt + + status.press_attempt=true; + status.pressing_inside=true; pressed(); emit_signal("pressed"); @@ -71,8 +74,15 @@ void BaseButton::_input_event(InputEvent p_event) { } + } else { + + if (status.press_attempt &&status.pressing_inside) { + pressed(); + emit_signal("pressed"); + } + status.press_attempt=false; } - + update(); break; } diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index ac0ded03ab..90393a1296 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -297,7 +297,7 @@ void AcceptDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_label"),&AcceptDialog::get_label); ObjectTypeDB::bind_method(_MD("set_hide_on_ok","enabled"),&AcceptDialog::set_hide_on_ok); ObjectTypeDB::bind_method(_MD("get_hide_on_ok"),&AcceptDialog::get_hide_on_ok); - ObjectTypeDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_cancel,DEFVAL(false),DEFVAL("")); + ObjectTypeDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_button,DEFVAL(false),DEFVAL("")); ObjectTypeDB::bind_method(_MD("add_cancel:Button","name"),&AcceptDialog::add_cancel); ObjectTypeDB::bind_method(_MD("_builtin_text_entered"),&AcceptDialog::_builtin_text_entered); ObjectTypeDB::bind_method(_MD("register_text_enter:LineEdit","line_edit"),&AcceptDialog::register_text_enter); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index c2dc1318c9..0ba3bdb7c6 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -855,7 +855,7 @@ void PopupMenu::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_item","label","id","accel"),&PopupMenu::add_item,DEFVAL(-1),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("add_icon_check_item","texture","label","id","accel"),&PopupMenu::add_icon_check_item,DEFVAL(-1),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("add_check_item","label","id","accel"),&PopupMenu::add_check_item,DEFVAL(-1),DEFVAL(0)); - ObjectTypeDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_check_item,DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_submenu_item,DEFVAL(-1)); ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&PopupMenu::set_item_text); ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon); ObjectTypeDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 9084983a4c..a39c61ecac 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1438,8 +1438,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ if (p_button==BUTTON_LEFT) { /* process selection */ - if (p_doubleclick && (!c.editable || c.mode==TreeItem::CELL_MODE_CUSTOM || c.mode==TreeItem::CELL_MODE_ICON)) { - + if (p_doubleclick && (!c.editable || c.mode==TreeItem::CELL_MODE_CUSTOM || c.mode==TreeItem::CELL_MODE_ICON || c.mode==TreeItem::CELL_MODE_CHECK)) { emit_signal("item_activated"); return -1; diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index bcdc50c880..c51974167d 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -968,6 +968,18 @@ void SceneMainLoop::set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect } +#ifdef TOOLS_ENABLED +void SceneMainLoop::set_edited_scene_root(Node *p_node) { + edited_scene_root=p_node; +} + +Node *SceneMainLoop::get_edited_scene_root() const { + + return edited_scene_root; +} +#endif + + void SceneMainLoop::_bind_methods() { @@ -983,6 +995,10 @@ void SceneMainLoop::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_editor_hint","enable"),&SceneMainLoop::set_editor_hint); ObjectTypeDB::bind_method(_MD("is_editor_hint"),&SceneMainLoop::is_editor_hint); +#ifdef TOOLS_ENABLED + ObjectTypeDB::bind_method(_MD("set_edited_scene_root","scene"),&SceneMainLoop::set_edited_scene_root); + ObjectTypeDB::bind_method(_MD("get_edited_scene_root"),&SceneMainLoop::get_edited_scene_root); +#endif ObjectTypeDB::bind_method(_MD("set_pause","enable"),&SceneMainLoop::set_pause); ObjectTypeDB::bind_method(_MD("is_paused"),&SceneMainLoop::is_paused); @@ -1069,6 +1085,10 @@ SceneMainLoop::SceneMainLoop() { root->set_physics_object_picking(GLOBAL_DEF("physics/enable_object_picking",true)); +#ifdef TOOLS_ENABLED + edited_scene_root=NULL; +#endif + ADD_SIGNAL( MethodInfo("idle_frame")); ADD_SIGNAL( MethodInfo("fixed_frame")); diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h index 493644d2bc..bfa755ff7c 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_main_loop.h @@ -102,6 +102,9 @@ private: int64_t current_frame; int node_count; +#ifdef TOOLS_ENABLED + Node *edited_scene_root; +#endif struct UGCall { StringName group; @@ -223,6 +226,13 @@ public: void set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize); + //void change_scene(const String& p_path); + //Node *get_loaded_scene(); + +#ifdef TOOLS_ENABLED + void set_edited_scene_root(Node *p_node); + Node *get_edited_scene_root() const; +#endif SceneMainLoop(); ~SceneMainLoop(); diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index 25d1c8530e..8e80f868c6 100644 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -36,8 +36,12 @@ void Timer::_notification(int p_what) { case NOTIFICATION_READY: { - if (autostart) - start(); + if (autostart) { +#ifdef TOOLS_ENABLED + if (get_scene()->is_editor_hint() && get_scene()->get_edited_scene_root() && (get_scene()->get_edited_scene_root()==this || get_scene()->get_edited_scene_root()->is_a_parent_of(this))) + break; +#endif start(); + } } break; case NOTIFICATION_PROCESS: { diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index bd39fafc8b..6b7ed66463 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -95,8 +95,8 @@ void Viewport::_update_stretch_transform() { if (size_override_stretch && size_override) { - print_line("sive override size "+size_override_size); - print_line("rect size "+rect.size); + //print_line("sive override size "+size_override_size); + //print_line("rect size "+rect.size); stretch_transform=Matrix32(); Size2 scale = rect.size/(size_override_size+size_override_margin*2); stretch_transform.scale(scale); @@ -135,7 +135,9 @@ void Viewport::_update_rect() { } vr.width=rect.size.width; vr.height=rect.size.height; + VisualServer::get_singleton()->viewport_set_rect(viewport,vr); + last_vp_rect=rect; if (canvas_item.is_valid()) { VisualServer::get_singleton()->canvas_item_set_custom_rect(canvas_item,true,rect); @@ -513,6 +515,7 @@ void Viewport::set_rect(const Rect2& p_rect) { if (rect==p_rect) return; rect=p_rect; + _update_rect(); _update_stretch_transform(); @@ -558,7 +561,7 @@ void Viewport::_update_listener() { void Viewport::_update_listener_2d() { - if (is_inside_scene() && audio_listener && camera && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) + if (is_inside_scene() && audio_listener && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,find_world_2d()->get_sound_space()); else SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,RID()); @@ -1029,13 +1032,16 @@ void Viewport::_make_input_local(InputEvent& ev) { Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 g = ai.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); Vector2 l = ai.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)); - Vector2 r = ai.xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 r = ai.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 s = ai.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y)); ev.mouse_motion.x=l.x; ev.mouse_motion.y=l.y; ev.mouse_motion.global_x=g.x; ev.mouse_motion.global_y=g.y; ev.mouse_motion.relative_x=r.x; ev.mouse_motion.relative_y=r.y; + ev.mouse_motion.speed_x=s.x; + ev.mouse_motion.speed_y=s.y; } break; case InputEvent::SCREEN_TOUCH: { @@ -1050,8 +1056,8 @@ void Viewport::_make_input_local(InputEvent& ev) { Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 t = ai.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)); - Vector2 r = ai.xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); - Vector2 s = ai.xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); + Vector2 r = ai.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); + Vector2 s = ai.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); ev.screen_drag.x=t.x; ev.screen_drag.y=t.y; ev.screen_drag.relative_x=r.x; @@ -1185,6 +1191,21 @@ void Viewport::set_physics_object_picking(bool p_enable) { } + +Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const { + + Matrix32 xf = get_final_transform(); + return xf.xform(p_viewport_coords); + + +} + +Vector2 Viewport::get_camera_rect_size() const { + + return last_vp_rect.size; +} + + bool Viewport::get_physics_object_picking() { diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 5d68438f0d..37f1b357c6 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -110,6 +110,7 @@ friend class RenderTargetTexture; Size2 size_override_size; Size2 size_override_margin; + Rect2 last_vp_rect; bool transparent_bg; bool render_target_vflip; @@ -229,6 +230,10 @@ public: RenderTargetUpdateMode get_render_target_update_mode() const; Ref<RenderTargetTexture> get_render_target_texture() const; + + Vector2 get_camera_coords(const Vector2& p_viewport_coords) const; + Vector2 get_camera_rect_size() const; + void queue_screen_capture(); Image get_screen_capture() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index a5ad38e79c..f3b13f30bf 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -176,7 +176,6 @@ #include "scene/3d/camera.h" #include "scene/3d/interpolated_camera.h" -#include "scene/3d/follow_camera.h" #include "scene/3d/position_3d.h" #include "scene/3d/test_cube.h" #include "scene/3d/mesh_instance.h" @@ -353,7 +352,6 @@ void register_scene_types() { ObjectTypeDB::register_type<BoneAttachment>(); ObjectTypeDB::register_virtual_type<VisualInstance>(); ObjectTypeDB::register_type<Camera>(); - ObjectTypeDB::register_type<FollowCamera>(); ObjectTypeDB::register_type<InterpolatedCamera>(); ObjectTypeDB::register_type<TestCube>(); ObjectTypeDB::register_type<MeshInstance>(); @@ -396,6 +394,7 @@ void register_scene_types() { ObjectTypeDB::register_type<VisibilityNotifier>(); ObjectTypeDB::register_type<VisibilityEnabler>(); ObjectTypeDB::register_type<BakedLightInstance>(); + ObjectTypeDB::register_type<BakedLightSampler>(); ObjectTypeDB::register_type<WorldEnvironment>(); //scenariofx diff --git a/scene/resources/baked_light.cpp b/scene/resources/baked_light.cpp index 647c8df5d4..226edec9ae 100644 --- a/scene/resources/baked_light.cpp +++ b/scene/resources/baked_light.cpp @@ -23,6 +23,27 @@ DVector<uint8_t> BakedLight::get_octree() const { return VS::get_singleton()->baked_light_get_octree(baked_light); } +void BakedLight::set_light(const DVector<uint8_t>& p_light) { + + VS::get_singleton()->baked_light_set_light(baked_light,p_light); +} + +DVector<uint8_t> BakedLight::get_light() const { + + return VS::get_singleton()->baked_light_get_light(baked_light); +} + + +void BakedLight::set_sampler_octree(const DVector<int>& p_sampler_octree) { + + VS::get_singleton()->baked_light_set_sampler_octree(baked_light,p_sampler_octree); +} + +DVector<int> BakedLight::get_sampler_octree() const { + + return VS::get_singleton()->baked_light_get_sampler_octree(baked_light); +} + @@ -199,6 +220,43 @@ float BakedLight::get_normal_damp() const { return normal_damp; } +void BakedLight::set_tint(float p_margin) { + tint=p_margin; +} + +float BakedLight::get_tint() const { + + return tint; +} + +void BakedLight::set_saturation(float p_margin) { + saturation=p_margin; +} + +float BakedLight::get_saturation() const { + + return saturation; +} + +void BakedLight::set_ao_radius(float p_ao_radius) { + ao_radius=p_ao_radius; +} + +float BakedLight::get_ao_radius() const { + return ao_radius; +} + +void BakedLight::set_ao_strength(float p_ao_strength) { + + ao_strength=p_ao_strength; +} + +float BakedLight::get_ao_strength() const { + + return ao_strength; +} + + void BakedLight::set_energy_multiplier(float p_multiplier){ energy_multiply=p_multiplier; @@ -329,6 +387,13 @@ void BakedLight::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_octree","octree"),&BakedLight::set_octree); ObjectTypeDB::bind_method(_MD("get_octree"),&BakedLight::get_octree); + ObjectTypeDB::bind_method(_MD("set_light","light"),&BakedLight::set_light); + ObjectTypeDB::bind_method(_MD("get_light"),&BakedLight::get_light); + + ObjectTypeDB::bind_method(_MD("set_sampler_octree","sampler_octree"),&BakedLight::set_sampler_octree); + ObjectTypeDB::bind_method(_MD("get_sampler_octree"),&BakedLight::get_sampler_octree); + + ObjectTypeDB::bind_method(_MD("add_lightmap","texture:Texture","gen_size"),&BakedLight::add_lightmap); ObjectTypeDB::bind_method(_MD("erase_lightmap","id"),&BakedLight::erase_lightmap); ObjectTypeDB::bind_method(_MD("clear_lightmaps"),&BakedLight::clear_lightmaps); @@ -357,6 +422,18 @@ void BakedLight::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_normal_damp","normal_damp"),&BakedLight::set_normal_damp); ObjectTypeDB::bind_method(_MD("get_normal_damp"),&BakedLight::get_normal_damp); + ObjectTypeDB::bind_method(_MD("set_tint","tint"),&BakedLight::set_tint); + ObjectTypeDB::bind_method(_MD("get_tint"),&BakedLight::get_tint); + + ObjectTypeDB::bind_method(_MD("set_saturation","saturation"),&BakedLight::set_saturation); + ObjectTypeDB::bind_method(_MD("get_saturation"),&BakedLight::get_saturation); + + ObjectTypeDB::bind_method(_MD("set_ao_radius","ao_radius"),&BakedLight::set_ao_radius); + ObjectTypeDB::bind_method(_MD("get_ao_radius"),&BakedLight::get_ao_radius); + + ObjectTypeDB::bind_method(_MD("set_ao_strength","ao_strength"),&BakedLight::set_ao_strength); + ObjectTypeDB::bind_method(_MD("get_ao_strength"),&BakedLight::get_ao_strength); + ObjectTypeDB::bind_method(_MD("set_format","format"),&BakedLight::set_format); ObjectTypeDB::bind_method(_MD("get_format"),&BakedLight::get_format); @@ -384,17 +461,24 @@ void BakedLight::_bind_methods(){ ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/plot_size",PROPERTY_HINT_RANGE,"1.0,16.0,0.01"),_SCS("set_plot_size"),_SCS("get_plot_size")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/energy_mult",PROPERTY_HINT_RANGE,"0.01,4096.0,0.01"),_SCS("set_energy_multiplier"),_SCS("get_energy_multiplier")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/gamma_adjust",PROPERTY_HINT_EXP_EASING),_SCS("set_gamma_adjust"),_SCS("get_gamma_adjust")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/saturation",PROPERTY_HINT_RANGE,"0,8,0.01"),_SCS("set_saturation"),_SCS("get_saturation")); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/diffuse"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_DIFFUSE); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/specular"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_SPECULAR); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/translucent"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_TRANSLUCENT); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/conserve_energy"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_CONSERVE_ENERGY); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/linear_color"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_LINEAR_COLOR); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"lightmap/use_only_uv2"),_SCS("set_transfer_lightmaps_only_to_uv2"),_SCS("get_transfer_lightmaps_only_to_uv2")); ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_octree"),_SCS("get_octree")); + ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"light",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_light"),_SCS("get_light")); + ADD_PROPERTY( PropertyInfo(Variant::INT_ARRAY,"sampler_octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_sampler_octree"),_SCS("get_sampler_octree")); ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"lightmaps",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_lightmap_data"),_SCS("_get_lightmap_data")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/cell_margin",PROPERTY_HINT_RANGE,"0.01,0.8,0.01"),_SCS("set_cell_extra_margin"),_SCS("get_cell_extra_margin")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/edge_damp",PROPERTY_HINT_RANGE,"0.0,8.0,0.1"),_SCS("set_edge_damp"),_SCS("get_edge_damp")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/normal_damp",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_normal_damp"),_SCS("get_normal_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/light_tint",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_tint"),_SCS("get_tint")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/ao_radius",PROPERTY_HINT_RANGE,"0.0,16.0,0.01"),_SCS("set_ao_radius"),_SCS("get_ao_radius")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/ao_strength",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_ao_strength"),_SCS("get_ao_strength")); BIND_CONSTANT( MODE_OCTREE ); BIND_CONSTANT( MODE_LIGHTMAPS ); @@ -415,18 +499,24 @@ BakedLight::BakedLight() { lattice_subdiv=4; plot_size=2.5; bounces=1; - energy_multiply=1.0; - gamma_adjust=1.0; + energy_multiply=2.0; + gamma_adjust=0.7; cell_extra_margin=0.05; edge_damp=0.0; normal_damp=0.0; + saturation=1; + tint=0.0; + ao_radius=2.5; + ao_strength=0.7; format=FORMAT_RGB; transfer_only_uv2=false; + flags[BAKE_DIFFUSE]=true; flags[BAKE_SPECULAR]=false; flags[BAKE_TRANSLUCENT]=true; flags[BAKE_CONSERVE_ENERGY]=false; + flags[BAKE_LINEAR_COLOR]=false; mode=MODE_OCTREE; baked_light=VS::get_singleton()->baked_light_create(); diff --git a/scene/resources/baked_light.h b/scene/resources/baked_light.h index 57ed7d7aee..41e1e5f9e0 100644 --- a/scene/resources/baked_light.h +++ b/scene/resources/baked_light.h @@ -26,6 +26,7 @@ public: BAKE_SPECULAR, BAKE_TRANSLUCENT, BAKE_CONSERVE_ENERGY, + BAKE_LINEAR_COLOR, BAKE_MAX }; @@ -50,6 +51,10 @@ private: float cell_extra_margin; float edge_damp; float normal_damp; + float tint; + float ao_radius; + float ao_strength; + float saturation; int bounces; bool transfer_only_uv2; Format format; @@ -99,6 +104,18 @@ public: void set_normal_damp(float p_margin); float get_normal_damp() const; + void set_tint(float p_margin); + float get_tint() const; + + void set_saturation(float p_saturation); + float get_saturation() const; + + void set_ao_radius(float p_ao_radius); + float get_ao_radius() const; + + void set_ao_strength(float p_ao_strength); + float get_ao_strength() const; + void set_bake_flag(BakeFlags p_flags,bool p_enable); bool get_bake_flag(BakeFlags p_flags) const; @@ -114,6 +131,14 @@ public: void set_octree(const DVector<uint8_t>& p_octree); DVector<uint8_t> get_octree() const; + void set_light(const DVector<uint8_t>& p_light); + DVector<uint8_t> get_light() const; + + void set_sampler_octree(const DVector<int>& p_sampler_octree); + DVector<int> get_sampler_octree() const; + + + void add_lightmap(const Ref<Texture> &p_texture,Size2 p_gen_size=Size2(256,256)); void set_lightmap_gen_size(int p_idx,const Size2& p_size); Size2 get_lightmap_gen_size(int p_idx) const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 4320d4c081..2c278f4fed 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -36,7 +36,8 @@ static const char*_flag_names[Material::FLAG_MAX]={ "invert_faces", "unshaded", "on_top", - "lightmap_on_uv2" + "lightmap_on_uv2", + "colarray_is_srgb" }; @@ -46,7 +47,8 @@ static const Material::Flag _flag_indices[Material::FLAG_MAX]={ Material::FLAG_INVERT_FACES, Material::FLAG_UNSHADED, Material::FLAG_ONTOP, - Material::FLAG_LIGHTMAP_ON_UV2 + Material::FLAG_LIGHTMAP_ON_UV2, + Material::FLAG_COLOR_ARRAY_SRGB, }; @@ -132,6 +134,8 @@ void Material::_bind_methods() { BIND_CONSTANT( FLAG_INVERT_FACES ); BIND_CONSTANT( FLAG_UNSHADED ); BIND_CONSTANT( FLAG_ONTOP ); + BIND_CONSTANT( FLAG_LIGHTMAP_ON_UV2 ); + BIND_CONSTANT( FLAG_COLOR_ARRAY_SRGB ); BIND_CONSTANT( FLAG_MAX ); BIND_CONSTANT( DEPTH_DRAW_ALWAYS ); @@ -156,6 +160,8 @@ Material::Material(const RID& p_material) { flags[FLAG_INVERT_FACES]=false; flags[FLAG_UNSHADED]=false; flags[FLAG_ONTOP]=false; + flags[FLAG_LIGHTMAP_ON_UV2]=true; + flags[FLAG_COLOR_ARRAY_SRGB]=false; depth_draw_mode=DEPTH_DRAW_OPAQUE_ONLY; @@ -427,7 +433,7 @@ FixedMaterial::FixedMaterial() : Material(VS::get_singleton()->fixed_material_cr param[PARAM_SHADE_PARAM]=0.5; param[PARAM_DETAIL]=1.0; - + set_flag(FLAG_COLOR_ARRAY_SRGB,true); fixed_flags[FLAG_USE_ALPHA]=false; fixed_flags[FLAG_USE_COLOR_ARRAY]=false; @@ -544,6 +550,10 @@ void ShaderMaterial::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"), &ShaderMaterial::set_shader ); ObjectTypeDB::bind_method(_MD("get_shader:Shader"), &ShaderMaterial::get_shader ); + + ObjectTypeDB::bind_method(_MD("set_shader_param","param","value:var"), &ShaderMaterial::set_shader_param); + ObjectTypeDB::bind_method(_MD("get_shader_param:var","param"), &ShaderMaterial::get_shader_param); + ObjectTypeDB::bind_method(_MD("_shader_changed"), &ShaderMaterial::_shader_changed ); } @@ -589,6 +599,8 @@ ParticleSystemMaterial::ParticleSystemMaterial() :Material(VisualServer::get_sin set_depth_draw_mode(DEPTH_DRAW_NEVER); VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_ALPHA,true); VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true); + set_flag(FLAG_COLOR_ARRAY_SRGB,true); + } ParticleSystemMaterial::~ParticleSystemMaterial() { @@ -659,6 +671,8 @@ UnshadedMaterial::UnshadedMaterial() :Material(VisualServer::get_singleton()->fi set_flag(FLAG_UNSHADED,true); set_use_alpha(true); + set_flag(FLAG_COLOR_ARRAY_SRGB,true); + } UnshadedMaterial::~UnshadedMaterial() { diff --git a/scene/resources/material.h b/scene/resources/material.h index ad503c43c6..9c3feede08 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -54,6 +54,7 @@ public: FLAG_UNSHADED = VS::MATERIAL_FLAG_UNSHADED, FLAG_ONTOP = VS::MATERIAL_FLAG_ONTOP, FLAG_LIGHTMAP_ON_UV2 = VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2, + FLAG_COLOR_ARRAY_SRGB = VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB, FLAG_MAX = VS::MATERIAL_FLAG_MAX }; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index c6e492fcb3..3aeccdc551 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -29,6 +29,7 @@ #include "mesh.h" #include "scene/resources/concave_polygon_shape.h" #include "scene/resources/convex_polygon_shape.h" +#include "surface_tool.h" static const char*_array_name[]={ "vertex_array", @@ -648,6 +649,30 @@ void Mesh::center_geometry() { } +void Mesh::regen_normalmaps() { + + + Vector< Ref<SurfaceTool> > surfs; + for(int i=0;i<get_surface_count();i++) { + + Ref<SurfaceTool> st = memnew( SurfaceTool ); + st->create_from(Ref<Mesh>(this),i); + surfs.push_back(st); + } + + while (get_surface_count()) { + surface_remove(0); + } + + for(int i=0;i<surfs.size();i++) { + + surfs[i]->generate_tangents(); + surfs[i]->commit(Ref<Mesh>(this)); + } +} + + + Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { if (triangle_mesh.is_valid()) @@ -740,6 +765,8 @@ void Mesh::_bind_methods() { ObjectTypeDB::bind_method(_MD("surface_get_name","surf_idx"),&Mesh::surface_get_name); ObjectTypeDB::bind_method(_MD("center_geometry"),&Mesh::center_geometry); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("center_geometry"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::bind_method(_MD("regen_normalmaps"),&Mesh::regen_normalmaps); + ObjectTypeDB::set_method_flags(get_type_static(),_SCS("regen_normalmaps"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::bind_method(_MD("set_custom_aabb","aabb"),&Mesh::set_custom_aabb); ObjectTypeDB::bind_method(_MD("get_custom_aabb"),&Mesh::get_custom_aabb); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 5243163a4d..d6ab6a1198 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -167,6 +167,7 @@ public: Ref<Shape> create_convex_shape() const; void center_geometry(); + void regen_normalmaps(); DVector<Face3> get_faces() const; Ref<TriangleMesh> generate_triangle_mesh() const; diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index df5fee81a8..3ed6cebf07 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -148,8 +148,8 @@ void ShaderGraph::_bind_methods() { ObjectTypeDB::bind_method(_MD("node_set_pos"),&ShaderGraph::node_set_pos ); ObjectTypeDB::bind_method(_MD("node_get_pos"),&ShaderGraph::node_get_pos ); - ObjectTypeDB::bind_method(_MD("node_get_param"),&ShaderGraph::node_get_type); - ObjectTypeDB::bind_method(_MD("node_get_type"),&ShaderGraph::node_get_param); + ObjectTypeDB::bind_method(_MD("node_get_param"),&ShaderGraph::node_get_param); + ObjectTypeDB::bind_method(_MD("node_get_type"),&ShaderGraph::node_get_type); ObjectTypeDB::bind_method(_MD("connect"),&ShaderGraph::connect ); ObjectTypeDB::bind_method(_MD("disconnect"),&ShaderGraph::disconnect ); diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index ca891920da..738b642d43 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -109,7 +109,7 @@ void Shape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("collide","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide); ObjectTypeDB::bind_method(_MD("collide_with_motion","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion); ObjectTypeDB::bind_method(_MD("collide_and_get_contacts:var","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide_and_get_contacts); - ObjectTypeDB::bind_method(_MD("collide_with_motion_and_get_contacts:var","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_and_get_contacts); + ObjectTypeDB::bind_method(_MD("collide_with_motion_and_get_contacts:var","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion_and_get_contacts); ADD_PROPERTY( PropertyInfo(Variant::REAL,"custom_solver_bias",PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_custom_solver_bias"),_SCS("get_custom_solver_bias")); } diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 2856101674..dd39205932 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -105,7 +105,7 @@ void SurfaceTool::add_vertex( const Vector3& p_vertex) { vtx.weights=last_weights; vtx.bones=last_bones; vtx.tangent=last_tangent.normal; - vtx.binormal=last_tangent.normal.cross(last_normal).normalized() * last_tangent.d; + vtx.binormal=last_normal.cross(last_tangent.normal).normalized() * last_tangent.d; vertex_array.push_back(vtx); first=false; format|=Mesh::ARRAY_FORMAT_VERTEX; @@ -299,7 +299,9 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& p_existing) { w[idx+0]=v.tangent.x; w[idx+1]=v.tangent.y; w[idx+2]=v.tangent.z; - float d = v.binormal.dot(v.normal.cross(v.tangent)); + + //float d = v.tangent.dot(v.binormal,v.normal); + float d = v.binormal.dot( v.normal.cross(v.tangent)); w[idx+3]=d<0 ? -1 : 1; } @@ -565,6 +567,7 @@ void SurfaceTool::create_from(const Ref<Mesh>& p_existing, int p_surface) { clear(); primitive=p_existing->surface_get_primitive_type(p_surface); _create_list(p_existing,p_surface,&vertex_array,&index_array,format); + material=p_existing->surface_get_material(p_surface); } @@ -611,165 +614,96 @@ void SurfaceTool::append_from(const Ref<Mesh>& p_existing, int p_surface,const T } +//mikktspace callbacks +int SurfaceTool::mikktGetNumFaces(const SMikkTSpaceContext * pContext) { -void SurfaceTool::generate_tangents() { - - ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_TEX_UV)); - ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_NORMAL)); - - - if (index_array.size()) { - - Vector<List<Vertex>::Element*> vtx; - vtx.resize(vertex_array.size()); - int idx=0; - for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) { - vtx[idx++]=E; - E->get().binormal=Vector3(); - E->get().tangent=Vector3(); - } - - for (List<int>::Element *E=index_array.front();E;) { - - int i[3]; - i[0]=E->get(); - E=E->next(); - ERR_FAIL_COND(!E); - i[1]=E->get(); - E=E->next(); - ERR_FAIL_COND(!E); - i[2]=E->get(); - E=E->next(); - ERR_FAIL_COND(!E); - - - Vector3 v1 = vtx[ i[0] ]->get().vertex; - Vector3 v2 = vtx[ i[1] ]->get().vertex; - Vector3 v3 = vtx[ i[2] ]->get().vertex; - - Vector2 w1 = vtx[ i[0] ]->get().uv; - Vector2 w2 = vtx[ i[1] ]->get().uv; - Vector2 w3 = vtx[ i[2] ]->get().uv; - - - float x1 = v2.x - v1.x; - float x2 = v3.x - v1.x; - float y1 = v2.y - v1.y; - float y2 = v3.y - v1.y; - float z1 = v2.z - v1.z; - float z2 = v3.z - v1.z; - - float s1 = w2.x - w1.x; - float s2 = w3.x - w1.x; - float t1 = w2.y - w1.y; - float t2 = w3.y - w1.y; - - float r = (s1 * t2 - s2 * t1); - - Vector3 binormal,tangent; - - if (r==0) { - binormal=Vector3(0,0,0); - tangent=Vector3(0,0,0); - } else { - tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); - binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); - } - - tangent.normalize(); - binormal.normalize(); - Vector3 normal=Plane( v1, v2, v3 ).normal; - - Vector3 tangentp = tangent - normal * normal.dot( tangent ); - Vector3 binormalp = binormal - normal * (normal.dot(binormal)) - tangent * (tangent.dot(binormal)); - - tangentp.normalize(); - binormalp.normalize(); + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + return varr.size()/3; +} +int SurfaceTool::mikktGetNumVerticesOfFace(const SMikkTSpaceContext * pContext, const int iFace){ + return 3; //always 3 +} +void SurfaceTool::mikktGetPosition(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert){ - for (int j=0;j<3;j++) { - vtx[ i[j] ]->get().binormal+=binormalp; - vtx[ i[j] ]->get().tangent+=tangentp; + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + Vector3 v = varr[iFace*3+iVert]->get().vertex; + fvPosOut[0]=v.x; + fvPosOut[1]=v.y; + fvPosOut[2]=v.z; - } - } - for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) { - E->get().binormal.normalize(); - E->get().tangent.normalize(); - } +} +void SurfaceTool::mikktGetNormal(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert){ - } else { + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + Vector3 v = varr[iFace*3+iVert]->get().normal; + fvNormOut[0]=v.x; + fvNormOut[1]=v.y; + fvNormOut[2]=v.z; - for (List<Vertex>::Element *E=vertex_array.front();E;) { +} +void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert){ - List< Vertex >::Element *v[3]; - v[0]=E; - v[1]=v[0]->next(); - ERR_FAIL_COND(!v[1]); - v[2]=v[1]->next(); - ERR_FAIL_COND(!v[2]); - E=v[2]->next(); + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + Vector2 v = varr[iFace*3+iVert]->get().uv; + fvTexcOut[0]=v.x; + //fvTexcOut[1]=v.y; + fvTexcOut[1]=1.0-v.y; - Vector3 v1 = v[0]->get().vertex; - Vector3 v2 = v[1]->get().vertex; - Vector3 v3 = v[2]->get().vertex; +} +void SurfaceTool::mikktSetTSpaceBasic(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert){ - Vector2 w1 = v[0]->get().uv; - Vector2 w2 = v[1]->get().uv; - Vector2 w3 = v[2]->get().uv; + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + Vertex &vtx = varr[iFace*3+iVert]->get(); + vtx.tangent = Vector3(fvTangent[0],fvTangent[1],fvTangent[2]); + vtx.binormal = vtx.normal.cross(vtx.tangent) * fSign; +} - float x1 = v2.x - v1.x; - float x2 = v3.x - v1.x; - float y1 = v2.y - v1.y; - float y2 = v3.y - v1.y; - float z1 = v2.z - v1.z; - float z2 = v3.z - v1.z; - float s1 = w2.x - w1.x; - float s2 = w3.x - w1.x; - float t1 = w2.y - w1.y; - float t2 = w3.y - w1.y; +void SurfaceTool::generate_tangents() { - float r = (s1 * t2 - s2 * t1); + ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_TEX_UV)); + ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_NORMAL)); - Vector3 binormal,tangent; + bool indexed = index_array.size()>0; + if (indexed) + deindex(); - if (r==0) { - binormal=Vector3(0,0,0); - tangent=Vector3(0,0,0); - } else { - tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); - binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); - } - tangent.normalize(); - binormal.normalize(); - Vector3 normal=Plane( v1, v2, v3 ).normal; + SMikkTSpaceInterface mkif; + mkif.m_getNormal=mikktGetNormal; + mkif.m_getNumFaces=mikktGetNumFaces; + mkif.m_getNumVerticesOfFace=mikktGetNumVerticesOfFace; + mkif.m_getPosition=mikktGetPosition; + mkif.m_getTexCoord=mikktGetTexCoord; + mkif.m_setTSpaceBasic=mikktSetTSpaceBasic; + mkif.m_setTSpace=NULL; - Vector3 tangentp = tangent - normal * normal.dot( tangent ); - Vector3 binormalp = binormal - normal * (normal.dot(binormal)) - tangent * (tangent.dot(binormal)); + SMikkTSpaceContext msc; + msc.m_pInterface=&mkif; - tangentp.normalize(); - binormalp.normalize(); + Vector<List<Vertex>::Element*> vtx; + vtx.resize(vertex_array.size()); + int idx=0; + for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) { + vtx[idx++]=E; + E->get().binormal=Vector3(); + E->get().tangent=Vector3(); + } + msc.m_pUserData=&vtx; + bool res = genTangSpaceDefault(&msc); - for (int j=0;j<3;j++) { - v[j]->get().binormal=binormalp; - v[j]->get().tangent=tangentp; + ERR_FAIL_COND(!res); + format|=Mesh::ARRAY_FORMAT_TANGENT; - } - } - } + if (indexed) + index(); - format|=Mesh::ARRAY_FORMAT_TANGENT; } diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index fe82d3a4ce..fc5940145b 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -30,7 +30,7 @@ #define SURFACE_TOOL_H #include "scene/resources/mesh.h" - +#include "mikktspace.h" class SurfaceTool : public Reference { @@ -82,6 +82,14 @@ private: void _create_list(const Ref<Mesh>& p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index,int &lformat); + + //mikktspace callbacks + static int mikktGetNumFaces(const SMikkTSpaceContext * pContext); + static int mikktGetNumVerticesOfFace(const SMikkTSpaceContext * pContext, const int iFace); + static void mikktGetPosition(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert); + static void mikktGetNormal(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert); + static void mikktGetTexCoord(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert); + static void mikktSetTSpaceBasic(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert); protected: static void _bind_methods(); diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 73441882fb..725a440b59 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -185,6 +185,7 @@ float BodySW::get_param(PhysicsServer::BodyParameter p_param) const { void BodySW::set_mode(PhysicsServer::BodyMode p_mode) { + PhysicsServer::BodyMode prev=mode; mode=p_mode; switch(p_mode) { @@ -199,6 +200,10 @@ void BodySW::set_mode(PhysicsServer::BodyMode p_mode) { set_active(p_mode==PhysicsServer::BODY_MODE_KINEMATIC && contacts.size()); linear_velocity=Vector3(); angular_velocity=Vector3(); + if (mode==PhysicsServer::BODY_MODE_KINEMATIC && prev!=mode) { + first_time_kinematic=true; + } + } break; case PhysicsServer::BODY_MODE_RIGID: { @@ -238,6 +243,11 @@ void BodySW::set_state(PhysicsServer::BodyState p_state, const Variant& p_varian new_transform=p_variant; //wakeup_neighbours(); set_active(true); + if (first_time_kinematic) { + _set_transform(p_variant); + _set_inv_transform(get_transform().affine_inverse()); + first_time_kinematic=false; + } } else if (mode==PhysicsServer::BODY_MODE_STATIC) { _set_transform(p_variant); @@ -669,6 +679,7 @@ BodySW::BodySW() : CollisionObjectSW(TYPE_BODY), active_list(this), inertia_upda island_step=0; island_next=NULL; island_list_next=NULL; + first_time_kinematic=false; _set_static(false); density=0; contact_count=0; diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index f152c4754a..ee3c76e455 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -74,6 +74,7 @@ class BodySW : public CollisionObjectSW { bool continuous_cd; bool can_sleep; + bool first_time_kinematic; void _update_inertia(); virtual void _shapes_changed(); Transform new_transform; diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index e90faa3efb..fbad19f6be 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -176,6 +176,7 @@ float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { + Physics2DServer::BodyMode prev=mode; mode=p_mode; switch(p_mode) { @@ -189,6 +190,9 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { set_active(p_mode==Physics2DServer::BODY_MODE_KINEMATIC && contacts.size()); linear_velocity=Vector2(); angular_velocity=0; + if (mode==Physics2DServer::BODY_MODE_KINEMATIC && prev!=mode) { + first_time_kinematic=true; + } } break; case Physics2DServer::BODY_MODE_RIGID: { @@ -226,9 +230,15 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant& p_va if (mode==Physics2DServer::BODY_MODE_KINEMATIC) { - new_transform=p_variant; + + new_transform=p_variant; //wakeup_neighbours(); set_active(true); + if (first_time_kinematic) { + _set_transform(p_variant); + _set_inv_transform(get_transform().affine_inverse()); + first_time_kinematic=false; + } } else if (mode==Physics2DServer::BODY_MODE_STATIC) { _set_transform(p_variant); _set_inv_transform(get_transform().affine_inverse()); @@ -591,6 +601,7 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti island_next=NULL; island_list_next=NULL; _set_static(false); + first_time_kinematic=false; density=0; contact_count=0; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index cf4d5c92f2..789fb1cfee 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -72,6 +72,7 @@ class Body2DSW : public CollisionObject2DSW { bool omit_force_integration; bool active; bool can_sleep; + bool first_time_kinematic; void _update_inertia(); virtual void _shapes_changed(); Matrix32 new_transform; @@ -335,6 +336,8 @@ public: virtual Vector2 get_contact_collider_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_pos; } virtual ObjectID get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_instance_id; } virtual int get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_shape; } + virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Variant()); return body->get_shape_metadata(body->contacts[p_contact_idx].collider_shape); } + virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_velocity_at_pos; } virtual Physics2DDirectSpaceState* get_space_state(); diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index 277a286144..d0443f8110 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -55,6 +55,14 @@ void CollisionObject2DSW::set_shape(int p_index,Shape2DSW *p_shape){ _shapes_changed(); } + +void CollisionObject2DSW::set_shape_metadata(int p_index,const Variant& p_metadata) { + + ERR_FAIL_INDEX(p_index,shapes.size()); + shapes[p_index].metadata=p_metadata; + +} + void CollisionObject2DSW::set_shape_transform(int p_index,const Matrix32& p_transform){ ERR_FAIL_INDEX(p_index,shapes.size()); diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index 1d61a1df4a..00ad361245 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -55,6 +55,7 @@ private: BroadPhase2DSW::ID bpid; Rect2 aabb_cache; //for rayqueries Shape2DSW *shape; + Variant metadata; bool trigger; Shape() { trigger=false; } }; @@ -97,11 +98,15 @@ public: void add_shape(Shape2DSW *p_shape,const Matrix32& p_transform=Matrix32()); void set_shape(int p_index,Shape2DSW *p_shape); void set_shape_transform(int p_index,const Matrix32& p_transform); + void set_shape_metadata(int p_index,const Variant& p_metadata); + + _FORCE_INLINE_ int get_shape_count() const { return shapes.size(); } _FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const { return shapes[p_index].shape; } _FORCE_INLINE_ const Matrix32& get_shape_transform(int p_index) const { return shapes[p_index].xform; } _FORCE_INLINE_ const Matrix32& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; } _FORCE_INLINE_ const Rect2& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } + _FORCE_INLINE_ const Variant& get_shape_metadata(int p_index) const { return shapes[p_index].metadata; } _FORCE_INLINE_ Matrix32 get_transform() const { return transform; } _FORCE_INLINE_ Matrix32 get_inv_transform() const { return inv_transform; } diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 09fa3f9b6a..ab85f5e1d6 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -548,6 +548,22 @@ void Physics2DServerSW::body_set_shape_transform(RID p_body, int p_shape_idx, co body->set_shape_transform(p_shape_idx,p_transform); } +void Physics2DServerSW::body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_shape_metadata(p_shape_idx,p_metadata); +} + + +Variant Physics2DServerSW::body_get_shape_metadata(RID p_body, int p_shape_idx) const { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,Variant()); + return body->get_shape_metadata(p_shape_idx); +} + + int Physics2DServerSW::body_get_shape_count(RID p_body) const { Body2DSW *body = body_owner.get(p_body); diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 7ffffe669f..9edd4eee11 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -149,10 +149,14 @@ public: virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32()); virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape); virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform); + virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata); + virtual int body_get_shape_count(RID p_body) const; virtual RID body_get_shape(RID p_body, int p_shape_idx) const; virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const; + virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const; + virtual void body_remove_shape(RID p_body, int p_shape_idx); virtual void body_clear_shapes(RID p_body); diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 21a99cd4b2..8b72436936 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -126,6 +126,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec if (r_result.collider_id!=0) r_result.collider=ObjectDB::get_instance(r_result.collider_id); r_result.normal=res_normal; + r_result.metadata=res_obj->get_shape_metadata(res_shape); r_result.position=res_point; r_result.rid=res_obj->get_self(); r_result.shape=res_shape; @@ -171,6 +172,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matri r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id); r_results[cc].rid=col_obj->get_self(); r_results[cc].shape=shape_idx; + r_results[cc].metadata=col_obj->get_shape_metadata(shape_idx); cc++; @@ -350,6 +352,7 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v rd->best_object=rd->object; rd->best_shape=rd->shape; + } @@ -399,6 +402,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape r_info->normal=rcd.best_normal; r_info->point=rcd.best_contact; r_info->rid=rcd.best_object->get_self(); + r_info->metadata=rcd.best_object->get_shape_metadata(rcd.best_shape); if (rcd.best_object->get_type()==CollisionObject2DSW::TYPE_BODY) { const Body2DSW *body = static_cast<const Body2DSW*>(rcd.best_object); diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index da8ac5f9c8..2760f9bea6 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -97,6 +97,7 @@ void Physics2DDirectBodyState::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id); ObjectTypeDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object); ObjectTypeDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape); + ObjectTypeDB::bind_method(_MD("get_contact_collider_shape_metadata:var","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata); ObjectTypeDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos); ObjectTypeDB::bind_method(_MD("get_step"),&Physics2DDirectBodyState::get_step); ObjectTypeDB::bind_method(_MD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces); @@ -244,6 +245,7 @@ Dictionary Physics2DDirectSpaceState::_intersect_ray(const Vector2& p_from, cons d["collider"]=inters.collider; d["shape"]=inters.shape; d["rid"]=inters.rid; + d["metadata"]=inters.metadata; return d; } @@ -262,6 +264,7 @@ Array Physics2DDirectSpaceState::_intersect_shape(const Ref<Physics2DShapeQueryP d["collider_id"]=sr[i].collider_id; d["collider"]=sr[i].collider; d["shape"]=sr[i].shape; + d["metadata"]=sr[i].metadata; ret[i]=d; } @@ -311,6 +314,7 @@ Dictionary Physics2DDirectSpaceState::_get_rest_info(const Ref<Physics2DShapeQue r["collider_id"]=sri.collider_id; r["shape"]=sri.shape; r["linear_velocity"]=sri.linear_velocity; + r["metadata"]=sri.metadata; return r; } @@ -412,8 +416,8 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&Physics2DServer::area_set_space_override_mode); ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&Physics2DServer::area_get_space_override_mode); - ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&Physics2DServer::area_set_shape,DEFVAL(Matrix32())); - ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_get_shape); + ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&Physics2DServer::area_add_shape,DEFVAL(Matrix32())); + ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_set_shape); ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&Physics2DServer::area_set_shape_transform); ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&Physics2DServer::area_get_shape_count); @@ -446,10 +450,12 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_add_shape","body","shape","transform"),&Physics2DServer::body_add_shape,DEFVAL(Matrix32())); ObjectTypeDB::bind_method(_MD("body_set_shape","body","shape_idx","shape"),&Physics2DServer::body_set_shape); ObjectTypeDB::bind_method(_MD("body_set_shape_transform","body","shape_idx","transform"),&Physics2DServer::body_set_shape_transform); + ObjectTypeDB::bind_method(_MD("body_set_shape_metadata","body","shape_idx","metadata"),&Physics2DServer::body_set_shape_metadata); ObjectTypeDB::bind_method(_MD("body_get_shape_count","body"),&Physics2DServer::body_get_shape_count); ObjectTypeDB::bind_method(_MD("body_get_shape","body","shape_idx"),&Physics2DServer::body_get_shape); ObjectTypeDB::bind_method(_MD("body_get_shape_transform","body","shape_idx"),&Physics2DServer::body_get_shape_transform); + ObjectTypeDB::bind_method(_MD("body_get_shape_metadata","body","shape_idx"),&Physics2DServer::body_get_shape_metadata); ObjectTypeDB::bind_method(_MD("body_remove_shape","body","shape_idx"),&Physics2DServer::body_remove_shape); ObjectTypeDB::bind_method(_MD("body_clear_shapes","body"),&Physics2DServer::body_clear_shapes); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 17a21e46a3..20d7c3ad28 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -71,6 +71,7 @@ public: virtual ObjectID get_contact_collider_id(int p_contact_idx) const=0; virtual Object* get_contact_collider_object(int p_contact_idx) const; virtual int get_contact_collider_shape(int p_contact_idx) const=0; + virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const=0; virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const=0; virtual real_t get_step() const=0; @@ -163,6 +164,7 @@ public: ObjectID collider_id; Object *collider; int shape; + Variant metadata; }; virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; @@ -173,6 +175,8 @@ public: ObjectID collider_id; Object *collider; int shape; + Variant metadata; + }; @@ -190,6 +194,7 @@ public: ObjectID collider_id; int shape; Vector2 linear_velocity; //velocity at contact point + Variant metadata; }; @@ -360,10 +365,12 @@ public: virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32())=0; virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape)=0; virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform)=0; + virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata)=0; virtual int body_get_shape_count(RID p_body) const=0; virtual RID body_get_shape(RID p_body, int p_shape_idx) const=0; virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const=0; + virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const=0; virtual void body_set_shape_as_trigger(RID p_body, int p_shape_idx,bool p_enable)=0; virtual bool body_is_shape_set_as_trigger(RID p_body, int p_shape_idx) const=0; diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index fbed5779ff..e6b2927fb4 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -440,8 +440,8 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&PhysicsServer::area_set_space_override_mode); ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&PhysicsServer::area_get_space_override_mode); - ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&PhysicsServer::area_set_shape,DEFVAL(Transform())); - ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_get_shape); + ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&PhysicsServer::area_add_shape,DEFVAL(Transform())); + ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_set_shape); ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&PhysicsServer::area_set_shape_transform); ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&PhysicsServer::area_get_shape_count); @@ -452,8 +452,8 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("area_clear_shapes","area"),&PhysicsServer::area_clear_shapes); - ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&PhysicsServer::area_get_param); - ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&PhysicsServer::area_get_transform); + ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&PhysicsServer::area_set_param); + ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&PhysicsServer::area_set_transform); ObjectTypeDB::bind_method(_MD("area_get_param","area","param"),&PhysicsServer::area_get_param); ObjectTypeDB::bind_method(_MD("area_get_transform","area"),&PhysicsServer::area_get_transform); @@ -506,7 +506,7 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity); ObjectTypeDB::bind_method(_MD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock); - ObjectTypeDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_set_axis_lock); + ObjectTypeDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_get_axis_lock); ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception); ObjectTypeDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception); diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp index 95746b7675..5e81bc960a 100644 --- a/servers/visual/rasterizer.cpp +++ b/servers/visual/rasterizer.cpp @@ -98,11 +98,12 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { } if (p_key.use_xy_normalmap) { scode+="vec2 ywnormal=tex( fmp_normal_tex,"+uv_str+").wy * vec2(2.0,2.0) - vec2(1.0,1.0);\n"; - scode+="vec3 normal=vec3(ywnormal,sqrt(1 - (ywnormal.x * ywnormal.x) - (ywnormal.y * ywnormal.y) ));\n"; + scode+="NORMALMAP=vec3(ywnormal,sqrt(1 - (ywnormal.x * ywnormal.x) - (ywnormal.y * ywnormal.y) ));\n"; } else { - scode+="vec3 normal=tex( fmp_normal_tex,"+uv_str+").xyz * vec3(2.0,2.0,1.0) - vec3(1.0,1.0,0.0);\n"; + scode+="NORMALMAP=tex( fmp_normal_tex,"+uv_str+").xyz * vec3(2.0,2.0,1.0) - vec3(1.0,1.0,0.0);\n"; } - scode+="NORMAL = mix( NORMAL,mat3(TANGENT,BINORMAL,NORMAL) * normal, fmp_normal);\n"; + scode+="NORMALMAP_DEPTH=fmp_normal;\n"; + code+=scode; } @@ -363,12 +364,13 @@ RID Rasterizer::fixed_material_create() { FixedMaterial &fm=*fixed_materials[mat]; fm.self=mat; fm.get_key(); + material_set_flag(mat,VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB,true); for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) { material_set_param(mat,_fixed_material_param_names[i],fm.param[i]); //must be there } fixed_material_dirty_list.add(&fm.dirty_list); - //print_line("FMC: "+itos(mat.get_id())); + //print_line("FMC: "+itos(mat.get_id())); return mat; } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index dc970383b6..55625a2218 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -503,6 +503,7 @@ public: VS::BakedLightMode mode; RID octree_texture; + RID light_texture; float color_multiplier; //used for both lightmaps and octree Transform octree_transform; Map<int,RID> lightmaps; @@ -514,6 +515,7 @@ public: float lightmap_multiplier; int octree_steps; Vector2 octree_tex_pixel_size; + Vector2 light_tex_pixel_size; }; struct InstanceData { @@ -521,6 +523,7 @@ public: Transform transform; RID skeleton; RID material_override; + RID sampled_light; Vector<RID> light_instances; Vector<float> morph_values; BakedLightData *baked_light; @@ -586,6 +589,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value)=0; virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const=0; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height)=0; + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier)=0; + /*MISC*/ diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp index 637c251cf1..a671821e25 100644 --- a/servers/visual/rasterizer_dummy.cpp +++ b/servers/visual/rasterizer_dummy.cpp @@ -1679,6 +1679,18 @@ Variant RasterizerDummy::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } + +RID RasterizerDummy::sampled_light_dp_create(int p_width,int p_height) { + + return sampled_light_owner.make_rid(memnew(SampledLight)); +} + +void RasterizerDummy::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + +} + + /*MISC*/ bool RasterizerDummy::is_texture(const RID& p_rid) const { @@ -1816,6 +1828,14 @@ void RasterizerDummy::free(const RID& p_rid) { Environment *env = environment_owner.get( p_rid ); environment_owner.free(p_rid); memdelete( env ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); + }; } diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h index 373564249e..44bca423a4 100644 --- a/servers/visual/rasterizer_dummy.h +++ b/servers/visual/rasterizer_dummy.h @@ -353,6 +353,13 @@ class RasterizerDummy : public Rasterizer { mutable RID_Owner<Environment> environment_owner; + struct SampledLight { + + int w,h; + }; + + mutable RID_Owner<SampledLight> sampled_light_owner; + struct ShadowBuffer; struct LightInstance { @@ -713,6 +720,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier); + /*MISC*/ diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 14d35e89b1..ca219b13a4 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -1042,6 +1042,8 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={ { "NORMAL", TYPE_VEC3}, { "TANGENT", TYPE_VEC3}, { "BINORMAL", TYPE_VEC3}, + { "NORMALMAP", TYPE_VEC3}, + { "NORMALMAP_DEPTH", TYPE_FLOAT}, { "UV", TYPE_VEC2}, { "UV2", TYPE_VEC2}, { "COLOR", TYPE_VEC4}, diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 6d5627877b..13ecd49b68 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -1109,8 +1109,12 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< int tex_w; int tex_h; + int light_tex_w; + int light_tex_h; bool is16; + bool has_light_tex=false; { + DVector<uint8_t>::Read r=p_octree.read(); tex_w = decode_uint32(&r[0]); tex_h = decode_uint32(&r[4]); @@ -1123,7 +1127,22 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< baked_light->data.octree_steps=decode_uint32(&r[16]); baked_light->data.octree_tex_pixel_size.x=1.0/tex_w; baked_light->data.octree_tex_pixel_size.y=1.0/tex_h; + baked_light->data.texture_multiplier=decode_uint32(&r[20]); + light_tex_w=decode_uint16(&r[24]); + light_tex_h=decode_uint16(&r[26]); + print_line("ltexw "+itos(light_tex_w)); + print_line("ltexh "+itos(light_tex_h)); + + if (light_tex_w>0 && light_tex_h>0) { + baked_light->data.light_tex_pixel_size.x=1.0/light_tex_w; + baked_light->data.light_tex_pixel_size.y=1.0/light_tex_h; + has_light_tex=true; + } else { + baked_light->data.light_tex_pixel_size=baked_light->data.octree_tex_pixel_size; + + } + baked_light->octree_aabb.pos.x=decode_float(&r[32]); @@ -1141,12 +1160,33 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< rasterizer->free(baked_light->data.octree_texture); baked_light->data.octree_texture=RID(); + baked_light->octree_tex_size.x=0; + baked_light->octree_tex_size.y=0; + } + } + + if (baked_light->data.light_texture.is_valid()) { + if (!has_light_tex || light_tex_w!=baked_light->light_tex_size.x || light_tex_h!=baked_light->light_tex_size.y) { + rasterizer->free(baked_light->data.light_texture); + baked_light->data.light_texture=RID(); + baked_light->light_tex_size.x=0; + baked_light->light_tex_size.y=0; } } if (!baked_light->data.octree_texture.is_valid()) { baked_light->data.octree_texture=rasterizer->texture_create(); rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + baked_light->octree_tex_size.x=tex_w; + baked_light->octree_tex_size.y=tex_h; + } + + if (!baked_light->data.light_texture.is_valid() && has_light_tex) { + baked_light->data.light_texture=rasterizer->texture_create(); + rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + baked_light->light_tex_size.x=light_tex_w; + baked_light->light_tex_size.y=light_tex_h; + } Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree); @@ -1159,6 +1199,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< } + DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{ @@ -1174,6 +1215,67 @@ DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) c } } +void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light) { + + VS_CHANGED; + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + ERR_FAIL_COND(p_light.size()==0); + + int tex_w=baked_light->light_tex_size.x; + int tex_h=baked_light->light_tex_size.y; + + ERR_FAIL_COND(tex_w==0 && tex_h==0); + ERR_FAIL_COND(!baked_light->data.light_texture.is_valid()); + + + + print_line("w: "+itos(tex_w)+" h: "+itos(tex_h)+" lightsize: "+itos(p_light.size())); + + Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_light); + rasterizer->texture_set_data(baked_light->data.light_texture,img); + + + +} + +DVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{ + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>()); + + if (rasterizer->is_texture(baked_light->data.light_texture)) { + + Image img = rasterizer->texture_get_data(baked_light->data.light_texture); + return img.get_data(); + } else { + return DVector<uint8_t>(); + } +} + + + +void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const DVector<int> &p_sampler) { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + + baked_light->sampler=p_sampler; + + + +} + +DVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector<int>()); + + return baked_light->sampler; + +} + + void VisualServerRaster::baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id){ VS_CHANGED; @@ -1192,6 +1294,84 @@ void VisualServerRaster::baked_light_clear_lightmaps(RID p_baked_light){ } +/* BAKED LIGHT SAMPLER */ + +RID VisualServerRaster::baked_light_sampler_create() { + + BakedLightSampler * blsamp = memnew( BakedLightSampler ); + RID rid = baked_light_sampler_owner.make_rid(blsamp); + _update_baked_light_sampler_dp_cache(blsamp); + return rid; +} + +void VisualServerRaster::baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value){ + + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + ERR_FAIL_INDEX(p_param,BAKED_LIGHT_SAMPLER_MAX); + blsamp->params[p_param]=p_value; + _dependency_queue_update(p_baked_light_sampler,true); +} + +float VisualServerRaster::baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const{ + + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + ERR_FAIL_INDEX_V(p_param,BAKED_LIGHT_SAMPLER_MAX,0); + return blsamp->params[p_param]; +} + +void VisualServerRaster::_update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp) { + + int res = blsamp->resolution; + blsamp->dp_cache.resize(res*res*2); + Vector3 *dp_normals=blsamp->dp_cache.ptr(); + + for(int p=0;p<2;p++) { + float sign = p==0?1:-1; + int ofs = res*res*p; + for(int i=0;i<res;i++) { + for(int j=0;j<res;j++) { + + Vector2 v( + (i/float(res))*2.0-1.0, + (j/float(res))*2.0-1.0 + ); + + float l=v.length(); + if (l>1.0) { + v/=l; + l=1.0; //clamp to avoid imaginary + } + v*=(2*l)/(l*l+1); //inverse of the dual paraboloid function + Vector3 n = Vector3(v.x,v.y,sign*sqrtf(MAX(1 - v.dot(v),0))); //reconstruction of z + n.y*=sign; + dp_normals[j*res+i+ofs]=n; + } + } + } + +} + +void VisualServerRaster::baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution){ + + ERR_FAIL_COND(p_resolution<4 && p_resolution>64); + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + blsamp->resolution=p_resolution; + _update_baked_light_sampler_dp_cache(blsamp); + +} +int VisualServerRaster::baked_light_sampler_get_resolution(RID p_baked_light_sampler) const{ + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + return blsamp->resolution; +} + /* CAMERA API */ RID VisualServerRaster::camera_create() { @@ -1786,6 +1966,17 @@ void VisualServerRaster::scenario_set_environment(RID p_scenario, RID p_environm } +void VisualServerRaster::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { + + VS_CHANGED; + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->fallback_environment=p_environment; + + +} + RID VisualServerRaster::scenario_get_environment(RID p_scenario, RID p_environment) const{ const Scenario *scenario = scenario_owner.get(p_scenario); @@ -1932,6 +2123,20 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { } + if (instance->baked_light_sampler_info) { + + while (instance->baked_light_sampler_info->owned_instances.size()) { + + instance_geometry_set_baked_light_sampler(instance->baked_light_sampler_info->owned_instances.front()->get()->self,RID()); + } + + if (instance->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(instance->baked_light_sampler_info->sampled_light); + } + memdelete( instance->baked_light_sampler_info ); + instance->baked_light_sampler_info=NULL; + } + instance->data.morph_values.clear(); } @@ -1981,6 +2186,16 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { //instance->portal_info = memnew(Instance::PortalInfo); //instance->portal_info->portal=portal_owner.get(p_base); + } else if (baked_light_sampler_owner.owns(p_base)) { + + + instance->base_type=INSTANCE_BAKED_LIGHT_SAMPLER; + instance->baked_light_sampler_info=memnew( Instance::BakedLightSamplerInfo); + instance->baked_light_sampler_info->sampler=baked_light_sampler_owner.get(p_base); + + //instance->portal_info = memnew(Instance::PortalInfo); + //instance->portal_info->portal=portal_owner.get(p_base); + } else { ERR_EXPLAIN("Invalid base RID for instance!") ERR_FAIL(); @@ -2596,11 +2811,50 @@ RID VisualServerRaster::instance_geometry_get_baked_light(RID p_instance) const{ const Instance *instance = instance_owner.get( p_instance ); ERR_FAIL_COND_V( !instance,RID() ); if (instance->baked_light) - instance->baked_light->self; + return instance->baked_light->self; return RID(); } + +void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler) { + + VS_CHANGED; + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->sampled_light) { + instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance); + instance->data.sampled_light=RID(); + } + + if(p_baked_light_sampler.is_valid()) { + Instance *sampler_instance = instance_owner.get( p_baked_light_sampler ); + ERR_FAIL_COND( !sampler_instance ); + ERR_FAIL_COND( sampler_instance->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER ); + instance->sampled_light=sampler_instance; + instance->sampled_light->baked_light_sampler_info->owned_instances.insert(instance); + } else { + instance->sampled_light=NULL; + } + + instance->data.sampled_light=RID(); + +} + +RID VisualServerRaster::instance_geometry_get_baked_light_sampler(RID p_instance) const { + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND_V( !instance,RID() ); + + if (instance->sampled_light) + return instance->sampled_light->self; + else + return RID(); + +} + + void VisualServerRaster::instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id){ VS_CHANGED; @@ -2736,6 +2990,13 @@ void VisualServerRaster::_update_instance(Instance *p_instance) { pairable=true; } + if (p_instance->base_type == INSTANCE_BAKED_LIGHT_SAMPLER) { + + pairable_mask=(1<<INSTANCE_BAKED_LIGHT); + pairable=true; + } + + if (!p_instance->room && (1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) { base_type|=INSTANCE_ROOMLESS_MASK; @@ -2848,6 +3109,16 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) { new_aabb=baked_light->octree_aabb; } break; + case VisualServer::INSTANCE_BAKED_LIGHT_SAMPLER: { + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get( p_instance->base_rid ); + ERR_FAIL_COND(!baked_light_sampler); + float radius = baked_light_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + + new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2)); + + } break; + default: {} } @@ -3751,6 +4022,17 @@ void VisualServerRaster::free( RID p_rid ) { baked_light_owner.free(p_rid); memdelete(baked_light); + } else if (baked_light_sampler_owner.owns(p_rid)) { + + _free_attached_instances(p_rid); + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get(p_rid); + ERR_FAIL_COND(!baked_light_sampler); + //if (baked_light->data.octree_texture.is_valid()) + // rasterizer->free(baked_light->data.octree_texture); + baked_light_sampler_owner.free(p_rid); + memdelete(baked_light_sampler); + } else if (camera_owner.owns(p_rid)) { // delete te camera @@ -3802,7 +4084,9 @@ void VisualServerRaster::free( RID p_rid ) { instance_set_room(p_rid,RID()); instance_set_scenario(p_rid,RID()); instance_geometry_set_baked_light(p_rid,RID()); + instance_geometry_set_baked_light_sampler(p_rid,RID()); instance_set_base(p_rid,RID()); + if (instance->data.skeleton.is_valid()) instance_attach_skeleton(p_rid,RID()); @@ -4946,6 +5230,15 @@ void* VisualServerRaster::instance_pair(void *p_self, OctreeElementID, Instance //attempt to conncet portal A (will go through B anyway) //this is a little hackish, but works fine in practice + } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND_V(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER,NULL); + B->baked_light_sampler_info->baked_lights.insert(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -4995,6 +5288,15 @@ void VisualServerRaster::instance_unpair(void *p_self, OctreeElementID, Instance self->_portal_attempt_connect(A); self->_portal_attempt_connect(B); + } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER); + B->baked_light_sampler_info->baked_lights.erase(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -5186,6 +5488,308 @@ void VisualServerRaster::_cull_room(Camera *p_camera, Instance *p_room,Instance } +void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instance *p_sampled_light,bool p_linear_colorspace) { + + + BakedLightSampler *sampler_opts = p_sampled_light->baked_light_sampler_info->sampler; + int res = sampler_opts->resolution; + int dp_size = res*res*2; + Color * dp_map = (Color*)alloca( sizeof(Color)*dp_size); //allocate the dual parabolloid colors + Vector3 * dp_normals = (Vector3*)alloca( sizeof(Vector3)*dp_size); //allocate the dual parabolloid normals + const Vector3 * dp_src_normals = p_sampled_light->baked_light_sampler_info->sampler->dp_cache.ptr(); + + + if (!p_sampled_light->baked_light_sampler_info->sampled_light.is_valid() || p_sampled_light->baked_light_sampler_info->resolution!=sampler_opts->resolution) { + if (p_sampled_light->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(p_sampled_light->baked_light_sampler_info->sampled_light); + } + + p_sampled_light->baked_light_sampler_info->resolution=sampler_opts->resolution; + p_sampled_light->baked_light_sampler_info->sampled_light=rasterizer->sampled_light_dp_create(sampler_opts->resolution,sampler_opts->resolution*2); + + + } + + + zeromem(dp_map,sizeof(Color)*dp_size); + bool valid=false; + int samples=0; + + + for(Set<Instance*>::Element *E=p_sampled_light->baked_light_sampler_info->baked_lights.front();E;E=E->next()) { + + Instance *bl = E->get(); + if (bl->baked_light_info->baked_light->sampler.size()==0) + continue; //not usable + + + Matrix3 norm_xform = bl->baked_light_info->affine_inverse.basis;//.inverse(); + for(int i=0;i<dp_size;i++) { + dp_normals[i]=norm_xform.xform(dp_src_normals[i]).normalized(); + } + + //normals in place + + + //sample octree + + float r = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + float att = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_ATTENUATION]; + float str = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_STRENGTH]; + Vector3 s = p_sampled_light->data.transform.basis.get_scale(); + + r*=MAX(MAX(s.x,s.y),s.z); + AABB sample_aabb= bl->data.transform.affine_inverse().xform(AABB(Vector3(-r,-r,-r)+p_sampled_light->data.transform.origin,Vector3(r*2,r*2,r*2))); + //ok got octree local AABB + + DVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read(); + const int *rptr = rp.ptr(); + + int first = rptr[1]; + int depth = rptr[2]; + bool islinear = rptr[3]&1; + depth+=1; + + AABB aabb; + aabb.pos.x=decode_float((const uint8_t*)&rptr[4]); + aabb.pos.y=decode_float((const uint8_t*)&rptr[5]); + aabb.pos.z=decode_float((const uint8_t*)&rptr[6]); + aabb.size.x=decode_float((const uint8_t*)&rptr[7]); + aabb.size.y=decode_float((const uint8_t*)&rptr[8]); + aabb.size.z=decode_float((const uint8_t*)&rptr[9]); + + uint32_t *stack=(uint32_t*)alloca(depth*sizeof(uint32_t)); + int *stack_ptr=(int*)alloca(depth*sizeof(int)); + AABB *aabb_stack=(AABB*)alloca(depth*sizeof(AABB)); + + stack[0]=0; + stack_ptr[0]=first; + aabb_stack[0]=aabb; + Vector3 center = sample_aabb.pos + sample_aabb.size * 0.5; + + + int stack_pos=0; + Color max_col; + + //int reso = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]; + + int lalimit = sample_aabb.get_longest_axis_index(); + float limit = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]*sample_aabb.size[lalimit]; + + + while(true) { + + + bool leaf = (rptr[ stack_ptr[stack_pos] ]>>16)==0; + + if (aabb_stack[stack_pos].size[lalimit]<limit) { + leaf=true; + } + + + if (leaf) { + + Vector3 from = aabb_stack[stack_pos].pos + aabb_stack[stack_pos].size * 0.5; + Vector3 norm = (from-center).normalized(); + + + Color col; + col.r = ((rptr[ stack_ptr[stack_pos] ]&0xFFFF)/256.0); + col.g = ((rptr[ stack_ptr[stack_pos]+1 ]>>16)/256.0); + col.b = ((rptr[ stack_ptr[stack_pos]+1 ]&0xFFFF)/256.0); + + + max_col.r = MAX(max_col.r,col.r); + max_col.g = MAX(max_col.g,col.g); + max_col.b = MAX(max_col.b,col.b); + + if (!islinear && p_linear_colorspace) { + col=col.to_linear(); + } + + float distance; + + if (aabb_stack[stack_pos].has_point(center)) { + distance=0; + } else { + + Vector3 support = aabb_stack[stack_pos].get_support(norm); + distance = Math::absf(norm.dot(support)-norm.dot(center)); + + } + + if (distance>r) + distance=r; + + float mult = powf(1.0-distance/r,att)*str; + if (mult>0) { + col.r*=mult; + col.g*=mult; + col.b*=mult; + + + + for(int i=0;i<dp_size;i++) { + float mult2 = norm.dot(dp_normals[i]); + if (mult2<0) + mult2=0; + Color col2(col.r*mult2,col.g*mult2,col.b*mult2,1.0); + dp_map[i].r=MAX(dp_map[i].r,col2.r); + dp_map[i].g=MAX(dp_map[i].g,col2.g); + dp_map[i].b=MAX(dp_map[i].b,col2.b); + } + + } + + samples++; + //nothing is valid unless you hit a leaf + valid=true; + stack_pos--; + } else if ((stack[stack_pos]&0xFF)<8) { + + int i = stack[stack_pos]&0xFF; + int base = (stack[stack_pos]>>8); + + if (!((rptr[ stack_ptr[stack_pos] ]>>16)&(1<<i))) { + //no bit, no test + stack[stack_pos]=(base<<8)+(i+1); + continue; + } + + stack[stack_pos]=((base+1)<<8)+(i+1); + + AABB child_aabb = aabb_stack[stack_pos]; + child_aabb.size*=0.5; + if (i&1) + child_aabb.pos.x+=child_aabb.size.x; + if (i&2) + child_aabb.pos.y+=child_aabb.size.y; + if (i&4) + child_aabb.pos.z+=child_aabb.size.z; + + if (!child_aabb.intersects(sample_aabb)) { + continue; + } + + if (child_aabb.encloses(sample_aabb)) { + stack[stack_pos]=(base<<8)|8; //don't test the rest + } + + stack_pos++; + ERR_FAIL_COND(stack_pos>=depth); + + stack[stack_pos]=0; + stack_ptr[stack_pos]=rptr[ stack_ptr[stack_pos-1]+2+base ]; + aabb_stack[stack_pos]=child_aabb; + } else { + stack_pos--; + if (stack_pos<0) + break; + } + } + + + } + + //print_line("samples "+itos(samples) ); + + if (valid) { + + for(int i=0;i<res;i++) { + //average seams to avoid aliasing + { + //top + int ofs1 = i; + int ofs2 = dp_size-res+i; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //bottom + int ofs1 = res*res-res+i; + int ofs2 = res*res+i; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //left + int ofs1 = i*res; + int ofs2 = res*res+(res-i-1)*res; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //right + int ofs1 = i*res+(res-1); + int ofs2 = res*res+(res-i-1)*res+(res-1); + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + + } + + rasterizer->sampled_light_dp_update(p_sampled_light->baked_light_sampler_info->sampled_light,dp_map,1.0); + for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { + + F->get()->data.sampled_light=p_sampled_light->baked_light_sampler_info->sampled_light; + } + + + } else { + + for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { + + F->get()->data.sampled_light=RID(); //do not use because nothing close + } + } + + + + +/* + highp vec3 vtx = vertex_interp; + vtx.z*=dual_paraboloid.y; //side to affect + vtx.z+=0.01; + dp_clip=vtx.z; + highp float len=length( vtx ); + vtx=normalize(vtx); + vtx.xy/=1.0+vtx.z; + vtx.z = len*dual_paraboloid.x; // it's a reciprocal(len - z_near) / (z_far - z_near); + vtx+=normalize(vtx)*0.025; + vtx.z = vtx.z * 2.0 - 1.0; // fit to clipspace + vertex_interp=vtx; +*/ + + + + +} + + void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) { @@ -5237,6 +5841,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S /* STEP 2 - CULL */ int cull_count = p_scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL); light_cull_count=0; + light_samplers_culled=0; /* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); @@ -5397,6 +6002,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S keep=true; } + + } @@ -5409,6 +6016,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S cull_range.min=min; if (max>cull_range.max) cull_range.max=max; + + if (ins->sampled_light && ins->sampled_light->baked_light_sampler_info->last_pass!=render_pass) { + if (light_samplers_culled<MAX_LIGHT_SAMPLERS) { + light_sampler_cull_result[light_samplers_culled++]=ins->sampled_light; + ins->sampled_light->baked_light_sampler_info->last_pass=render_pass; + } + } } } @@ -5488,7 +6102,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } - { + { //this should eventually change to //assign shadows by distance to camera SortArray<Instance*,_InstanceLightsort> sorter; sorter.sort(light_cull_result,light_cull_count); @@ -5509,15 +6123,31 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } } + /* ENVIRONMENT */ - - /* STEP 6 - PROCESS GEOMETRY AND DRAW SCENE*/ - RID environment; if (p_camera->env.is_valid()) //camera has more environment priority environment=p_camera->env; - else + else if (p_scenario->environment.is_valid()) environment=p_scenario->environment; + else + environment=p_scenario->fallback_environment; + + + /* STEP 6 - SAMPLE BAKED LIGHT */ + + bool islinear =false; + if (environment.is_valid()) { + islinear = rasterizer->environment_is_fx_enabled(environment,VS::ENV_FX_SRGB); + } + + for(int i=0;i<light_samplers_culled;i++) { + + _process_sampled_light(p_camera->transform,light_sampler_cull_result[i],islinear); + } + + /* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/ + rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug); rasterizer->set_viewport(viewport_rect); @@ -5825,6 +6455,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ desired_rect.x+=p_ofs_x; desired_rect.y+=p_ofs_y; + // if the viewport is different than the actual one, change it if ( p_viewport->render_target.is_valid() || viewport_rect.x != desired_rect.x || @@ -5834,7 +6465,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ viewport_rect=desired_rect; - rasterizer->set_viewport(viewport_rect); + rasterizer->set_viewport(viewport_rect); } @@ -5882,6 +6513,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ if (p_viewport->queue_capture) { rasterizer->capture_viewport(&p_viewport->capture); + p_viewport->queue_capture = false; } //restore @@ -5981,7 +6613,14 @@ void VisualServerRaster::_draw_viewports() { int window_w = OS::get_singleton()->get_video_mode(E->get()).width; int window_h = OS::get_singleton()->get_video_mode(E->get()).height; - _draw_viewport(vp,0,0,window_w,window_h); + Rect2 r(0,0,vp->rect.width,vp->rect.height); + if (r.size.width==0) + r.size.width=window_w; + if (r.size.height==0) + r.size.height=window_w; + + + _draw_viewport(vp,r.pos.x,r.pos.y,r.size.width,r.size.height); } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 41ad3aab15..3064f9ceb0 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -51,6 +51,7 @@ class VisualServerRaster : public VisualServer { MAX_LIGHTS_CULLED=256, MAX_ROOM_CULL=32, MAX_EXTERIOR_PORTALS=128, + MAX_LIGHT_SAMPLERS=256, INSTANCE_ROOMLESS_MASK=(1<<20) @@ -90,12 +91,29 @@ class VisualServerRaster : public VisualServer { struct BakedLight { Rasterizer::BakedLightData data; + DVector<int> sampler; AABB octree_aabb; Size2i octree_tex_size; + Size2i light_tex_size; }; + struct BakedLightSampler { + float params[BAKED_LIGHT_SAMPLER_MAX]; + int resolution; + Vector<Vector3> dp_cache; + + BakedLightSampler() { + params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0; + params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0; + params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0; + params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1; + resolution=16; + } + }; + + void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp); struct Camera { enum Type { @@ -169,6 +187,7 @@ class VisualServerRaster : public VisualServer { List<Instance*>::Element *RE; Instance *baked_light; List<Instance*>::Element *BLE; + Instance *sampled_light; bool exterior; uint64_t last_render_pass; @@ -179,6 +198,8 @@ class VisualServerRaster : public VisualServer { InstanceSet lights; bool light_cache_dirty; + + struct RoomInfo { Transform affine_inverse; @@ -235,6 +256,23 @@ class VisualServerRaster : public VisualServer { Transform affine_inverse; List<Instance*> owned_instances; }; + + struct BakedLightSamplerInfo { + + Set<Instance*> baked_lights; + Set<Instance*> owned_instances; + BakedLightSampler *sampler; + int resolution; + Vector<Color> light_bufer; + RID sampled_light; + uint64_t last_pass; + Transform xform; // viewspace normal to lightspace, might not use one. + BakedLightSamplerInfo() { + sampler=NULL; + last_pass=0; + resolution=0; + } + }; struct ParticlesInfo { @@ -247,6 +285,7 @@ class VisualServerRaster : public VisualServer { ParticlesInfo *particles_info; PortalInfo * portal_info; BakedLightInfo * baked_light_info; + BakedLightSamplerInfo * baked_light_sampler_info; Instance() { @@ -282,6 +321,8 @@ class VisualServerRaster : public VisualServer { baked_light=NULL; baked_light_info=NULL; + baked_light_sampler_info=NULL; + sampled_light=NULL; BLE=NULL; light_cache_dirty=true; @@ -320,6 +361,7 @@ class VisualServerRaster : public VisualServer { List<RID> directional_lights; RID environment; + RID fallback_environment; Instance *dirty_instances; @@ -602,6 +644,9 @@ class VisualServerRaster : public VisualServer { int exterior_portal_cull_count; bool exterior_visited; + Instance *light_sampler_cull_result[MAX_LIGHT_SAMPLERS]; + int light_samplers_culled; + Instance *room_cull_result[MAX_ROOM_CULL]; int room_cull_count; bool room_cull_enabled; @@ -637,6 +682,7 @@ class VisualServerRaster : public VisualServer { mutable RID_Owner<Portal> portal_owner; mutable RID_Owner<BakedLight> baked_light_owner; + mutable RID_Owner<BakedLightSampler> baked_light_sampler_owner; mutable RID_Owner<Camera> camera_owner; mutable RID_Owner<Viewport> viewport_owner; @@ -657,6 +703,8 @@ class VisualServerRaster : public VisualServer { bool _test_portal_cull(Camera *p_camera, Instance *p_portal_from, Instance *p_portal_to); void _cull_portal(Camera *p_camera, Instance *p_portal,Instance *p_from_portal); void _cull_room(Camera *p_camera, Instance *p_room,Instance *p_from_portal=NULL); + void _process_sampled_light(const Transform &p_camera, Instance *p_sampled_light, bool p_linear_colorspace); + void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect,float p_opacity); void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform); @@ -952,12 +1000,28 @@ public: virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree); virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const; + virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light); + virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const; + + virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler); + virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const; + virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier); virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const; virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id); virtual void baked_light_clear_lightmaps(RID p_baked_light); + /* BAKED LIGHT SAMPLER */ + + virtual RID baked_light_sampler_create(); + + virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value); + virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const; + + virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution); + virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const; + /* CAMERA API */ virtual RID camera_create(); @@ -1038,6 +1102,8 @@ public: virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode); virtual void scenario_set_environment(RID p_scenario, RID p_environment); virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const; + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); + /* INSTANCING API */ @@ -1093,6 +1159,9 @@ public: virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light); virtual RID instance_geometry_get_baked_light(RID p_instance) const; + virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler); + virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const; + virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id); virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const; diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 73e736f684..a4653b1013 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -909,6 +909,12 @@ public: FUNC2(baked_light_set_octree,RID,DVector<uint8_t>); FUNC1RC(DVector<uint8_t>,baked_light_get_octree,RID); + FUNC2(baked_light_set_light,RID,DVector<uint8_t>); + FUNC1RC(DVector<uint8_t>,baked_light_get_light,RID); + + FUNC2(baked_light_set_sampler_octree,RID,const DVector<int>&); + FUNC1RC(DVector<int>,baked_light_get_sampler_octree,RID); + FUNC2(baked_light_set_lightmap_multiplier,RID,float); FUNC1RC(float,baked_light_get_lightmap_multiplier,RID); @@ -916,6 +922,14 @@ public: FUNC1(baked_light_clear_lightmaps,RID); + FUNC0R(RID,baked_light_sampler_create); + + FUNC3(baked_light_sampler_set_param,RID, BakedLightSamplerParam , float ); + FUNC2RC(float,baked_light_sampler_get_param,RID, BakedLightSamplerParam ); + + FUNC2(baked_light_sampler_set_resolution,RID,int); + FUNC1RC(int,baked_light_sampler_get_resolution,RID); + /* CAMERA API */ FUNC0R(RID,camera_create); @@ -929,6 +943,7 @@ public: FUNC2(camera_set_environment,RID,RID); FUNC1RC(RID,camera_get_environment,RID); + FUNC2(camera_set_use_vertical_aspect,RID,bool); FUNC2RC(bool,camera_is_using_vertical_aspect,RID,bool); @@ -998,6 +1013,7 @@ public: FUNC2(scenario_set_debug,RID,ScenarioDebugMode); FUNC2(scenario_set_environment,RID, RID); FUNC2RC(RID,scenario_get_environment,RID, RID); + FUNC2(scenario_set_fallback_environment,RID, RID); /* INSTANCING API */ @@ -1053,6 +1069,9 @@ public: FUNC2(instance_geometry_set_baked_light,RID, RID ); FUNC1RC(RID,instance_geometry_get_baked_light,RID); + FUNC2(instance_geometry_set_baked_light_sampler,RID, RID ); + FUNC1RC(RID,instance_geometry_get_baked_light_sampler,RID); + FUNC2(instance_geometry_set_baked_light_texture_index,RID, int); FUNC1RC(int,instance_geometry_get_baked_light_texture_index,RID); diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 9abfecaac6..e0238c8042 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -486,7 +486,7 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("instances_cull_aabb"),&VisualServer::instances_cull_aabb); ObjectTypeDB::bind_method(_MD("instances_cull_ray"),&VisualServer::instances_cull_ray); - ObjectTypeDB::bind_method(_MD("instances_cull_convex"),&VisualServer::instances_cull_ray); + ObjectTypeDB::bind_method(_MD("instances_cull_convex"),&VisualServer::instances_cull_convex); diff --git a/servers/visual_server.h b/servers/visual_server.h index e121f50554..ed04b0d09c 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -169,6 +169,7 @@ public: MATERIAL_FLAG_UNSHADED, MATERIAL_FLAG_ONTOP, MATERIAL_FLAG_LIGHTMAP_ON_UV2, + MATERIAL_FLAG_COLOR_ARRAY_SRGB, MATERIAL_FLAG_MAX, }; @@ -589,12 +590,35 @@ public: virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree)=0; virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const=0; + virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light)=0; + virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const=0; + + virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler)=0; + virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const=0; + virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0; virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0; virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0; virtual void baked_light_clear_lightmaps(RID p_baked_light)=0; + /* BAKED LIGHT SAMPLER */ + + virtual RID baked_light_sampler_create()=0; + + enum BakedLightSamplerParam { + BAKED_LIGHT_SAMPLER_RADIUS, + BAKED_LIGHT_SAMPLER_STRENGTH, + BAKED_LIGHT_SAMPLER_ATTENUATION, + BAKED_LIGHT_SAMPLER_DETAIL_RATIO, + BAKED_LIGHT_SAMPLER_MAX + }; + + virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value)=0; + virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const=0; + + virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution)=0; + virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const=0; /* CAMERA API */ @@ -807,7 +831,7 @@ public: virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode)=0; virtual void scenario_set_environment(RID p_scenario, RID p_environment)=0; virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const=0; - + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment)=0; /* INSTANCING API */ @@ -823,7 +847,8 @@ public: INSTANCE_ROOM, INSTANCE_PORTAL, INSTANCE_BAKED_LIGHT, - + INSTANCE_BAKED_LIGHT_SAMPLER, + INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES) }; @@ -897,9 +922,13 @@ public: virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light)=0; virtual RID instance_geometry_get_baked_light(RID p_instance) const=0; + virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler)=0; + virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const=0; + virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id)=0; virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const=0; + virtual void instance_light_set_enabled(RID p_instance,bool p_enabled)=0; virtual bool instance_light_is_enabled(RID p_instance) const=0; diff --git a/tools/collada/collada.cpp b/tools/collada/collada.cpp index 16b15426df..7a842391a4 100644 --- a/tools/collada/collada.cpp +++ b/tools/collada/collada.cpp @@ -443,7 +443,10 @@ Vector<String> Collada::_read_string_array(XMLParser& parser) { if (parser.get_node_type() == XMLParser::NODE_TEXT) { // parse String data String str = parser.get_node_data(); - array=str.split(" ",false); + array=str.split_spaces(); + //for(int i=0;i<array.size();i++) { + // print_line(itos(i)+": "+array[i]); + //} } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END) @@ -2066,6 +2069,8 @@ void Collada::_parse_animation(XMLParser& parser) { track.target=target; } + print_line("TARGET: "+track.target); + state.animation_tracks.push_back(track); if (!state.referenced_tracks.has(target)) @@ -2101,6 +2106,8 @@ void Collada::_parse_animation_clip(XMLParser& parser) { if (parser.has_attribute("name")) clip.name=parser.get_attribute_value("name"); + else if (parser.has_attribute("id")) + clip.name=parser.get_attribute_value("id"); if (parser.has_attribute("start")) clip.begin=parser.get_attribute_value("start").to_double(); if (parser.has_attribute("end")) diff --git a/tools/collada/collada.h b/tools/collada/collada.h index 360f54ec05..c5e5705105 100644 --- a/tools/collada/collada.h +++ b/tools/collada/collada.h @@ -302,6 +302,7 @@ public: Vector3 uv2; Plane tangent; Color color; + int uid; struct Weight { int bone_idx; float weight; @@ -331,21 +332,26 @@ public: bool operator<(const Vertex& p_vert) const { - if (vertex==p_vert.vertex) { - if(normal==p_vert.normal) { - if(uv==p_vert.uv) { - if(uv2==p_vert.uv2) { - return (color<p_vert.color); + if (uid==p_vert.uid) { + if (vertex==p_vert.vertex) { + if(normal==p_vert.normal) { + if(uv==p_vert.uv) { + if(uv2==p_vert.uv2) { + return (color<p_vert.color); + } else + return (uv2<p_vert.uv2); } else - return (uv2<p_vert.uv2); + return (uv<p_vert.uv); } else - return (uv<p_vert.uv); + return (normal<p_vert.normal); } else - return (normal<p_vert.normal); + return vertex<p_vert.vertex; } else - return vertex<p_vert.vertex; + return uid < p_vert.uid; } + + Vertex() { uid=0; idx=0; } }; struct Node { diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp index 319c1ad8b7..0bd21219bf 100644 --- a/tools/doc/doc_data.cpp +++ b/tools/doc/doc_data.cpp @@ -997,8 +997,8 @@ Error DocData::save(const String& p_path) { _write_string(f,1,"</constants>"); - _write_string(f,1,"<theme_items>"); if (c.theme_properties.size()) { + _write_string(f,1,"<theme_items>"); for(int i=0;i<c.theme_properties.size();i++) { @@ -1007,9 +1007,10 @@ Error DocData::save(const String& p_path) { _write_string(f,2,"</theme_item>"); } + _write_string(f,1,"</theme_items>"); } - _write_string(f,0,"</theme_items>"); + _write_string(f,0,"</class>"); } diff --git a/tools/docdump/makemd.py b/tools/docdump/makemd.py index 7cc2e9dc4b..f85d145d5e 100644 --- a/tools/docdump/makemd.py +++ b/tools/docdump/makemd.py @@ -337,7 +337,7 @@ for file in input_list: class_names.sort() -make_class_list(class_names, 3) +make_class_list(class_names, 2) for cn in class_names: c = classes[cn] diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index daba52be03..76755666eb 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -142,7 +142,7 @@ void EditorFileSystemDirectory::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_file","idx"),&EditorFileSystemDirectory::get_file); ObjectTypeDB::bind_method(_MD("get_file_path","idx"),&EditorFileSystemDirectory::get_file_path); ObjectTypeDB::bind_method(_MD("get_file_types","idx"),&EditorFileSystemDirectory::get_file_type); - ObjectTypeDB::bind_method(_MD("is_missing_sources","idx"),&EditorFileSystemDirectory::get_file_type); + ObjectTypeDB::bind_method(_MD("is_missing_sources","idx"),&EditorFileSystemDirectory::is_missing_sources); ObjectTypeDB::bind_method(_MD("get_name"),&EditorFileSystemDirectory::get_name); ObjectTypeDB::bind_method(_MD("get_parent"),&EditorFileSystemDirectory::get_parent); diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp index 819da4bb45..42260e70ba 100644 --- a/tools/editor/editor_help.cpp +++ b/tools/editor/editor_help.cpp @@ -293,7 +293,7 @@ void EditorHelpSearch::_bind_methods() { ObjectTypeDB::bind_method(_MD("_text_changed"),&EditorHelpSearch::_text_changed); ObjectTypeDB::bind_method(_MD("_confirmed"),&EditorHelpSearch::_confirmed); ObjectTypeDB::bind_method(_MD("_sbox_input"),&EditorHelpSearch::_sbox_input); - ObjectTypeDB::bind_method(_MD("_update_search"),&EditorHelpSearch::_sbox_input); + ObjectTypeDB::bind_method(_MD("_update_search"),&EditorHelpSearch::_update_search); ADD_SIGNAL(MethodInfo("go_to_help")); diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 8c3eb844b7..701704fbfa 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -69,6 +69,7 @@ #include "plugins/item_list_editor_plugin.h" #include "plugins/stream_editor_plugin.h" #include "plugins/multimesh_editor_plugin.h" +#include "plugins/mesh_editor_plugin.h" #include "plugins/theme_editor_plugin.h" #include "plugins/tile_map_editor_plugin.h" @@ -2336,6 +2337,8 @@ void EditorNode::set_edited_scene(Node *p_scene) { if (edited_scene && edited_scene->cast_to<Popup>()) edited_scene->cast_to<Popup>()->show(); //show popups scene_tree_dock->set_edited_scene(edited_scene); + if (get_scene()) + get_scene()->set_edited_scene_root(edited_scene); if (edited_scene) { if (p_scene->get_parent()!=scene_root) @@ -3974,6 +3977,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( SampleLibraryEditorPlugin(this) ) ); add_editor_plugin( memnew( ThemeEditorPlugin(this) ) ); add_editor_plugin( memnew( MultiMeshEditorPlugin(this) ) ); + add_editor_plugin( memnew( MeshInstanceEditorPlugin(this) ) ); add_editor_plugin( memnew( AnimationTreeEditorPlugin(this) ) ); add_editor_plugin( memnew( SamplePlayerEditorPlugin(this) ) ); add_editor_plugin( memnew( MeshLibraryEditorPlugin(this) ) ); diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 2b54a334bf..bc88896ebb 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -386,6 +386,8 @@ void EditorSettings::_load_defaults() { set("global/font",""); hints["global/font"]=PropertyInfo(Variant::STRING,"global/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt"); + set("global/autoscan_project_path",""); + hints["global/autoscan_project_path"]=PropertyInfo(Variant::STRING,"global/autoscan_project_path",PROPERTY_HINT_GLOBAL_DIR); set("global/default_project_path",""); hints["global/default_project_path"]=PropertyInfo(Variant::STRING,"global/default_project_path",PROPERTY_HINT_GLOBAL_DIR); set("global/default_project_export_path",""); diff --git a/tools/editor/icons/icon_baked_light.png b/tools/editor/icons/icon_baked_light.png Binary files differnew file mode 100644 index 0000000000..48039e264c --- /dev/null +++ b/tools/editor/icons/icon_baked_light.png diff --git a/tools/editor/icons/icon_baked_light_instance.png b/tools/editor/icons/icon_baked_light_instance.png Binary files differnew file mode 100644 index 0000000000..77e53aa8f6 --- /dev/null +++ b/tools/editor/icons/icon_baked_light_instance.png diff --git a/tools/editor/icons/icon_panels_2_alt.png b/tools/editor/icons/icon_panels_2_alt.png Binary files differnew file mode 100644 index 0000000000..2006f212ce --- /dev/null +++ b/tools/editor/icons/icon_panels_2_alt.png diff --git a/tools/editor/icons/icon_panels_3_alt.png b/tools/editor/icons/icon_panels_3_alt.png Binary files differnew file mode 100644 index 0000000000..5195b799a5 --- /dev/null +++ b/tools/editor/icons/icon_panels_3_alt.png diff --git a/tools/editor/icons/icon_particle_attractor_2d.png b/tools/editor/icons/icon_particle_attractor_2d.png Binary files differnew file mode 100644 index 0000000000..bb66611e45 --- /dev/null +++ b/tools/editor/icons/icon_particle_attractor_2d.png diff --git a/tools/editor/icons/icon_polygon_2d.png b/tools/editor/icons/icon_polygon_2d.png Binary files differnew file mode 100644 index 0000000000..9deb63a248 --- /dev/null +++ b/tools/editor/icons/icon_polygon_2d.png diff --git a/tools/editor/icons/icon_touch_screen_button.png b/tools/editor/icons/icon_touch_screen_button.png Binary files differnew file mode 100644 index 0000000000..16e84927f1 --- /dev/null +++ b/tools/editor/icons/icon_touch_screen_button.png diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp index 95ee1f92e2..e86356ebe9 100644 --- a/tools/editor/io_plugins/editor_import_collada.cpp +++ b/tools/editor/io_plugins/editor_import_collada.cpp @@ -694,6 +694,7 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co // Must convert to GL/DX format. int _prim_ofs=0; + int vertidx=0; for(int p_i=0;p_i<p.count;p_i++) { @@ -718,6 +719,8 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co ERR_FAIL_INDEX_V(src,p.indices.size(),ERR_INVALID_DATA); Collada::Vertex vertex; + if (p_morph_data) + vertex.uid=vertidx++; int vertex_index=p.indices[src+vertex_ofs]; //used for index field (later used by controllers) int vertex_pos = (vertex_src->stride?vertex_src->stride:3) * vertex_index; @@ -746,7 +749,7 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co Vector3 tangent =Vector3(tangent_src->array[tangent_pos+0],tangent_src->array[tangent_pos+1],tangent_src->array[tangent_pos+2]); vertex.tangent.normal=tangent; - vertex.tangent.d= vertex.normal.cross(tangent).dot(binormal) > 0 ? -1 : 1; + vertex.tangent.d= vertex.normal.cross(tangent).dot(binormal) > 0 ? 1 : -1; } } @@ -781,6 +784,8 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co vertex.vertex.z = -vertex.vertex.z; SWAP( vertex.normal.z, vertex.normal.y ); vertex.normal.z = -vertex.normal.z; + SWAP( vertex.tangent.normal.z, vertex.tangent.normal.y ); + vertex.tangent.normal.z = -vertex.tangent.normal.z; } @@ -1670,16 +1675,21 @@ void ColladaImport::_fix_param_animation_tracks() { source=skin.base; } else if (collada.state.morph_controller_data_map.has(source)) { + const Collada::MorphControllerData& morph = collada.state.morph_controller_data_map[source]; + if (morph.targets.has("MORPH_WEIGHT") && morph.targets.has("MORPH_TARGET")) { + String weights = morph.targets["MORPH_WEIGHT"]; String targets = morph.targets["MORPH_TARGET"]; + //fails here if (morph.sources.has(targets) && morph.sources.has(weights)) { const Collada::MorphControllerData::Source &weight_src=morph.sources[weights]; const Collada::MorphControllerData::Source &target_src=morph.sources[targets]; + ERR_FAIL_COND(weight_src.array.size() != target_src.sarray.size()); for(int i=0;i<weight_src.array.size();i++) { @@ -1688,6 +1698,7 @@ void ColladaImport::_fix_param_animation_tracks() { String mesh_name = target_src.sarray[i]; if (collada.state.mesh_name_map.has(mesh_name) && collada.state.referenced_tracks.has(track_name)) { + const Vector<int>&rt = collada.state.referenced_tracks[track_name]; for(int rti=0;rti<rt.size();rti++) { @@ -1718,7 +1729,7 @@ void ColladaImport::_fix_param_animation_tracks() { void ColladaImport::create_animations(bool p_make_tracks_in_all_bones) { - print_line("-=-=-=-=-PRE CA"); + _fix_param_animation_tracks(); for(int i=0;i<collada.state.animation_clips.size();i++) { @@ -1731,6 +1742,7 @@ void ColladaImport::create_animations(bool p_make_tracks_in_all_bones) { for(int i=0;i<collada.state.animation_tracks.size();i++) { Collada::AnimationTrack &at = collada.state.animation_tracks[i]; + //print_line("CHANNEL: "+at.target+" PARAM: "+at.param); if (!node_map.has(at.target)) { print_line("Coudlnt find node: "+at.target); continue; @@ -1749,7 +1761,7 @@ void ColladaImport::create_animations(bool p_make_tracks_in_all_bones) { } create_animation(-1,p_make_tracks_in_all_bones); - print_line("clipcount: "+itos(collada.state.animation_clips.size())); + //print_line("clipcount: "+itos(collada.state.animation_clips.size())); for(int i=0;i<collada.state.animation_clips.size();i++) create_animation(i,p_make_tracks_in_all_bones); @@ -1761,10 +1773,10 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones if (p_clip==-1) { - print_line("default"); + //print_line("default"); animation->set_name("default"); } else { - print_line("clip name: "+collada.state.animation_clips[p_clip].name); + //print_line("clip name: "+collada.state.animation_clips[p_clip].name); animation->set_name(collada.state.animation_clips[p_clip].name); } @@ -1836,7 +1848,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones base_snapshots.push_back(f); f+=snapshot_interval; } - print_line("anim len: "+rtos(anim_length)); + //print_line("anim len: "+rtos(anim_length)); animation->set_length(anim_length); bool tracks_found=false; @@ -1861,7 +1873,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones Collada::Node *cn = collada.state.scene_map[E->get()]; if (cn->ignore_anim) { - print_line("warning, ignoring animation on node: "+path); + //print_line("warning, ignoring animation on node: "+path); continue; } diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp index 3774b7d25b..42a185b7c2 100644 --- a/tools/editor/plugins/baked_light_baker.cpp +++ b/tools/editor/plugins/baked_light_baker.cpp @@ -4,8 +4,17 @@ #include <cmath> #include "io/marshalls.h" #include "tools/editor/editor_node.h" +#include "tools/editor/editor_settings.h" +void baked_light_baker_add_64f(double *dst,double value); +void baked_light_baker_add_64i(int64_t *dst,int64_t value); + +//-separar en 2 testuras? +//*mejorar performance y threads +//*modos lineales +//*saturacion + _FORCE_INLINE_ static uint64_t get_uv_normal_bit(const Vector3& p_vector) { int lat = Math::fast_ftoi(Math::floor(Math::acos(p_vector.dot(Vector3(0,1,0)))*6.0/Math_PI+0.5)); @@ -66,6 +75,12 @@ BakedLightBaker::MeshTexture* BakedLightBaker::_get_mat_tex(const Ref<Texture>& image.convert(Image::FORMAT_RGBA); } + if (imgtex->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR) { + Image copy = image; + copy.srgb_to_linear(); + image=copy; + } + DVector<uint8_t> dvt=image.get_data(); DVector<uint8_t>::Read r=dvt.read(); MeshTexture mt; @@ -105,8 +120,13 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m if (fm.is_valid()) { //fixed route mm.diffuse.color=fm->get_parameter(FixedMaterial::PARAM_DIFFUSE); + if (linear_color) + mm.diffuse.color=mm.diffuse.color.to_linear(); mm.diffuse.tex=_get_mat_tex(fm->get_texture(FixedMaterial::PARAM_DIFFUSE)); mm.specular.color=fm->get_parameter(FixedMaterial::PARAM_SPECULAR); + if (linear_color) + mm.specular.color=mm.specular.color.to_linear(); + mm.specular.tex=_get_mat_tex(fm->get_texture(FixedMaterial::PARAM_SPECULAR)); } else { @@ -270,6 +290,11 @@ void BakedLightBaker::_parse_geometry(Node* p_node) { dirl.type=VS::LightType(dl->get_light_type()); dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE); dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR); + if (linear_color) + dirl.diffuse=dirl.diffuse.to_linear(); + if (linear_color) + dirl.specular=dirl.specular.to_linear(); + 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(); @@ -472,8 +497,11 @@ void BakedLightBaker::_make_bvh() { } 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); + + bvh_depth = max_depth; } void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_depth) { @@ -563,6 +591,12 @@ void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_de child->aabb.pos.z+=child->aabb.size.z; + child->full_accum[0]=0; + child->full_accum[1]=0; + child->full_accum[2]=0; + child->sampler_ofs=0; + + if (stack_pos==octree_depth-1) { child->leaf=true; @@ -585,14 +619,10 @@ void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_de cell_count++; int lz = lights.size(); - child->light = memnew_arr(OctantLight,lz); - - for(int li=0;li<lz;li++) { - for(int ci=0;ci<8;ci++) { - child->light[li].accum[ci][0]=0; - child->light[li].accum[ci][1]=0; - child->light[li].accum[ci][2]=0; - } + for(int ci=0;ci<8;ci++) { + child->light_accum[ci][0]=0; + child->light_accum[ci][1]=0; + child->light_accum[ci][2]=0; } child->parent=ptr_stack[stack_pos]; @@ -797,12 +827,12 @@ void BakedLightBaker::_make_octree() { -void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, const AABB& p_plot_aabb, const Color& p_light, const Plane& p_plane) { +void BakedLightBaker::_plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos, const AABB& p_plot_aabb, const Color& p_light,const Color& p_tint_light,bool p_only_full, const Plane& p_plane) { //stackless version - uint32_t *stack=octant_stack; - uint32_t *ptr_stack=octantptr_stack; + uint32_t *stack=thread_stack.octant_stack; + uint32_t *ptr_stack=thread_stack.octantptr_stack; Octant *octants=octant_pool.ptr(); stack[0]=0; @@ -815,6 +845,29 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, Octant &octant=octants[ptr_stack[stack_pos]]; + if (stack[stack_pos]==0) { + + + Vector3 pos = octant.aabb.pos + octant.aabb.size*0.5; + float md = 1<<(octree_depth - stack_pos ); + float r=cell_size*plot_size*md; + float div = 1.0/(md*md*md); + //div=1.0; + + + float d = p_plot_pos.distance_to(pos); + + if ((p_plane.distance_to(pos)>-cell_size*1.75*md) && d<=r) { + + + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + + baked_light_baker_add_64f(&octant.full_accum[0],p_tint_light.r*intensity*div); + baked_light_baker_add_64f(&octant.full_accum[1],p_tint_light.g*intensity*div); + baked_light_baker_add_64f(&octant.full_accum[2],p_tint_light.b*intensity*div); + } + } + if (octant.leaf) { @@ -822,41 +875,44 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, //if (p_plane.normal.dot(octant.aabb.get_support(p_plane.normal)) < p_plane.d-CMP_EPSILON) { //octants behind are no go - - float r=cell_size*plot_size; - for(int i=0;i<8;i++) { - Vector3 pos=octant.aabb.pos; - if (i&1) - pos.x+=octant.aabb.size.x; - if (i&2) - pos.y+=octant.aabb.size.y; - if (i&4) - pos.z+=octant.aabb.size.z; + if (!p_only_full) { + float r=cell_size*plot_size; + for(int i=0;i<8;i++) { + Vector3 pos=octant.aabb.pos; + if (i&1) + pos.x+=octant.aabb.size.x; + if (i&2) + pos.y+=octant.aabb.size.y; + if (i&4) + pos.z+=octant.aabb.size.z; - float d = p_plot_pos.distance_to(pos); + float d = p_plot_pos.distance_to(pos); - if ((p_plane.distance_to(pos)>-cell_size*1.75) && d<=r) { + if ((p_plane.distance_to(pos)>-cell_size*1.75) && d<=r) { - float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. - if (edge_damp>0) { - Vector3 normal = Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2]); - if (normal.x>0 || normal.y>0 || normal.z>0) { + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + if (edge_damp>0) { + Vector3 normal = Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2]); + if (normal.x>0 || normal.y>0 || normal.z>0) { - float damp = Math::abs(p_plane.normal.dot(normal)); - intensity*=pow(damp,edge_damp); + float damp = Math::abs(p_plane.normal.dot(normal)); + intensity*=pow(damp,edge_damp); + } } - } - //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size); - //intensity = Math::cos(d*Math_PI*0.5/r); + //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size); + //intensity = Math::cos(d*Math_PI*0.5/r); + + baked_light_baker_add_64f(&octant.light_accum[i][0],p_light.r*intensity); + baked_light_baker_add_64f(&octant.light_accum[i][1],p_light.g*intensity); + baked_light_baker_add_64f(&octant.light_accum[i][2],p_light.b*intensity); + - octant.light[p_light_index].accum[i][0]+=p_light.r*intensity; - octant.light[p_light_index].accum[i][1]+=p_light.g*intensity; - octant.light[p_light_index].accum[i][2]+=p_light.b*intensity; + } } } @@ -893,11 +949,11 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, } -float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce,bool p_only_dist) { +float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce,bool p_only_dist) { - uint32_t* stack = ray_stack; - BVH **bstack = bvh_stack; + uint32_t* stack = thread_stack.ray_stack; + BVH **bstack = thread_stack.bvh_stack; enum { TEST_AABB_BIT=0, @@ -915,6 +971,7 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons n/=len; + real_t d=1e10; bool inters=false; Vector3 r_normal; @@ -1139,7 +1196,7 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons #endif - ret=_throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); + ret=_throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); } if (use_specular && (specular_at_point.r>CMP_EPSILON || specular_at_point.g>CMP_EPSILON || specular_at_point.b>CMP_EPSILON)) { @@ -1150,7 +1207,7 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons Vector3 rn = n - r_normal *r_normal.dot(n) * 2.0; - _throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,specular_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); + _throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,specular_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); } } @@ -1158,19 +1215,25 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons // _plot_light_point(r_point,octree,octree_aabb,p_light); - Color plot_light=diffuse_at_point; + Color plot_light=res_light.linear_interpolate(diffuse_at_point,tint); plot_light.r*=att; plot_light.g*=att; plot_light.b*=att; + Color tint_light=diffuse_at_point; + tint_light.r*=att; + tint_light.g*=att; + tint_light.b*=att; + + bool skip=false; - if (!p_first_bounce) { + if (!p_first_bounce || p_bake_direct) { float r = plot_size * cell_size*2; if (dist<r) { //avoid accumulaiton of light on corners //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size); - plot_light=Color(0,0,0,0); + skip-true; } else { @@ -1181,12 +1244,12 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons double r2 = double(rand())/RAND_MAX; double r3 = double(rand())/RAND_MAX; Vector3 rn = ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*r3*0.25)).normalized(); - float d =_throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1,false,true); - r = plot_size*cell_size*0.7; + float d =_throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1,false,true); + r = plot_size*cell_size*ao_radius; if (d>0 && d<r) { //avoid accumulaiton of light on corners //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size); - plot_light=Color(0,0,0,0); + skip=true; } else { //plot_light=Color(0,0,0,0); @@ -1195,11 +1258,9 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons } - if (!p_first_bounce || lights[p_light_index].bake_direct) { - Plane plane(r_point,r_normal); - //print_line(String(plot_light)+String(" ")+rtos(att)); - _plot_light(p_light_index,r_point,aabb,plot_light,plane); - } + Plane plane(r_point,r_normal); + if (!skip) + _plot_light(thread_stack,r_point,aabb,plot_light,tint_light,!(!p_first_bounce || p_bake_direct),plane); return dist; @@ -1305,79 +1366,100 @@ void BakedLightBaker::_make_octree_texture() { //ok let's try to just create a texture - { + int otex_w=256; - int otex_w=(1<<lattice_size)*(1<<lattice_size)*2; //make sure lattice fits horizontally - Vector3 lattice_cell_size=octree_aabb.size; - for(int i=0;i<lattice_size;i++) { + while (true) { - lattice_cell_size*=0.5; - } + uint32_t oct_idx=leaf_list; - while(true) { + int row=0; - //let's plot the leafs first, given the octree is not so obvious which size it will have - int row=4+4*(1<<lattice_size); + print_line("begin at row "+itos(row)); + int longest_line_reused=0; + int col=0; + int processed=0; + + //reset + while(oct_idx) { - uint32_t oct_idx=leaf_list; + BakedLightBaker::Octant *oct = &octants[oct_idx]; + oct->texture_x=0; + oct->texture_y=0; + oct_idx=oct->next_leaf; - //untag - while(oct_idx) { + } - BakedLightBaker::Octant *oct = &octants[oct_idx]; - //0,0 also means unprocessed - oct->texture_x=0; - oct->texture_y=0; - oct_idx=oct->next_leaf; + oct_idx=leaf_list; + //assign + while(oct_idx) { + BakedLightBaker::Octant *oct = &octants[oct_idx]; + if (oct->first_neighbour && oct->texture_x==0 && oct->texture_y==0) { + //was not processed + uint32_t current_idx=oct_idx; + int reused=0; + + while(current_idx) { + BakedLightBaker::Octant *o = &octants[current_idx]; + if (col+1 >= otex_w) { + col=0; + row+=4; + } + o->texture_x=col; + o->texture_y=row; + processed++; + + if (o->bake_neighbour) { + reused++; + } + col+=o->bake_neighbour ? 1 : 2; //reuse neighbour + current_idx=o->bake_neighbour; + } + + if (reused>longest_line_reused) { + longest_line_reused=reused; + } } + oct_idx=oct->next_leaf; + } - oct_idx=leaf_list; + row+=4; + if (otex_w < row) { - print_line("begin at row "+itos(row)); - int longest_line_reused=0; - int col=0; - int processed=0; + otex_w*=2; + } else { + + baked_light_texture_w=otex_w; + baked_light_texture_h=nearest_power_of_2(row); + print_line("w: "+itos(otex_w)); + print_line("h: "+itos(row)); + break; + } - while(oct_idx) { - BakedLightBaker::Octant *oct = &octants[oct_idx]; - if (oct->first_neighbour && oct->texture_x==0 && oct->texture_y==0) { - //was not processed - uint32_t current_idx=oct_idx; - int reused=0; + } - while(current_idx) { - BakedLightBaker::Octant *o = &octants[current_idx]; - if (col+1 >= otex_w) { - col=0; - row+=4; - } - o->texture_x=col; - o->texture_y=row; - processed++; - if (o->bake_neighbour) { - reused++; - } - col+=o->bake_neighbour ? 1 : 2; //reuse neighbour - current_idx=o->bake_neighbour; - } + { - if (reused>longest_line_reused) { - longest_line_reused=reused; - } - } - oct_idx=oct->next_leaf; - } + otex_w=(1<<lattice_size)*(1<<lattice_size)*2; //make sure lattice fits horizontally + Vector3 lattice_cell_size=octree_aabb.size; + for(int i=0;i<lattice_size;i++) { + + lattice_cell_size*=0.5; + } - print_line("processed "+itos(processed)); - print_line("longest reused: "+itos(longest_line_reused)); + + while(true) { + + //let's plot the leafs first, given the octree is not so obvious which size it will have + int row=4+4*(1<<lattice_size); + int col=0; col=0; row+=4; @@ -1478,7 +1560,25 @@ double BakedLightBaker::get_normalization(int p_light_idx) const { return nrg; } -void BakedLightBaker::throw_rays(int p_amount) { + + +double BakedLightBaker::get_modifier(int p_light_idx) const { + + double nrg=0; + + const LightData &dl=lights[p_light_idx]; + double cell_area = cell_size*cell_size;; + //nrg+= /*dl.energy */ (dl.rays_thrown * cell_area / dl.area); + nrg=cell_area; + nrg*=(Math_PI*plot_size*plot_size)*0.5; // damping of radial linear gradient kernel + nrg*=dl.constant; + //nrg*=5; + + + return nrg; +} + +void BakedLightBaker::throw_rays(ThreadStack& thread_stack,int p_amount) { @@ -1488,6 +1588,8 @@ void BakedLightBaker::throw_rays(int p_amount) { int amount = p_amount * total_light_area / dl.area; + double mod = 1.0/double(get_modifier(i)); + mod*=p_amount/float(amount); switch(dl.type) { @@ -1502,12 +1604,15 @@ void BakedLightBaker::throw_rays(int p_amount) { from+=dl.left*(r2*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; + float m = mod*dl.energy; + col.r*=m; + col.g*=m; + col.b*=m; + dl.rays_thrown++; - total_rays++; - _throw_ray(i,from,to,dl.length,col,NULL,0,0,max_bounces,true); + baked_light_baker_add_64i(&total_rays,1); + + _throw_ray(thread_stack,dl.bake_direct,from,to,dl.length,col,NULL,0,0,max_bounces,true); } } break; case VS::LIGHT_OMNI: { @@ -1543,13 +1648,14 @@ void BakedLightBaker::throw_rays(int p_amount) { #endif Vector3 to = dl.pos+dir*dl.radius; Color col=dl.diffuse; - col.r*=dl.energy; - col.g*=dl.energy; - col.b*=dl.energy; + float m = mod*dl.energy; + col.r*=m; + col.g*=m; + col.b*=m; dl.rays_thrown++; - total_rays++; - _throw_ray(i,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); + baked_light_baker_add_64i(&total_rays,1); + _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); // _throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true); } @@ -1574,13 +1680,14 @@ void BakedLightBaker::throw_rays(int p_amount) { Vector3 to = dl.pos+dir*dl.radius; Color col=dl.diffuse; - col.r*=dl.energy; - col.g*=dl.energy; - col.b*=dl.energy; + float m = mod*dl.energy; + col.r*=m; + col.g*=m; + col.b*=m; dl.rays_thrown++; - total_rays++; - _throw_ray(i,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); + baked_light_baker_add_64i(&total_rays,1); + _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); // _throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true); } @@ -1622,6 +1729,10 @@ void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) { edge_damp=baked_light->get_edge_damp(); normal_damp=baked_light->get_normal_damp(); octree_extra_margin=baked_light->get_cell_extra_margin(); + tint=baked_light->get_tint(); + ao_radius=baked_light->get_ao_radius(); + ao_strength=baked_light->get_ao_strength(); + linear_color=baked_light->get_bake_flag(BakedLight::BAKE_LINEAR_COLOR); baked_textures.clear(); for(int i=0;i<baked_light->get_lightmaps_count();i++) { @@ -1651,13 +1762,134 @@ void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) { } -void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { +void BakedLightBaker::update_octree_sampler(DVector<int> &p_sampler) { + + BakedLightBaker::Octant *octants=octant_pool.ptr(); + double norm = 1.0/double(total_rays); + + + + if (p_sampler.size()==0 || first_bake_to_map) { + + Vector<int> tmp_smp; + tmp_smp.resize(32); //32 for header + + for(int i=0;i<32;i++) { + tmp_smp[i]=0; + } + + for(int i=octant_pool_size-1;i>=0;i--) { + + if (i==0) + tmp_smp[1]=tmp_smp.size(); + + Octant &octant=octants[i]; + octant.sampler_ofs = tmp_smp.size(); + int idxcol[2]={0,0}; + + int r = CLAMP((octant.full_accum[0]*norm)*2048,0,32767); + int g = CLAMP((octant.full_accum[1]*norm)*2048,0,32767); + int b = CLAMP((octant.full_accum[2]*norm)*2048,0,32767); + + idxcol[0]|=r; + idxcol[1]|=(g<<16)|b; + + if (octant.leaf) { + tmp_smp.push_back(idxcol[0]); + tmp_smp.push_back(idxcol[1]); + } else { + + for(int j=0;j<8;j++) { + if (octant.children[j]) { + idxcol[0]|=(1<<(j+16)); + } + } + tmp_smp.push_back(idxcol[0]); + tmp_smp.push_back(idxcol[1]); + for(int j=0;j<8;j++) { + if (octant.children[j]) { + tmp_smp.push_back(octants[octant.children[j]].sampler_ofs); + if (octants[octant.children[j]].sampler_ofs==0) { + print_line("FUUUUUUUUCK"); + } + } + } + } + + } + + p_sampler.resize(tmp_smp.size()); + DVector<int>::Write w = p_sampler.write(); + int ss = tmp_smp.size(); + for(int i=0;i<ss;i++) { + w[i]=tmp_smp[i]; + } + + first_bake_to_map=false; + + } + + double gamma = baked_light->get_gamma_adjust(); + double mult = baked_light->get_energy_multiplier(); + float saturation = baked_light->get_saturation(); + + DVector<int>::Write w = p_sampler.write(); + + encode_uint32(octree_depth,(uint8_t*)&w[2]); + encode_uint32(linear_color,(uint8_t*)&w[3]); + + encode_float(octree_aabb.pos.x,(uint8_t*)&w[4]); + encode_float(octree_aabb.pos.y,(uint8_t*)&w[5]); + encode_float(octree_aabb.pos.z,(uint8_t*)&w[6]); + encode_float(octree_aabb.size.x,(uint8_t*)&w[7]); + encode_float(octree_aabb.size.y,(uint8_t*)&w[8]); + encode_float(octree_aabb.size.z,(uint8_t*)&w[9]); + + //norm*=multiplier; + + for(int i=octant_pool_size-1;i>=0;i--) { + + Octant &octant=octants[i]; + int idxcol[2]={w[octant.sampler_ofs],w[octant.sampler_ofs+1]}; + + double rf=pow(octant.full_accum[0]*norm*mult,gamma); + double gf=pow(octant.full_accum[1]*norm*mult,gamma); + double bf=pow(octant.full_accum[2]*norm*mult,gamma); + + double gray = (rf+gf+bf)/3.0; + rf = gray + (rf-gray)*saturation; + gf = gray + (gf-gray)*saturation; + bf = gray + (bf-gray)*saturation; + + + int r = CLAMP((rf)*2048,0,32767); + int g = CLAMP((gf)*2048,0,32767); + int b = CLAMP((bf)*2048,0,32767); + + idxcol[0]=((idxcol[0]>>16)<<16)|r; + idxcol[1]=(g<<16)|b; + w[octant.sampler_ofs]=idxcol[0]; + w[octant.sampler_ofs+1]=idxcol[1]; + } + +} + +void BakedLightBaker::update_octree_images(DVector<uint8_t> &p_octree,DVector<uint8_t> &p_light) { int len = baked_octree_texture_w*baked_octree_texture_h*4; - p_image.resize(len); - DVector<uint8_t>::Write w = p_image.write(); + p_octree.resize(len); + + int ilen = baked_light_texture_w*baked_light_texture_h*4; + p_light.resize(ilen); + + + DVector<uint8_t>::Write w = p_octree.write(); zeromem(w.ptr(),len); + + DVector<uint8_t>::Write iw = p_light.write(); + zeromem(iw.ptr(),ilen); + float gamma = baked_light->get_gamma_adjust(); float mult = baked_light->get_energy_multiplier(); @@ -1668,6 +1900,13 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { w[i+3]=0xFF; } + for(int i=0;i<ilen;i+=4) { + iw[i+0]=0xFF; + iw[i+1]=0; + iw[i+2]=0xFF; + iw[i+3]=0xFF; + } + float multiplier=1.0; if (baked_light->get_format()==BakedLight::FORMAT_HDR8) @@ -1678,6 +1917,9 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { encode_float(1<<lattice_size,&w[12]); encode_uint32(octree_depth-lattice_size,&w[16]); encode_uint32(multiplier,&w[20]); + encode_uint16(baked_light_texture_w,&w[24]); //if present, use the baked light texture + encode_uint16(baked_light_texture_h,&w[26]); + encode_uint32(0,&w[28]); //baked light texture format encode_float(octree_aabb.pos.x,&w[32]); encode_float(octree_aabb.pos.y,&w[36]); @@ -1690,6 +1932,7 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { BakedLightBaker::Octant *octants=octant_pool.ptr(); int octant_count=octant_pool_size; uint8_t *ptr = w.ptr(); + uint8_t *lptr = iw.ptr(); int child_offsets[8]={ @@ -1703,7 +1946,18 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { baked_octree_texture_w*8+baked_octree_texture_w*4+4, }; - Vector<double> norm_arr; + int lchild_offsets[8]={ + 0, + 4, + baked_light_texture_w*4, + baked_light_texture_w*4+4, + baked_light_texture_w*8+0, + baked_light_texture_w*8+4, + baked_light_texture_w*8+baked_light_texture_w*4, + baked_light_texture_w*8+baked_light_texture_w*4+4, + }; + + /*Vector<double> norm_arr; norm_arr.resize(lights.size()); for(int i=0;i<lights.size();i++) { @@ -1711,39 +1965,43 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { } const double *normptr=norm_arr.ptr(); - +*/ + double norm = 1.0/double(total_rays); int lz=lights.size(); mult/=multiplier; + double saturation = baked_light->get_saturation(); for(int i=0;i<octant_count;i++) { Octant &oct=octants[i]; if (oct.texture_x==0 && oct.texture_y==0) continue; - int ofs = (oct.texture_y * baked_octree_texture_w + oct.texture_x)<<2; + if (oct.leaf) { + int ofs = (oct.texture_y * baked_light_texture_w + oct.texture_x)<<2; + ERR_CONTINUE(ofs<0 || ofs >ilen); //write colors for(int j=0;j<8;j++) { //if (!oct.children[j]) // continue; - uint8_t *iptr=&ptr[ofs+child_offsets[j]]; - float r=0; - float g=0; - float b=0; - - for(int k=0;k<lz;k++) { - r+=oct.light[k].accum[j][0]*normptr[k]; - g+=oct.light[k].accum[j][1]*normptr[k]; - b+=oct.light[k].accum[j][2]*normptr[k]; - } + uint8_t *iptr=&lptr[ofs+lchild_offsets[j]]; + + float r=oct.light_accum[j][0]*norm; + float g=oct.light_accum[j][1]*norm; + float b=oct.light_accum[j][2]*norm; r=pow(r*mult,gamma); g=pow(g*mult,gamma); b=pow(b*mult,gamma); + double gray = (r+g+b)/3.0; + r = gray + (r-gray)*saturation; + g = gray + (g-gray)*saturation; + b = gray + (b-gray)*saturation; + float ic[3]={ r, g, @@ -1757,6 +2015,8 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { } else { + int ofs = (oct.texture_y * baked_octree_texture_w + oct.texture_x)<<2; + ERR_CONTINUE(ofs<0 || ofs >len); //write indices for(int j=0;j<8;j++) { @@ -1822,49 +2082,61 @@ void BakedLightBaker::_bake_thread_func(void *arg) { BakedLightBaker *ble = (BakedLightBaker*)arg; - ble->rays_at_snap_time=ble->total_rays; - ble->snap_time=OS::get_singleton()->get_ticks_usec(); - while(!ble->bake_thread_exit) { - ble->throw_rays(1000); - uint64_t t=OS::get_singleton()->get_ticks_usec(); - if (t-ble->snap_time>1000000) { + ThreadStack thread_stack; - double time = (t-ble->snap_time)/1000000.0; + thread_stack.ray_stack = memnew_arr(uint32_t,ble->bvh_depth); + thread_stack.bvh_stack = memnew_arr(BVH*,ble->bvh_depth); + thread_stack.octant_stack = memnew_arr(uint32_t,ble->octree_depth*2 ); + thread_stack.octantptr_stack = memnew_arr(uint32_t,ble->octree_depth*2 ); - int rays=ble->total_rays-ble->rays_at_snap_time; - ble->rays_sec=int(rays/time); - ble->snap_time=OS::get_singleton()->get_ticks_usec(); - ble->rays_at_snap_time=ble->total_rays; - } + while(!ble->bake_thread_exit) { + + ble->throw_rays(thread_stack,1000); } + memdelete_arr(thread_stack.ray_stack ); + memdelete_arr(thread_stack.bvh_stack ); + memdelete_arr(thread_stack.octant_stack ); + memdelete_arr(thread_stack.octantptr_stack ); + } void BakedLightBaker::_start_thread() { - if (thread!=NULL) + if (threads.size()!=0) return; bake_thread_exit=false; - thread=Thread::create(_bake_thread_func,this); + int thread_count = EDITOR_DEF("light_baker/custom_bake_threads",0); + if (thread_count<=0 || thread_count>64) + thread_count=OS::get_singleton()->get_processor_count(); + + //thread_count=1; + threads.resize(thread_count); + for(int i=0;i<threads.size();i++) { + threads[i]=Thread::create(_bake_thread_func,this); + } } void BakedLightBaker::_stop_thread() { - if (thread==NULL) + if (threads.size()==0) return; bake_thread_exit=true; - Thread::wait_to_finish(thread); - thread=NULL; + for(int i=0;i<threads.size();i++) { + Thread::wait_to_finish(threads[i]); + } + threads.clear(); } void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma) { uint8_t *ptr = &image[(y*width+x)*4]; - int lc = lights.size(); + //int lc = lights.size(); + double norm = 1.0/double(total_rays); Color color; @@ -1888,11 +2160,9 @@ void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int heigh for(int i=0;i<8;i++) { - for(int j=0;j<lc;j++) { - cols[i].x+=octant.light[j].accum[i][0]*p_norm_ptr[j]; - cols[i].y+=octant.light[j].accum[i][1]*p_norm_ptr[j]; - cols[i].z+=octant.light[j].accum[i][2]*p_norm_ptr[j]; - } + cols[i].x+=octant.light_accum[i][0]*norm; + cols[i].y+=octant.light_accum[i][1]*norm; + cols[i].z+=octant.light_accum[i][2]*norm; } @@ -2355,12 +2625,13 @@ void BakedLightBaker::clear() { memdelete_arr(octantptr_stack); if (bvh_stack) memdelete_arr(bvh_stack); - +/* + * ??? for(int i=0;i<octant_pool.size();i++) { - if (octant_pool[i].leaf) { - memdelete_arr( octant_pool[i].light ); - } Vector<double> norm_arr; - norm_arr.resize(lights.size()); + //if (octant_pool[i].leaf) { + // memdelete_arr( octant_pool[i].light ); + //} Vector<double> norm_arr; + //norm_arr.resize(lights.size()); for(int i=0;i<lights.size();i++) { norm_arr[i] = 1.0/get_normalization(i); @@ -2368,6 +2639,7 @@ void BakedLightBaker::clear() { const double *normptr=norm_arr.ptr(); } +*/ octant_pool.clear(); octant_pool_size=0; bvh=NULL; @@ -2388,8 +2660,9 @@ void BakedLightBaker::clear() { baked_octree_texture_h=0; paused=false; baking=false; - thread=NULL; + bake_thread_exit=false; + first_bake_to_map=true; baked_light=Ref<BakedLight>(); total_rays=0; @@ -2414,12 +2687,11 @@ BakedLightBaker::BakedLightBaker() { baked_octree_texture_h=0; paused=false; baking=false; - thread=NULL; + bake_thread_exit=false; - rays_at_snap_time=0; - snap_time=0; - rays_sec=0; total_rays=0; + first_bake_to_map=true; + linear_color=false; } diff --git a/tools/editor/plugins/baked_light_baker.h b/tools/editor/plugins/baked_light_baker.h index e0a9d91cd4..8fbeeddc6a 100644 --- a/tools/editor/plugins/baked_light_baker.h +++ b/tools/editor/plugins/baked_light_baker.h @@ -15,17 +15,19 @@ public: OCTANT_POOL_CHUNK=1000000 }; - struct OctantLight { + //struct OctantLight { - double accum[8][3]; - }; + // double accum[8][3]; + //}; struct Octant { bool leaf; AABB aabb; uint16_t texture_x; uint16_t texture_y; + int sampler_ofs; float normal_accum[8][3]; + double full_accum[3]; int parent; union { struct { @@ -33,7 +35,7 @@ public: float offset[3]; int bake_neighbour; bool first_neighbour; - OctantLight *light; + double light_accum[8][3]; }; int children[8]; }; @@ -234,32 +236,49 @@ public: Transform base_inv; int leaf_list; int octree_depth; + int bvh_depth; int cell_count; uint32_t *ray_stack; + BVH **bvh_stack; uint32_t *octant_stack; uint32_t *octantptr_stack; + + struct ThreadStack { + uint32_t *octant_stack; + uint32_t *octantptr_stack; + uint32_t *ray_stack; + BVH **bvh_stack; + }; + Map<Vector3,Vector3> endpoint_normal; Map<Vector3,uint64_t> endpoint_normal_bits; - BVH **bvh_stack; + float cell_size; float plot_size; //multiplied by cell size float octree_extra_margin; int max_bounces; - uint64_t total_rays; + int64_t total_rays; bool use_diffuse; bool use_specular; bool use_translucency; + bool linear_color; int baked_octree_texture_w; int baked_octree_texture_h; + int baked_light_texture_w; + int baked_light_texture_h; int lattice_size; float edge_damp; float normal_damp; + float tint; + float ao_radius; + float ao_strength; bool paused; bool baking; + bool first_bake_to_map; Map<Ref<Material>,MeshMaterial*> mat_map; Map<Ref<Texture>,MeshTexture*> tex_map; @@ -285,19 +304,16 @@ public: //void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,int p_octant=0); - void _plot_light(int p_light_index,const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,const Plane& p_plane); + void _plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,const Color& p_tint_light,bool p_only_full,const Plane& p_plane); //void _plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light); - float _throw_ray(int p_light_index,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false,bool p_only_dist=false); + float _throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false,bool p_only_dist=false); float total_light_area; - uint64_t rays_at_snap_time; - uint64_t snap_time; - int rays_sec; + Vector<Thread*> threads; - Thread *thread; bool bake_thread_exit; static void _bake_thread_func(void *arg); @@ -306,18 +322,20 @@ public: public: - void throw_rays(int p_amount); + void throw_rays(ThreadStack &thread_stack, int p_amount); double get_normalization(int p_light_idx) const; + double get_modifier(int p_light_idx) const; void bake(const Ref<BakedLight>& p_light,Node *p_base); bool is_baking(); void set_pause(bool p_pause); bool is_paused(); - int get_rays_sec() { return rays_sec; } + uint64_t get_rays_thrown() { return total_rays; } Error transfer_to_lightmaps(); - void update_octree_image(DVector<uint8_t> &p_image); + void update_octree_sampler(DVector<int> &p_sampler); + void update_octree_images(DVector<uint8_t> &p_octree,DVector<uint8_t> &p_light); Ref<BakedLight> get_baked_light() { return baked_light; } diff --git a/tools/editor/plugins/baked_light_baker_cmpxchg.cpp b/tools/editor/plugins/baked_light_baker_cmpxchg.cpp new file mode 100644 index 0000000000..d08c9f6484 --- /dev/null +++ b/tools/editor/plugins/baked_light_baker_cmpxchg.cpp @@ -0,0 +1,84 @@ + +#include "typedefs.h" + + +#ifdef WINDOWS_ENABLED + +#include "windows.h" + +void baked_light_baker_add_64f(double *dst,double value) { + + union { + int64_t i; + double f; + } swapy; + + + while(true) { + swapy.f=*dst; + int64_t from = swapy.i; + swapy.f+=value; + int64_t to=swapy.i; + int64_t result = InterlockedCompareExchange64((int64_t*)dst,to,from); + if (result==from) + break; + } + +} + +void baked_light_baker_add_64i(int64_t *dst,int64_t value) { + + while(true) { + int64_t from = *dst; + int64_t to = from+value; + int64_t result = InterlockedCompareExchange64(dst,to,from); + if (result==from) + break; + } +} + +#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 + +void baked_light_baker_add_64f(double *dst,double value) { + + + union { + int64_t i; + double f; + } swapy; + + + while(true) { + swapy.f=*dst; + int64_t from = swapy.i; + swapy.f+=value; + int64_t to=swapy.i; + if (__sync_bool_compare_and_swap((int64_t*)dst,from,to)) + break; + } +} + +void baked_light_baker_add_64i(int64_t *dst,int64_t value) { + + while(!__sync_bool_compare_and_swap(dst,*dst,(*dst)+value)) {} + +} + +#else + +//in goder (the god of programmers) we trust +#warning seems this platform or compiler does not support safe cmpxchg, your baked lighting may be funny + +void baked_light_baker_add_64f(double *dst,double value) { + + *dst+=value; + +} + +void baked_light_baker_add_64i(int64_t *dst,int64_t value) { + + *dst+=value; + +} + +#endif diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp index 3d48f2e732..2f8393f102 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.cpp +++ b/tools/editor/plugins/baked_light_editor_plugin.cpp @@ -111,7 +111,10 @@ void BakedLightEditor::_notification(int p_option) { #endif ERR_FAIL_COND(node->get_baked_light().is_null()); - baker->update_octree_image(octree_texture); + baker->update_octree_images(octree_texture,light_texture); + baker->update_octree_sampler(octree_sampler); + // print_line("sampler size: "+itos(octree_sampler.size()*4)); + #if 1 //debug Image img(baker->baked_octree_texture_w,baker->baked_octree_texture_h,0,Image::FORMAT_RGBA,octree_texture); @@ -121,11 +124,19 @@ void BakedLightEditor::_notification(int p_option) { #endif - bake_info->set_text("rays/s: "+itos(baker->get_rays_sec())); + + + uint64_t rays_snap = baker->get_rays_thrown(); + int rays_sec = (rays_snap-last_rays_time)*1.0-(update_timeout); + last_rays_time=rays_snap; + + bake_info->set_text("rays/s: "+itos(rays_sec)); update_timeout=1; print_line("MSUPDATE: "+itos(OS::get_singleton()->get_ticks_msec()-t)); t=OS::get_singleton()->get_ticks_msec(); node->get_baked_light()->set_octree(octree_texture); + node->get_baked_light()->set_light(light_texture); + node->get_baked_light()->set_sampler_octree(octree_sampler); node->get_baked_light()->set_edited(true); print_line("MSSET: "+itos(OS::get_singleton()->get_ticks_msec()-t)); @@ -195,6 +206,9 @@ void BakedLightEditor::_bake_pressed() { baker->bake(node->get_baked_light(),node); node->get_baked_light()->set_mode(BakedLight::MODE_OCTREE); update_timeout=0; + + last_rays_time=0; + set_process(true); } diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h index 7912bd92e5..27ab88d70b 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.h +++ b/tools/editor/plugins/baked_light_editor_plugin.h @@ -23,6 +23,8 @@ class BakedLightEditor : public Control { float update_timeout; DVector<uint8_t> octree_texture; + DVector<uint8_t> light_texture; + DVector<int> octree_sampler; BakedLightBaker *baker; AcceptDialog *err_dialog; @@ -33,6 +35,9 @@ class BakedLightEditor : public Control { Button *button_make_lightmaps; Label *bake_info; + uint64_t last_rays_time; + + BakedLightInstance *node; diff --git a/tools/editor/plugins/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp new file mode 100644 index 0000000000..b8a5bd3bbe --- /dev/null +++ b/tools/editor/plugins/mesh_editor_plugin.cpp @@ -0,0 +1,227 @@ +#include "mesh_editor_plugin.h" + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/physics_body.h" +#include "scene/3d/body_shape.h" +#include "scene/gui/spin_box.h" +#include "scene/gui/box_container.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/navigation_mesh.h" +#include "spatial_editor_plugin.h" + +void MeshInstanceEditor::_node_removed(Node *p_node) { + + if(p_node==node) { + node=NULL; + options->hide(); + } + +} + + + +void MeshInstanceEditor::edit(MeshInstance *p_mesh) { + + node=p_mesh; + +} + +void MeshInstanceEditor::_menu_option(int p_option) { + + Ref<Mesh> mesh = node->get_mesh(); + if (mesh.is_null()) { + err_dialog->set_text("Mesh is empty!"); + err_dialog->popup_centered(Size2(100,50)); + return; + } + + switch(p_option) { + case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: { + + Ref<Shape> shape = mesh->create_trimesh_shape(); + if (shape.is_null()) + return; + StaticBody *body = memnew( StaticBody ); + CollisionShape *cshape = memnew( CollisionShape ); + cshape->set_shape(shape); + body->add_child(cshape); + Node *owner = node==get_scene()->get_edited_scene_root() ? node : node->get_owner(); + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Create Static Trimesh"); + ur->add_do_method(node,"add_child",body); + ur->add_do_method(body,"set_owner",owner); + ur->add_do_method(cshape,"set_owner",owner); + ur->add_do_reference(body); + ur->add_undo_method(node,"remove_child",body); + ur->commit_action(); + + } break; + case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: { + + Ref<Shape> shape = mesh->create_convex_shape(); + if (shape.is_null()) + return; + StaticBody *body = memnew( StaticBody ); + CollisionShape *cshape = memnew( CollisionShape ); + cshape->set_shape(shape); + body->add_child(cshape); + Node *owner = node==get_scene()->get_edited_scene_root() ? node : node->get_owner(); + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Create Static Trimesh"); + ur->add_do_method(node,"add_child",body); + ur->add_do_method(body,"set_owner",owner); + ur->add_do_method(cshape,"set_owner",owner); + ur->add_do_reference(body); + ur->add_undo_method(node,"remove_child",body); + ur->commit_action(); + + } break; + case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: { + + + if (node==get_scene()->get_edited_scene_root()) { + err_dialog->set_text("This doesn't work on scene root!"); + err_dialog->popup_centered(Size2(100,50)); + return; + } + Ref<Shape> shape = mesh->create_trimesh_shape(); + if (shape.is_null()) + return; + CollisionShape *cshape = memnew( CollisionShape ); + cshape->set_shape(shape); + + Node *owner = node->get_owner(); + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Create Static Trimesh"); + ur->add_do_method(node->get_parent(),"add_child",cshape); + ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1); + ur->add_do_method(cshape,"set_owner",owner); + ur->add_do_reference(cshape); + ur->add_undo_method(node->get_parent(),"remove_child",cshape); + ur->commit_action(); + + } break; + case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: { + + + if (node==get_scene()->get_edited_scene_root()) { + err_dialog->set_text("This doesn't work on scene root!"); + err_dialog->popup_centered(Size2(100,50)); + return; + } + Ref<Shape> shape = mesh->create_convex_shape(); + if (shape.is_null()) + return; + CollisionShape *cshape = memnew( CollisionShape ); + cshape->set_shape(shape); + + Node *owner = node->get_owner(); + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Create Static Trimesh"); + ur->add_do_method(node->get_parent(),"add_child",cshape); + ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1); + ur->add_do_method(cshape,"set_owner",owner); + ur->add_do_reference(cshape); + ur->add_undo_method(node->get_parent(),"remove_child",cshape); + ur->commit_action(); + + } break; + case MENU_OPTION_CREATE_NAVMESH: { + + + + + Ref<NavigationMesh> nmesh = memnew( NavigationMesh ); + + if (nmesh.is_null()) + return; + + nmesh->create_from_mesh(mesh); + NavigationMeshInstance *nmi = memnew( NavigationMeshInstance ); + nmi->set_navigation_mesh(nmesh); + + Node *owner = node==get_scene()->get_edited_scene_root() ? node : node->get_owner(); + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Create Navigation Mesh"); + + ur->add_do_method(node,"add_child",nmi); + ur->add_do_method(nmi,"set_owner",owner); + + ur->add_do_reference(nmi); + ur->add_undo_method(node,"remove_child",nmi); + ur->commit_action(); + } break; + } + +} + +void MeshInstanceEditor::_bind_methods() { + + ObjectTypeDB::bind_method("_menu_option",&MeshInstanceEditor::_menu_option); +} + +MeshInstanceEditor::MeshInstanceEditor() { + + + options = memnew( MenuButton ); + //add_child(options); + SpatialEditor::get_singleton()->add_control_to_menu_panel(options); + + options->set_text("Mesh"); + options->get_popup()->add_item("Create Trimesh Static Body",MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); + options->get_popup()->add_item("Create Convex Static Body",MENU_OPTION_CREATE_STATIC_CONVEX_BODY); + options->get_popup()->add_separator(); + options->get_popup()->add_item("Create Trimesh Collision Sibling",MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE); + options->get_popup()->add_item("Create Convex Collision Sibling",MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE); + options->get_popup()->add_separator(); + options->get_popup()->add_item("Create Navigation Mesh",MENU_OPTION_CREATE_NAVMESH); + + options->get_popup()->connect("item_pressed", this,"_menu_option"); + +} + + +void MeshInstanceEditorPlugin::edit(Object *p_object) { + + mesh_editor->edit(p_object->cast_to<MeshInstance>()); +} + +bool MeshInstanceEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("MeshInstance"); +} + +void MeshInstanceEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + mesh_editor->options->show(); + } else { + + mesh_editor->options->hide(); + mesh_editor->edit(NULL); + } + +} + +MeshInstanceEditorPlugin::MeshInstanceEditorPlugin(EditorNode *p_node) { + + editor=p_node; + mesh_editor = memnew( MeshInstanceEditor ); + editor->get_viewport()->add_child(mesh_editor); + + mesh_editor->options->hide(); +} + + +MeshInstanceEditorPlugin::~MeshInstanceEditorPlugin() +{ +} + + diff --git a/tools/editor/plugins/mesh_editor_plugin.h b/tools/editor/plugins/mesh_editor_plugin.h new file mode 100644 index 0000000000..557eb90148 --- /dev/null +++ b/tools/editor/plugins/mesh_editor_plugin.h @@ -0,0 +1,68 @@ +#ifndef MESH_EDITOR_PLUGIN_H +#define MESH_EDITOR_PLUGIN_H + + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/3d/mesh_instance.h" +#include "scene/gui/spin_box.h" + + +class MeshInstanceEditor : public Node { + + OBJ_TYPE(MeshInstanceEditor, Node ); + + + enum Menu { + + MENU_OPTION_CREATE_STATIC_TRIMESH_BODY, + MENU_OPTION_CREATE_STATIC_CONVEX_BODY, + MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE, + MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE, + MENU_OPTION_CREATE_NAVMESH, + }; + + AcceptDialog *err_dialog; + + + Panel *panel; + MeshInstance *node; + + LineEdit *surface_source; + LineEdit *mesh_source; + + + void _menu_option(int p_option); +friend class MeshInstanceEditorPlugin; + MenuButton * options; + +protected: + void _node_removed(Node *p_node); + static void _bind_methods(); +public: + + void edit(MeshInstance *p_mesh); + MeshInstanceEditor(); +}; + +class MeshInstanceEditorPlugin : public EditorPlugin { + + OBJ_TYPE( MeshInstanceEditorPlugin, EditorPlugin ); + + MeshInstanceEditor *mesh_editor; + EditorNode *editor; + +public: + + virtual String get_name() const { return "MeshInstance"; } + 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); + + MeshInstanceEditorPlugin(EditorNode *p_node); + ~MeshInstanceEditorPlugin(); + +}; + +#endif // MESH_EDITOR_PLUGIN_H diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index 1c87dd0810..24e09111e2 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -1105,6 +1105,8 @@ void ScriptEditor::ensure_select_current() { if (!ste) return; Ref<Script> script = ste->get_edited_script(); + + ste->get_text_edit()->grab_focus(); } } @@ -1284,7 +1286,7 @@ void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const continue; String code = ste->get_text_edit()->get_text(); - int pos = script->get_language()->find_function(code,p_function); + int pos = script->get_language()->find_function(p_function,code); if (pos==-1) { //does not exist diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index b87b250b22..e91e7a94fe 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -860,10 +860,19 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { _edit.snap=false; _edit.mode=TRANSFORM_NONE; + //gizmo has priority over everything + bool can_select_gizmos=true; + + { + int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS); + can_select_gizmos = view_menu->get_popup()->is_item_checked( idx ); + } + - if (spatial_editor->get_selected()) { + + if (can_select_gizmos && spatial_editor->get_selected()) { Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo(); if (seg.is_valid()) { @@ -1934,6 +1943,18 @@ void SpatialEditorViewport::_menu_option(int p_option) { view_menu->get_popup()->set_item_checked( idx, current ); } break; + case VIEW_GIZMOS: { + + int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS); + bool current = view_menu->get_popup()->is_item_checked( idx ); + current=!current; + if (current) + camera->set_visible_layers( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+index))|(1<<GIZMO_EDIT_LAYER)|(1<<GIZMO_GRID_LAYER) ); + else + camera->set_visible_layers( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+index))|(1<<GIZMO_GRID_LAYER) ); + view_menu->get_popup()->set_item_checked( idx, current ); + + } break; } @@ -1950,7 +1971,7 @@ void SpatialEditorViewport::_preview_exited_scene() { void SpatialEditorViewport::_init_gizmo_instance(int p_idx) { - uint32_t layer=1<<(GIZMO_BASE_LAYER+p_idx); + uint32_t layer=1<<(GIZMO_BASE_LAYER+p_idx);//|(1<<GIZMO_GRID_LAYER); for(int i=0;i<3;i++) { move_gizmo_instance[i]=VS::get_singleton()->instance_create(); @@ -2115,6 +2136,9 @@ void SpatialEditorViewport::reset() { cursor.distance=4; cursor.region_select=false; + + + } SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) { @@ -2139,7 +2163,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed surface->set_area_as_parent_rect(); camera = memnew(Camera); camera->set_disable_gizmo(true); - camera->set_visible_layers( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+p_index)) ); + camera->set_visible_layers( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+p_index))|(1<<GIZMO_EDIT_LAYER)|(1<<GIZMO_GRID_LAYER) ); //camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment()); viewport->add_child(camera); camera->make_current(); @@ -2166,6 +2190,9 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT),true); view_menu->get_popup()->add_separator(); view_menu->get_popup()->add_check_item("Audio Listener",VIEW_AUDIO_LISTENER); + view_menu->get_popup()->add_separator(); + view_menu->get_popup()->add_check_item("Gizmos",VIEW_GIZMOS); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_GIZMOS),true); view_menu->get_popup()->add_separator(); view_menu->get_popup()->add_item("Selection (F)",VIEW_CENTER_TO_SELECTION); @@ -2348,6 +2375,10 @@ Dictionary SpatialEditor::get_state() const { vc=3; else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS) )) vc=4; + else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT) )) + vc=5; + else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT) )) + vc=6; d["viewport_mode"]=vc; Array vpdata; @@ -2358,11 +2389,16 @@ Dictionary SpatialEditor::get_state() const { d["viewports"]=vpdata; d["default_light"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT) );; + d["ambient_light_color"]=settings_ambient_color->get_color(); + + d["default_srgb"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB) );; d["show_grid"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID) );; d["show_origin"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN) );; d["fov"]=get_fov(); d["znear"]=get_znear(); d["zfar"]=get_zfar(); + d["deflight_rot_x"]=settings_default_light_rot_x; + d["deflight_rot_y"]=settings_default_light_rot_y; return d; } @@ -2389,6 +2425,10 @@ void SpatialEditor::set_state(const Dictionary& p_state) { _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS); else if (vc==4) _menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS); + else if (vc==5) + _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT); + else if (vc==6) + _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT); Array vp = d["viewports"]; ERR_FAIL_COND(vp.size()>4); @@ -2399,11 +2439,12 @@ void SpatialEditor::set_state(const Dictionary& p_state) { if (d.has("zfar")) - settings_zfar->set_text(d["zfar"]); + settings_zfar->set_val(float(d["zfar"])); if (d.has("znear")) - settings_znear->set_text(d["znear"]); + settings_znear->set_val(float(d["znear"])); if (d.has("fov")) - settings_fov->set_text(d["fov"]); + settings_fov->set_val(float(d["fov"])); + if (d.has("default_light")) { bool use = d["default_light"]; @@ -2421,7 +2462,17 @@ void SpatialEditor::set_state(const Dictionary& p_state) { } } + if (d.has("ambient_light_color")) { + settings_ambient_color->set_color(d["ambient_light_color"]); + viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,d["ambient_light_color"]); + } + if (d.has("default_srgb")) { + bool use = d["default_srgb"]; + + viewport_environment->set_enable_fx(Environment::FX_SRGB,use); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB), use ); + } if (d.has("show_grid")) { bool use = d["show_grid"]; @@ -2439,6 +2490,12 @@ void SpatialEditor::set_state(const Dictionary& p_state) { } } + if (d.has("deflight_rot_x")) + settings_default_light_rot_x=d["deflight_rot_x"]; + if (d.has("deflight_rot_y")) + settings_default_light_rot_y=d["deflight_rot_y"]; + + _update_default_light_angle(); } @@ -2601,11 +2658,29 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } else { light_instance=VisualServer::get_singleton()->instance_create2(light,get_scene()->get_root()->get_world()->get_scenario()); VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform); + + _update_default_light_angle(); } view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), light_instance.is_valid() ); } break; + case MENU_VIEW_USE_DEFAULT_SRGB: { + + bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) ); + + if (is_checked) { + viewport_environment->set_enable_fx(Environment::FX_SRGB,false); + } else { + viewport_environment->set_enable_fx(Environment::FX_SRGB,true); + } + + is_checked = ! is_checked; + + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), is_checked ); + + + } break; case MENU_VIEW_USE_1_VIEWPORT: { for(int i=1;i<4;i++) { @@ -2619,6 +2694,8 @@ void SpatialEditor::_menu_item_pressed(int p_option) { view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false ); } break; case MENU_VIEW_USE_2_VIEWPORTS: { @@ -2641,6 +2718,32 @@ void SpatialEditor::_menu_item_pressed(int p_option) { view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), true ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false ); + + } break; + case MENU_VIEW_USE_2_VIEWPORTS_ALT: { + + for(int i=1;i<4;i++) { + + if (i==1 || i==3) + viewports[i]->hide(); + else + viewports[i]->show(); + + + } + viewports[0]->set_area_as_parent_rect(); + viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5); + viewports[2]->set_area_as_parent_rect(); + viewports[2]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5); + + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), true ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false ); } break; case MENU_VIEW_USE_3_VIEWPORTS: { @@ -2665,6 +2768,34 @@ void SpatialEditor::_menu_item_pressed(int p_option) { view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), true ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false ); + + } break; + case MENU_VIEW_USE_3_VIEWPORTS_ALT: { + + for(int i=1;i<4;i++) { + + if (i==1) + viewports[i]->hide(); + else + viewports[i]->show(); + } + viewports[0]->set_area_as_parent_rect(); + viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5); + viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5); + viewports[2]->set_area_as_parent_rect(); + viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5); + viewports[2]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5); + viewports[3]->set_area_as_parent_rect(); + viewports[3]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5); + + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), true ); } break; case MENU_VIEW_USE_4_VIEWPORTS: { @@ -2690,6 +2821,8 @@ void SpatialEditor::_menu_item_pressed(int p_option) { view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), true ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false ); + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false ); } break; case MENU_VIEW_DISPLAY_NORMAL: { @@ -2758,7 +2891,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_CAMERA_SETTINGS: { - settings_dialog->popup_centered(Size2(200,160)); + settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size()+Size2(50,50)); } break; } @@ -2773,6 +2906,7 @@ void SpatialEditor::_init_indicators() { light_instance=VisualServer::get_singleton()->instance_create2(light,get_scene()->get_root()->get_world()->get_scenario()); + light_transform.rotate(Vector3(1,0,0),Math_PI/5.0); VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform); @@ -2831,10 +2965,12 @@ void SpatialEditor::_init_indicators() { VisualServer::get_singleton()->mesh_add_surface(grid[i],VisualServer::PRIMITIVE_LINES,d); VisualServer::get_singleton()->mesh_surface_set_material(grid[i],0,indicator_mat); grid_instance[i] = VisualServer::get_singleton()->instance_create2(grid[i],get_scene()->get_root()->get_world()->get_scenario()); + grid_visible[i]=false; grid_enable[i]=false; VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i],VS::INSTANCE_FLAG_VISIBLE,false); VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i],VS::INSTANCE_FLAG_CAST_SHADOW,false); + VS::get_singleton()->instance_set_layer_mask(grid_instance[i],1<<SpatialEditorViewport::GIZMO_GRID_LAYER); } @@ -2853,6 +2989,8 @@ void SpatialEditor::_init_indicators() { // VisualServer::get_singleton()->poly_add_primitive(origin,origin_points,Vector<Vector3>(),origin_colors,Vector<Vector3>()); // VisualServer::get_singleton()->poly_set_material(origin,indicator_mat,true); origin_instance = VisualServer::get_singleton()->instance_create2(origin,get_scene()->get_root()->get_world()->get_scenario()); + VS::get_singleton()->instance_set_layer_mask(origin_instance,1<<SpatialEditorViewport::GIZMO_GRID_LAYER); + VisualServer::get_singleton()->instance_geometry_set_flag(origin_instance,VS::INSTANCE_FLAG_CAST_SHADOW,false); @@ -2888,6 +3026,8 @@ void SpatialEditor::_init_indicators() { VisualServer::get_singleton()->mesh_surface_set_material(cursor_mesh,0,cmat,true); cursor_instance = VisualServer::get_singleton()->instance_create2(cursor_mesh,get_scene()->get_root()->get_world()->get_scenario()); + VS::get_singleton()->instance_set_layer_mask(cursor_instance,1<<SpatialEditorViewport::GIZMO_GRID_LAYER); + VisualServer::get_singleton()->instance_geometry_set_flag(cursor_instance,VS::INSTANCE_FLAG_CAST_SHADOW,false); @@ -3159,19 +3299,23 @@ void SpatialEditor::_notification(int p_what) { view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT),get_icon("Panels1","EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS),get_icon("Panels2","EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT),get_icon("Panels2Alt","EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS),get_icon("Panels3","EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT),get_icon("Panels3Alt","EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS),get_icon("Panels4","EditorIcons")); _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT); get_scene()->connect("node_removed",this,"_node_removed"); + VS::get_singleton()->scenario_set_fallback_environment(get_viewport()->find_world()->get_scenario(),viewport_environment->get_rid()); + } if (p_what==NOTIFICATION_ENTER_SCENE) { gizmos = memnew( SpatialEditorGizmos ); _init_indicators(); - + _update_default_light_angle(); } if (p_what==NOTIFICATION_EXIT_SCENE) { @@ -3276,8 +3420,12 @@ void SpatialEditor::_toggle_maximize_view(Object* p_viewport) { _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT); else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS) )) _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS); + else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT) )) + _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT); else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS) )) _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS); + else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT) )) + _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT); else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS) )) _menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS); } @@ -3302,7 +3450,8 @@ void SpatialEditor::_bind_methods() { // ObjectTypeDB::bind_method("_update_selection",&SpatialEditor::_update_selection); ObjectTypeDB::bind_method("_get_editor_data",&SpatialEditor::_get_editor_data); ObjectTypeDB::bind_method("_request_gizmo",&SpatialEditor::_request_gizmo); - + ObjectTypeDB::bind_method("_default_light_angle_input",&SpatialEditor::_default_light_angle_input); + ObjectTypeDB::bind_method("_update_ambient_light_color",&SpatialEditor::_update_ambient_light_color); ObjectTypeDB::bind_method("_toggle_maximize_view",&SpatialEditor::_toggle_maximize_view); ADD_SIGNAL( MethodInfo("transform_key_request") ); @@ -3312,9 +3461,9 @@ void SpatialEditor::_bind_methods() { void SpatialEditor::clear() { - settings_fov->set_text(EDITOR_DEF("3d_editor/default_fov",60.0)); - settings_znear->set_text(EDITOR_DEF("3d_editor/default_z_near",0.1)); - settings_zfar->set_text(EDITOR_DEF("3d_editor/default_z_far",1500.0)); + settings_fov->set_val(EDITOR_DEF("3d_editor/default_fov",60.0)); + settings_znear->set_val(EDITOR_DEF("3d_editor/default_z_near",0.1)); + settings_zfar->set_val(EDITOR_DEF("3d_editor/default_z_far",1500.0)); for(int i=0;i<4;i++) { viewports[i]->reset(); @@ -3338,11 +3487,54 @@ void SpatialEditor::clear() { viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(SpatialEditorViewport::VIEW_AUDIO_LISTENER),i==0); viewports[i]->viewport->set_as_audio_listener(i==0); } + view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true ); + settings_default_light_rot_x=Math_PI*0.3; + settings_default_light_rot_y=Math_PI*0.2; + + viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,Color(0.15,0.15,0.15)); + settings_ambient_color->set_color(Color(0.15,0.15,0.15)); + if (!light_instance.is_valid()) + _menu_item_pressed(MENU_VIEW_USE_DEFAULT_LIGHT); + + _update_default_light_angle(); + } + +void SpatialEditor::_update_ambient_light_color(const Color& p_color) { + + viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,settings_ambient_color->get_color()); + +} + +void SpatialEditor::_update_default_light_angle() { + + Transform t; + t.basis.rotate(Vector3(1,0,0),settings_default_light_rot_x); + t.basis.rotate(Vector3(0,1,0),settings_default_light_rot_y); + settings_dlight->set_transform(t); + if (light_instance.is_valid()) { + VS::get_singleton()->instance_set_transform(light_instance,t); + } + +} + +void SpatialEditor::_default_light_angle_input(const InputEvent& p_event) { + + + if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&(0x1|0x2|0x4)) { + + settings_default_light_rot_y = Math::fposmod(settings_default_light_rot_y - p_event.mouse_motion.relative_x*0.01,Math_PI*2.0); + settings_default_light_rot_x = Math::fposmod(settings_default_light_rot_x - p_event.mouse_motion.relative_y*0.01,Math_PI*2.0); + _update_default_light_angle(); + } + +} + + SpatialEditor::SpatialEditor(EditorNode *p_editor) { @@ -3438,11 +3630,14 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { p = view_menu->get_popup(); p->add_check_item("Use Default Light",MENU_VIEW_USE_DEFAULT_LIGHT); + p->add_check_item("Use Default sRGB",MENU_VIEW_USE_DEFAULT_SRGB); p->add_separator(); p->add_check_item("1 Viewport",MENU_VIEW_USE_1_VIEWPORT,KEY_MASK_ALT+KEY_1); p->add_check_item("2 Viewports",MENU_VIEW_USE_2_VIEWPORTS,KEY_MASK_ALT+KEY_2); + p->add_check_item("2 Viewports (Alt)",MENU_VIEW_USE_2_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_2); p->add_check_item("3 Viewports",MENU_VIEW_USE_3_VIEWPORTS,KEY_MASK_ALT+KEY_3); + p->add_check_item("3 Viewports (Alt)",MENU_VIEW_USE_3_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_3); p->add_check_item("4 Viewports",MENU_VIEW_USE_4_VIEWPORTS,KEY_MASK_ALT+KEY_4); p->add_separator(); @@ -3538,42 +3733,68 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { settings_dialog = memnew( ConfirmationDialog ); settings_dialog->set_title("Viewport Settings"); add_child(settings_dialog); - l = memnew(Label); - l->set_text("Perspective FOV (deg.):"); - l->set_pos(Point2(5,5)); - settings_dialog->add_child(l); - - settings_fov = memnew( LineEdit ); - settings_fov->set_anchor( MARGIN_RIGHT, ANCHOR_END ); - settings_fov->set_begin( Point2(15,22) ); - settings_fov->set_end( Point2(15,35) ); - settings_fov->set_text(EDITOR_DEF("3d_editor/default_fov",60.0)); - settings_dialog->add_child(settings_fov); - - l = memnew(Label); - l->set_text("View Z-Near"); - l->set_pos(Point2(5,45)); - settings_dialog->add_child(l); - - settings_znear = memnew( LineEdit ); - settings_znear->set_anchor( MARGIN_RIGHT, ANCHOR_END ); - settings_znear->set_begin( Point2(15,62) ); - settings_znear->set_end( Point2(15,75) ); - settings_znear->set_text(EDITOR_DEF("3d_editor/default_z_near",0.1)); - settings_dialog->add_child(settings_znear); - - - l = memnew(Label); - l->set_text("View Z-Far"); - l->set_pos(Point2(5,85)); - settings_dialog->add_child(l); - - settings_zfar = memnew( LineEdit ); - settings_zfar->set_anchor( MARGIN_RIGHT, ANCHOR_END ); - settings_zfar->set_begin( Point2(15,102) ); - settings_zfar->set_end( Point2(15,115) ); - settings_zfar->set_text(EDITOR_DEF("3d_editor/default_z_far",1500.0)); - settings_dialog->add_child(settings_zfar); + settings_vbc = memnew( VBoxContainer ); + settings_vbc->set_custom_minimum_size(Size2(200,0)); + settings_dialog->add_child(settings_vbc); + settings_dialog->set_child_rect(settings_vbc); + + + + settings_light_base = memnew( Control ); + settings_light_base->set_custom_minimum_size(Size2(128,128)); + settings_light_base->connect("input_event",this,"_default_light_angle_input"); + settings_vbc->add_margin_child("Default Light Normal:",settings_light_base); + settings_light_vp = memnew( Viewport ); + settings_light_vp->set_use_own_world(true); + settings_light_base->add_child(settings_light_vp); + + settings_dlight = memnew( DirectionalLight ); + settings_light_vp->add_child(settings_dlight); + settings_sphere = memnew( ImmediateGeometry ); + settings_sphere->begin(Mesh::PRIMITIVE_TRIANGLES,Ref<Texture>()); + settings_sphere->set_color(Color(1,1,1)); + settings_sphere->add_sphere(32,16,1); + settings_sphere->end(); + settings_light_vp->add_child(settings_sphere); + settings_camera = memnew( Camera ); + settings_light_vp->add_child(settings_camera); + settings_camera->set_translation(Vector3(0,0,2)); + settings_camera->set_orthogonal(2.1,0.1,5); + + settings_default_light_rot_x=Math_PI*0.3; + settings_default_light_rot_y=Math_PI*0.2; + + + + settings_ambient_color = memnew( ColorPickerButton ); + settings_vbc->add_margin_child("Ambient Light Color:",settings_ambient_color); + settings_ambient_color->connect("color_changed",this,"_update_ambient_light_color"); + + viewport_environment->set_enable_fx(Environment::FX_AMBIENT_LIGHT,true); + viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,Color(0.15,0.15,0.15)); + settings_ambient_color->set_color(Color(0.15,0.15,0.15)); + + + settings_fov = memnew( SpinBox ); + settings_fov->set_max(179); + settings_fov->set_min(1); + settings_fov->set_step(0.01); + settings_fov->set_val(EDITOR_DEF("3d_editor/default_fov",60.0)); + settings_vbc->add_margin_child("Perspective FOV (deg.):",settings_fov); + + settings_znear = memnew( SpinBox ); + settings_znear->set_max(10000); + settings_znear->set_min(0.1); + settings_znear->set_step(0.01); + settings_znear->set_val(EDITOR_DEF("3d_editor/default_z_near",0.1)); + settings_vbc->add_margin_child("View Z-Near:",settings_znear); + + settings_zfar = memnew( SpinBox ); + settings_zfar->set_max(10000); + settings_zfar->set_min(0.1); + settings_zfar->set_step(0.01); + settings_zfar->set_val(EDITOR_DEF("3d_editor/default_z_far",1500)); + settings_vbc->add_margin_child("View Z-Far:",settings_zfar); //settings_dialog->get_cancel()->hide(); /* XFORM DIALOG */ diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h index 0cfdbfaf47..1fdc97c49d 100644 --- a/tools/editor/plugins/spatial_editor_plugin.h +++ b/tools/editor/plugins/spatial_editor_plugin.h @@ -32,6 +32,8 @@ #include "tools/editor/editor_plugin.h" #include "tools/editor/editor_node.h" #include "scene/3d/visual_instance.h" +#include "scene/3d/immediate_geometry.h" +#include "scene/3d/light.h" #include "scene/gui/panel_container.h" /** @author Juan Linietsky <reduzio@gmail.com> @@ -80,11 +82,15 @@ friend class SpatialEditor; VIEW_ENVIRONMENT, VIEW_ORTHOGONAL, VIEW_AUDIO_LISTENER, + VIEW_GIZMOS, }; +public: enum { - GIZMO_BASE_LAYER=25 + GIZMO_BASE_LAYER=27, + GIZMO_EDIT_LAYER=26, + GIZMO_GRID_LAYER=25 }; - +private: int index; void _menu_option(int p_option); Size2 prev_size; @@ -344,9 +350,12 @@ private: MENU_TRANSFORM_DIALOG, MENU_VIEW_USE_1_VIEWPORT, MENU_VIEW_USE_2_VIEWPORTS, + MENU_VIEW_USE_2_VIEWPORTS_ALT, MENU_VIEW_USE_3_VIEWPORTS, + MENU_VIEW_USE_3_VIEWPORTS_ALT, MENU_VIEW_USE_4_VIEWPORTS, MENU_VIEW_USE_DEFAULT_LIGHT, + MENU_VIEW_USE_DEFAULT_SRGB, MENU_VIEW_DISPLAY_NORMAL, MENU_VIEW_DISPLAY_WIREFRAME, MENU_VIEW_DISPLAY_OVERDRAW, @@ -380,15 +389,28 @@ private: LineEdit *xform_scale[3]; OptionButton *xform_type; - LineEdit *settings_fov; - LineEdit *settings_znear; - LineEdit *settings_zfar; + VBoxContainer *settings_vbc; + SpinBox *settings_fov; + SpinBox *settings_znear; + SpinBox *settings_zfar; + DirectionalLight *settings_dlight; + ImmediateGeometry *settings_sphere; + Camera *settings_camera; + float settings_default_light_rot_x; + float settings_default_light_rot_y; + + Control *settings_light_base; + Viewport *settings_light_vp; + ColorPickerButton *settings_ambient_color; + Image settings_light_dir_image; + void _xform_dialog_action(); void _menu_item_pressed(int p_option); HBoxContainer *hbc_menu; + // // void _generate_selection_box(); @@ -418,6 +440,10 @@ private: SpatialEditorGizmos *gizmos; SpatialEditor(); + void _update_ambient_light_color(const Color& p_color); + void _update_default_light_angle(); + void _default_light_angle_input(const InputEvent& p_event); + protected: @@ -434,9 +460,9 @@ public: static SpatialEditor *get_singleton() { return singleton; } void snap_cursor_to_plane(const Plane& p_plane); - float get_znear() const { return settings_znear->get_text().to_double(); } - float get_zfar() const { return settings_zfar->get_text().to_double(); } - float get_fov() const { return settings_fov->get_text().to_double(); } + float get_znear() const { return settings_znear->get_val(); } + float get_zfar() const { return settings_zfar->get_val(); } + float get_fov() const { return settings_fov->get_val(); } Transform get_gizmo_transform() const { return gizmo.transform; } bool is_gizmo_visible() const { return gizmo.visible; } diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp index 1da29c5e7b..a0031ff456 100644 --- a/tools/editor/project_export.cpp +++ b/tools/editor/project_export.cpp @@ -529,6 +529,8 @@ void ProjectExportDialog::_group_selected() { _update_group(); //? + + _update_group_tree(); } String ProjectExportDialog::_get_selected_group() { @@ -738,6 +740,8 @@ void ProjectExportDialog::_group_changed(Variant v) { EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg"); EditorNode::get_undo_redo()->commit_action(); updating=false; + // update atlas preview button + _update_group(); } void ProjectExportDialog::_group_item_edited() { diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index 5764f9f2d9..0c32a4ba75 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -321,6 +321,7 @@ public: fdialog = memnew( FileDialog ); add_child(fdialog); fdialog->set_access(FileDialog::ACCESS_FILESYSTEM); + fdialog->set_current_dir( EditorSettings::get_singleton()->get("global/default_project_path") ); project_name->connect("text_changed", this,"_text_changed"); project_path->connect("text_changed", this,"_path_text_changed"); fdialog->connect("dir_selected", this,"_path_selected"); @@ -973,6 +974,11 @@ ProjectManager::ProjectManager() { npdialog->connect("project_created", this,"_load_recent_projects"); _load_recent_projects(); + + if ( EditorSettings::get_singleton()->get("global/autoscan_project_path") ) { + _scan_begin( EditorSettings::get_singleton()->get("global/autoscan_project_path") ); + } + //get_ok()->set_text("Open"); //get_ok()->set_text("Exit"); diff --git a/tools/editor/scenes_dock.cpp b/tools/editor/scenes_dock.cpp index 34422b4d50..3f7c82d988 100644 --- a/tools/editor/scenes_dock.cpp +++ b/tools/editor/scenes_dock.cpp @@ -200,9 +200,11 @@ void ScenesDock::_instance_pressed() { } void ScenesDock::_open_pressed(){ + TreeItem *sel = tree->get_selected(); - if (!sel) + if (!sel) { return; + } String path = sel->get_metadata(0); if (ResourceLoader::get_resource_type(path)=="PackedScene") { @@ -300,6 +302,7 @@ ScenesDock::ScenesDock(EditorNode *p_editor) { tree->set_v_size_flags(SIZE_EXPAND_FILL); tree->connect("item_edited",this,"_favorite_toggled"); + tree->connect("item_activated",this,"_open_pressed"); timer = memnew( Timer ); timer->set_one_shot(true); diff --git a/tools/editor/spatial_editor_gizmos.cpp b/tools/editor/spatial_editor_gizmos.cpp index c613a34895..04d5888861 100644 --- a/tools/editor/spatial_editor_gizmos.cpp +++ b/tools/editor/spatial_editor_gizmos.cpp @@ -36,7 +36,7 @@ #include "scene/resources/ray_shape.h"
#include "scene/resources/convex_polygon_shape.h"
#include "scene/resources/plane_shape.h"
-
+#include "quick_hull.h"
// Keep small children away from this file.
// It's so ugly it will eat them alive
@@ -75,6 +75,7 @@ void SpatialGizmoTool::Instance::create_instance(Spatial *p_base) { VS::get_singleton()->instance_set_extra_visibility_margin(instance,1);
VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_CAST_SHADOW,false);
VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_RECEIVE_SHADOWS,false);
+ VS::get_singleton()->instance_set_layer_mask(instance,1<<SpatialEditorViewport::GIZMO_EDIT_LAYER); //gizmos are 26
}
@@ -1237,6 +1238,10 @@ void SkeletonSpatialGizmo::redraw() { weights[0]=1;
+ AABB aabb;
+
+ Color bonecolor = Color(1.0,0.4,0.4,0.3);
+ Color rootcolor = Color(0.4,1.0,0.4,0.1);
for (int i=0;i<skel->get_bone_count();i++) {
@@ -1247,8 +1252,96 @@ void SkeletonSpatialGizmo::redraw() { Vector3 v0 = grests[parent].origin;
Vector3 v1 = grests[i].origin;
+ Vector3 d = (v1-v0).normalized();
+ float dist = v0.distance_to(v1);
+
+ //find closest axis
+ int closest=-1;
+ float closest_d;
+ for(int j=0;j<3;j++) {
+ float dp = Math::abs(grests[parent].basis[j].normalized().dot(d));
+ if (j==0 || dp>closest_d)
+ closest=j;
+ }
+
+ //find closest other
+ Vector3 first;
+ Vector3 points[4];
+ int pointidx=0;
+ for(int j=0;j<3;j++) {
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(rootcolor);
+ surface_tool->add_vertex(v0-grests[parent].basis[j].normalized()*dist*0.05);
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(rootcolor);
+ surface_tool->add_vertex(v0+grests[parent].basis[j].normalized()*dist*0.05);
+
+ if (j==closest)
+ continue;
+
+ Vector3 axis;
+ if (first==Vector3()) {
+ axis = d.cross(d.cross(grests[parent].basis[j])).normalized();
+ first=axis;
+ } else {
+ axis = d.cross(first).normalized();
+ }
+
+ for(int k=0;k<2;k++) {
+
+ if (k==1)
+ axis=-axis;
+ Vector3 point = v0+d*dist*0.2;
+ point+=axis*dist*0.1;
+
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(v0);
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(point);
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(point);
+ bones[0]=i;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(v1);
+ points[pointidx++]=point;
+
+ }
+
+ }
+
+ SWAP( points[1],points[2] );
+ for(int j=0;j<4;j++) {
+
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(points[j]);
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(points[(j+1)%4]);
+ }
+/*
bones[0]=parent;
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
@@ -1259,13 +1352,13 @@ void SkeletonSpatialGizmo::redraw() { surface_tool->add_weights(weights);
surface_tool->add_color(Color(0.4,1,0.4,0.4));
surface_tool->add_vertex(v1);
-
+*/
} else {
grests[i]=skel->get_bone_rest(i);
bones[0]=i;
}
-
+/*
Transform t = grests[i];
t.orthonormalize();
@@ -1302,6 +1395,7 @@ void SkeletonSpatialGizmo::redraw() { }
}
+ */
}
Ref<Mesh> m = surface_tool->commit();
@@ -1978,6 +2072,34 @@ void CollisionShapeSpatialGizmo::redraw(){ }
+ if (s->cast_to<ConvexPolygonShape>()) {
+
+ DVector<Vector3> points = s->cast_to<ConvexPolygonShape>()->get_points();
+
+ if (points.size()>3) {
+
+ QuickHull qh;
+ Vector<Vector3> varr = Variant(points);
+ Geometry::MeshData md;
+ Error err = qh.build(varr,md);
+ if (err==OK) {
+ Vector<Vector3> points;
+ points.resize(md.edges.size()*2);
+ for(int i=0;i<md.edges.size();i++) {
+ points[i*2+0]=md.vertices[md.edges[i].a];
+ points[i*2+1]=md.vertices[md.edges[i].b];
+ }
+
+
+ add_lines(points,SpatialEditorGizmos::singleton->shape_material);
+ add_collision_segments(points);
+
+ }
+ }
+
+ }
+
+
if (s->cast_to<RayShape>()) {
Ref<RayShape> rs=s;
@@ -2210,7 +2332,8 @@ void NavigationMeshSpatialGizmo::redraw() { Ref<TriangleMesh> tmesh = memnew( TriangleMesh);
tmesh->create(tmeshfaces);
- add_lines(lines,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_edge_material:SpatialEditorGizmos::singleton->navmesh_edge_material_disabled);
+ if (lines.size())
+ add_lines(lines,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_edge_material:SpatialEditorGizmos::singleton->navmesh_edge_material_disabled);
add_collision_triangles(tmesh);
Ref<Mesh> m = memnew( Mesh );
Array a;
diff --git a/tools/export/blender25/install.txt b/tools/export/blender25/install.txt index b245bbf3df..049af8848e 100644 --- a/tools/export/blender25/install.txt +++ b/tools/export/blender25/install.txt @@ -5,19 +5,7 @@ Godot Author's Own Collada Exporter scripts/addons folder (You will see many other io_scene_blahblah like folders). Copy the entire dir, not just the contents, make it just like the others. -2) Go to Blender settings and enable the "Khronos Collada" plugin +2) Go to Blender settings and enable the "Better Collada" plugin 3) Enjoy proper Collada export. -4) If it's broken, you can: - a) Flame the Blender developers in their mailing list for changing - the API every month. - b) Flame the Blender developers for not giving a home to this script - and mantaining it themselves, instead choosing to use the huge, - bloated and buggy OpenCollada based implementation that is as big - as Blender itself, while this script is a little over 1000 lines - of code, works better and has more features. - c) Cry to the poor Godot developers who are busy enough to fix it, - because they are good people and will fix it for you anyway (submit - an issue to github). - d) Be a Hero, save the day, fix it yourself and submit a pull request to - github with the changes. +4) If it's broken, contact us.
\ No newline at end of file diff --git a/tools/export/blender25/io_scene_dae/__init__.py b/tools/export/blender25/io_scene_dae/__init__.py index 29fa6ed114..b3e3f70cf0 100644 --- a/tools/export/blender25/io_scene_dae/__init__.py +++ b/tools/export/blender25/io_scene_dae/__init__.py @@ -19,14 +19,14 @@ # <pep8-80 compliant> bl_info = { - "name": "Khronos Collada format", + "name": "Better Collada Exporter", "author": "Juan Linietsky", "blender": (2, 5, 8), "api": 38691, "location": "File > Import-Export", - "description": ("Export DAE Scenes"), + "description": ("Export DAE Scenes, This plugin actually works better! otherwise contact me."), "warning": "", - "wiki_url": ("None"), + "wiki_url": ("http://www.godotengine.org"), "tracker_url": "", "support": 'OFFICIAL', "category": "Import-Export"} @@ -83,6 +83,17 @@ class ExportDAE(bpy.types.Operator, ExportHelper): description="Apply modifiers to mesh objects (on a copy!).", default=True, ) + use_tangent_arrays = BoolProperty( + name="Tangent Arrays", + description="Export Tangent and Binormal arrays (for normalmapping).", + default=False, + ) + use_triangles = BoolProperty( + name="Triangulate", + description="Export Triangles instead of Polygons.", + default=False, + ) + use_copy_images = BoolProperty( name="Copy Images", description="Copy Images (create images/ subfolder)", @@ -118,6 +129,7 @@ class ExportDAE(bpy.types.Operator, ExportHelper): description="Remove double keyframes", default=True, ) + anim_optimize_precision = FloatProperty( name="Precision", description=("Tolerence for comparing double keyframes " @@ -126,16 +138,13 @@ class ExportDAE(bpy.types.Operator, ExportHelper): soft_min=1, soft_max=16, default=6.0, ) + use_metadata = BoolProperty( name="Use Metadata", default=True, options={'HIDDEN'}, ) - export_shapekeys = BoolProperty( - name="Export Shape Keys", - default=False, - ) - + @property def check_extension(self): return True#return self.batch_mode == 'OFF' @@ -171,7 +180,7 @@ class ExportDAE(bpy.types.Operator, ExportHelper): def menu_func(self, context): - self.layout.operator(ExportDAE.bl_idname, text="Khronos Collada (.dae)") + self.layout.operator(ExportDAE.bl_idname, text="Better Collada (.dae)") def register(): diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py index 801eb7ae4c..a92b97b8a9 100644 --- a/tools/export/blender25/io_scene_dae/export_dae.py +++ b/tools/export/blender25/io_scene_dae/export_dae.py @@ -43,6 +43,7 @@ import time import math # math.pi import shutil import bpy +import bmesh from mathutils import Vector, Matrix #according to collada spec, order matters @@ -51,12 +52,14 @@ S_IMGS=1 S_FX=2 S_MATS=3 S_GEOM=4 -S_CONT=5 -S_CAMS=6 -S_LAMPS=7 -S_ANIM_CLIPS=8 -S_NODES=9 -S_ANIM=10 +S_MORPH=5 +S_SKIN=6 +S_CONT=7 +S_CAMS=8 +S_LAMPS=9 +S_ANIM_CLIPS=10 +S_NODES=11 +S_ANIM=12 CMP_EPSILON=0.0001 @@ -123,12 +126,25 @@ class DaeExporter: tup = (self.vertex.x,self.vertex.y,self.vertex.z,self.normal.x,self.normal.y,self.normal.z) for t in self.uv: tup = tup + (t.x,t.y) + if (self.color!=None): + tup = tup + (self.color.x,self.color.y,self.color.z) + if (self.tangent!=None): + tup = tup + (self.tangent.x,self.tangent.y,self.tangent.z) + if (self.bitangent!=None): + tup = tup + (self.bitangent.x,self.bitangent.y,self.bitangent.z) + #for t in self.bones: + # tup = tup + (t) + #for t in self.weights: + # tup = tup + (t) + return tup def __init__(self): self.vertex = Vector( (0.0,0.0,0.0) ) self.normal = Vector( (0.0,0.0,0.0) ) - self.color = Vector( (0.0,0.0,0.0) ) + self.tangent = None + self.bitangent = None + self.color = None self.uv = [] self.uv2 = Vector( (0.0,0.0) ) self.bones=[] @@ -281,9 +297,9 @@ class DaeExporter: self.writel(S_FX,5,'</transparency>') - self.writel(S_FX,5,'<index_of_refraction>'+str(material.specular_ior)+'</index_of_refraction>') self.writel(S_FX,4,'</'+shtype+'>') + self.writel(S_FX,4,'<index_of_refraction>'+str(material.specular_ior)+'</index_of_refraction>') self.writel(S_FX,4,'<extra>') self.writel(S_FX,5,'<technique profile="FCOLLADA">') @@ -315,16 +331,138 @@ class DaeExporter: return matid - def export_mesh(self,node,armature=None,shapename=None): + def export_mesh(self,node,armature=None,skeyindex=-1,skel_source=None): mesh = node.data - if (node.data in self.mesh_cache) and shapename==None: + + + if (node.data in self.mesh_cache): return self.mesh_cache[mesh] - if (len(node.modifiers) and self.config["use_mesh_modifiers"]) or shapename!=None: - mesh=node.to_mesh(self.scene,True,"RENDER") #is this allright? - else: - mesh=node.data + if (skeyindex==-1 and mesh.shape_keys!=None and len(mesh.shape_keys.key_blocks)): + values=[] + morph_targets=[] + md=None + for k in range(0,len(mesh.shape_keys.key_blocks)): + shape = node.data.shape_keys.key_blocks[k] + values+=[shape.value] #save value + shape.value=0 + + mid = self.new_id("morph") + + for k in range(0,len(mesh.shape_keys.key_blocks)): + + shape = node.data.shape_keys.key_blocks[k] + node.show_only_shape_key=True + node.active_shape_key_index = k + shape.value = 1.0 + mesh.update() + """ + oldval = shape.value + shape.value = 1.0 + + """ + p = node.data + v = node.to_mesh(bpy.context.scene, True, "RENDER") + node.data = v +# self.export_node(node,il,shape.name) + node.data.update() + if (armature and k==0): + md=self.export_mesh(node,armature,k,mid) + else: + md=self.export_mesh(node,None,k) + + node.data = p + node.data.update() + shape.value = 0.0 + morph_targets.append(md) + + """ + shape.value = oldval + """ + node.show_only_shape_key=False + node.active_shape_key_index = 0 + + + self.writel(S_MORPH,1,'<controller id="'+mid+'" name="">') + #if ("skin_id" in morph_targets[0]): + # self.writel(S_MORPH,2,'<morph source="#'+morph_targets[0]["skin_id"]+'" method="NORMALIZED">') + #else: + self.writel(S_MORPH,2,'<morph source="#'+morph_targets[0]["id"]+'" method="NORMALIZED">') + + self.writel(S_MORPH,3,'<source id="'+mid+'-morph-targets">') + self.writel(S_MORPH,4,'<IDREF_array id="'+mid+'-morph-targets-array" count="'+str(len(morph_targets)-1)+'">') + marr="" + warr="" + for i in range(len(morph_targets)): + if (i==0): + continue + elif (i>1): + marr+=" " + + if ("skin_id" in morph_targets[i]): + marr+=morph_targets[i]["skin_id"] + else: + marr+=morph_targets[i]["id"] + + warr+=" 0" + + self.writel(S_MORPH,5,marr) + self.writel(S_MORPH,4,'</IDREF_array>') + self.writel(S_MORPH,4,'<technique_common>') + self.writel(S_MORPH,5,'<accessor source="#'+mid+'-morph-targets-array" count="'+str(len(morph_targets)-1)+'" stride="1">') + self.writel(S_MORPH,6,'<param name="MORPH_TARGET" type="IDREF"/>') + self.writel(S_MORPH,5,'</accessor>') + self.writel(S_MORPH,4,'</technique_common>') + self.writel(S_MORPH,3,'</source>') + + self.writel(S_MORPH,3,'<source id="'+mid+'-morph-weights">') + self.writel(S_MORPH,4,'<float_array id="'+mid+'-morph-weights-array" count="'+str(len(morph_targets)-1)+'" >') + self.writel(S_MORPH,5,warr) + self.writel(S_MORPH,4,'</float_array>') + self.writel(S_MORPH,4,'<technique_common>') + self.writel(S_MORPH,5,'<accessor source="#'+mid+'-morph-weights-array" count="'+str(len(morph_targets)-1)+'" stride="1">') + self.writel(S_MORPH,6,'<param name="MORPH_WEIGHT" type="float"/>') + self.writel(S_MORPH,5,'</accessor>') + self.writel(S_MORPH,4,'</technique_common>') + self.writel(S_MORPH,3,'</source>') + + self.writel(S_MORPH,3,'<targets>') + self.writel(S_MORPH,4,'<input semantic="MORPH_TARGET" source="#'+mid+'-morph-targets"/>') + self.writel(S_MORPH,4,'<input semantic="MORPH_WEIGHT" source="#'+mid+'-morph-weights"/>') + self.writel(S_MORPH,3,'</targets>') + self.writel(S_MORPH,2,'</morph>') + self.writel(S_MORPH,1,'</controller>') + if (armature!=None): + + self.armature_for_morph[node]=armature + + meshdata={} + if (armature): + meshdata = morph_targets[0] + meshdata["morph_id"]=mid + else: + meshdata["id"]=morph_targets[0]["id"] + meshdata["morph_id"]=mid + meshdata["material_assign"]=morph_targets[0]["material_assign"] + + + + self.mesh_cache[node.data]=meshdata + return meshdata + + apply_modifiers = len(node.modifiers) and self.config["use_mesh_modifiers"] + + mesh=node.to_mesh(self.scene,apply_modifiers,"RENDER") #is this allright? + + triangulate=self.config["use_triangles"] + if (triangulate): + bm = bmesh.new() + bm.from_mesh(mesh) + bmesh.ops.triangulate(bm, faces=bm.faces) + bm.to_mesh(mesh) + bm.free() + mesh.update(calc_tessface=True) vertices=[] @@ -341,21 +479,33 @@ class DaeExporter: has_uv=False has_uv2=False has_weights=armature!=None - has_colors=False + has_tangents=self.config["use_tangent_arrays"] # could detect.. + has_colors=len(mesh.vertex_colors) mat_assign=[] uv_layer_count=len(mesh.uv_textures) + if (len(mesh.uv_textures)): + try: + mesh.calc_tangents() + except: + print("Warning, blender API is fucked up, not exporting UVs for this object.") + uv_layer_count=0 + mesh.calc_normals_split() + has_tangents=False + + else: + mesh.calc_normals_split() + has_tangents=False - for fi in range(len(mesh.tessfaces)): - f=mesh.tessfaces[fi] + for fi in range(len(mesh.polygons)): + f=mesh.polygons[fi] if (not (f.material_index in surface_indices)): surface_indices[f.material_index]=[] print("Type: "+str(type(f.material_index))) print("IDX: "+str(f.material_index)+"/"+str(len(mesh.materials))) - try: #Bizarre blender behavior i don't understand, so catching exception mat = mesh.materials[f.material_index] @@ -369,35 +519,42 @@ class DaeExporter: indices = surface_indices[f.material_index] vi=[] - #make triangles always + #vertices always 3 + """ if (len(f.vertices)==3): vi.append(0) vi.append(1) vi.append(2) elif (len(f.vertices)==4): + #todo, should use shortest path vi.append(0) vi.append(1) vi.append(2) vi.append(0) vi.append(2) vi.append(3) + """ - for x in vi: - mv = mesh.vertices[f.vertices[x]] + for lt in range(f.loop_total): + loop_index = f.loop_start + lt + ml = mesh.loops[loop_index] + mv = mesh.vertices[ml.vertex_index] v = self.Vertex() v.vertex = Vector( mv.co ) - for xt in mesh.tessface_uv_textures: - d = xt.data[fi] - uvsrc = [d.uv1,d.uv2,d.uv3,d.uv4] - v.uv.append( Vector( uvsrc[x] ) ) + for xt in mesh.uv_layers: + v.uv.append( Vector( xt.data[loop_index].uv ) ) + if (has_colors): + v.color = Vector( mesh.vertex_colors[0].data[loop_index].color ) + + v.normal = Vector( ml.normal ) + + if (has_tangents): + v.tangent = Vector( ml.tangent ) + v.bitangent = Vector( ml.bitangent ) - if (f.use_smooth): - v.normal=Vector( mv.normal ) - else: - v.normal=Vector( f.normal ) # if (armature): # v.vertex = node.matrix_world * v.vertex @@ -411,6 +568,7 @@ class DaeExporter: continue; name = node.vertex_groups[vg.group].name if (name in si["bone_index"]): + #could still put the weight as 0.0001 maybe if (vg.weight>0.001): #blender has a lot of zero weight stuff v.bones.append(si["bone_index"][name]) v.weights.append(vg.weight) @@ -419,21 +577,22 @@ class DaeExporter: tup = v.get_tup() idx = 0 - if (tup in vertex_map): + if (skeyindex==-1 and tup in vertex_map): #do not optmize if using shapekeys idx = vertex_map[tup] else: idx = len(vertices) vertices.append(v) vertex_map[tup]=idx - indices.append(idx) + vi.append(idx) + + if (len(vi)>2): + #only triangles and above + indices.append(vi) - if shapename != None: - meshid = self.new_id("mesh_"+shapename) - self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'_'+shapename+'">') - else: - meshid = self.new_id("mesh") - self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'">') + + meshid = self.new_id("mesh") + self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'">') self.writel(S_GEOM,2,'<mesh>') @@ -469,6 +628,37 @@ class DaeExporter: self.writel(S_GEOM,4,'</technique_common>') self.writel(S_GEOM,3,'</source>') + if (has_tangents): + self.writel(S_GEOM,3,'<source id="'+meshid+'-tangents">') + float_values="" + for v in vertices: + float_values+=" "+str(v.tangent.x)+" "+str(v.tangent.y)+" "+str(v.tangent.z) + self.writel(S_GEOM,4,'<float_array id="'+meshid+'-tangents-array" count="'+str(len(vertices)*3)+'">'+float_values+'</float_array>') + self.writel(S_GEOM,4,'<technique_common>') + self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-tangents-array" count="'+str(len(vertices))+'" stride="3">') + self.writel(S_GEOM,5,'<param name="X" type="float"/>') + self.writel(S_GEOM,5,'<param name="Y" type="float"/>') + self.writel(S_GEOM,5,'<param name="Z" type="float"/>') + self.writel(S_GEOM,4,'</accessor>') + self.writel(S_GEOM,4,'</technique_common>') + self.writel(S_GEOM,3,'</source>') + + self.writel(S_GEOM,3,'<source id="'+meshid+'-bitangents">') + float_values="" + for v in vertices: + float_values+=" "+str(v.bitangent.x)+" "+str(v.bitangent.y)+" "+str(v.bitangent.z) + self.writel(S_GEOM,4,'<float_array id="'+meshid+'-bitangents-array" count="'+str(len(vertices)*3)+'">'+float_values+'</float_array>') + self.writel(S_GEOM,4,'<technique_common>') + self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-bitangents-array" count="'+str(len(vertices))+'" stride="3">') + self.writel(S_GEOM,5,'<param name="X" type="float"/>') + self.writel(S_GEOM,5,'<param name="Y" type="float"/>') + self.writel(S_GEOM,5,'<param name="Z" type="float"/>') + self.writel(S_GEOM,4,'</accessor>') + self.writel(S_GEOM,4,'</technique_common>') + self.writel(S_GEOM,3,'</source>') + + + # UV Arrays for uvi in range(uv_layer_count): @@ -491,84 +681,129 @@ class DaeExporter: self.writel(S_GEOM,4,'</technique_common>') self.writel(S_GEOM,3,'</source>') + # Color Arrays + + if (has_colors): + self.writel(S_GEOM,3,'<source id="'+meshid+'-colors">') + float_values="" + for v in vertices: + float_values+=" "+str(v.color.x)+" "+str(v.color.y)+" "+str(v.color.z) + self.writel(S_GEOM,4,'<float_array id="'+meshid+'-colors-array" count="'+str(len(vertices)*3)+'">'+float_values+'</float_array>') + self.writel(S_GEOM,4,'<technique_common>') + self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-colors-array" count="'+str(len(vertices))+'" stride="3">') + self.writel(S_GEOM,5,'<param name="X" type="float"/>') + self.writel(S_GEOM,5,'<param name="Y" type="float"/>') + self.writel(S_GEOM,5,'<param name="Z" type="float"/>') + self.writel(S_GEOM,4,'</accessor>') + self.writel(S_GEOM,4,'</technique_common>') + self.writel(S_GEOM,3,'</source>') + # Triangle Lists self.writel(S_GEOM,3,'<vertices id="'+meshid+'-vertices">') self.writel(S_GEOM,4,'<input semantic="POSITION" source="#'+meshid+'-positions"/>') self.writel(S_GEOM,3,'</vertices>') + prim_type="" + if (triangulate): + prim_type="triangles" + else: + prim_type="polygons" + + for m in surface_indices: indices = surface_indices[m] mat = materials[m] + if (mat!=None): matref = self.new_id("trimat") - self.writel(S_GEOM,3,'<triangles count="'+str(int(len(indices)/3))+'" material="'+matref+'">') # todo material + self.writel(S_GEOM,3,'<'+prim_type+' count="'+str(int(len(indices)))+'" material="'+matref+'">') # todo material mat_assign.append( (mat,matref) ) else: - self.writel(S_GEOM,3,'<triangles count="'+str(int(len(indices)/3))+'">') # todo material + self.writel(S_GEOM,3,'<'+prim_type+' count="'+str(int(len(indices)))+'">') # todo material + + self.writel(S_GEOM,4,'<input semantic="VERTEX" source="#'+meshid+'-vertices" offset="0"/>') - self.writel(S_GEOM,4,'<input semantic="NORMAL" source="#'+meshid+'-normals" offset="1"/>') - extra_indices=0 + self.writel(S_GEOM,4,'<input semantic="NORMAL" source="#'+meshid+'-normals" offset="0"/>') + for uvi in range(uv_layer_count): - self.writel(S_GEOM,4,'<input semantic="TEXCOORD" source="#'+meshid+'-texcoord-'+str(uvi)+'" offset="'+str(2+uvi)+'" set="'+str(uvi)+'"/>') - extra_indices+=1 + self.writel(S_GEOM,4,'<input semantic="TEXCOORD" source="#'+meshid+'-texcoord-'+str(uvi)+'" offset="0" set="'+str(uvi)+'"/>') + + if (has_colors): + self.writel(S_GEOM,4,'<input semantic="COLOR" source="#'+meshid+'-colors" offset="0"/>') + if (has_tangents): + self.writel(S_GEOM,4,'<input semantic="TEXTANGENT" source="#'+meshid+'-tangents" offset="0"/>') + self.writel(S_GEOM,4,'<input semantic="TEXBINORMAL" source="#'+meshid+'-bitangents" offset="0"/>') + + if (triangulate): + int_values="<p>" + for p in indices: + for i in p: + int_values+=" "+str(i) + int_values+=" </p>" + self.writel(S_GEOM,4,int_values) + else: + for p in indices: + int_values="<p>" + for i in p: + int_values+=" "+str(i) + int_values+=" </p>" + self.writel(S_GEOM,4,int_values) - int_values="<p>" - for i in range(len(indices)): - int_values+=" "+str(indices[i]) # vertex index - int_values+=" "+str(indices[i]) # normal index - for e in range(extra_indices): - int_values+=" "+str(indices[i]) # normal index - int_values+="</p>" - self.writel(S_GEOM,4,int_values) - self.writel(S_GEOM,3,'</triangles>') + self.writel(S_GEOM,3,'</'+prim_type+'>') self.writel(S_GEOM,2,'</mesh>') self.writel(S_GEOM,1,'</geometry>') + meshdata={} meshdata["id"]=meshid meshdata["material_assign"]=mat_assign - self.mesh_cache[node.data]=meshdata + if (skeyindex==-1): + self.mesh_cache[node.data]=meshdata # Export armature data (if armature exists) - if (armature!=None): + if (armature!=None and (skel_source!=None or skeyindex==-1)): contid = self.new_id("controller") - self.writel(S_CONT,1,'<controller id="'+contid+'">') - self.writel(S_CONT,2,'<skin source="'+meshid+'">') - self.writel(S_CONT,3,'<bind_shape_matrix>'+strmtx(node.matrix_world)+'</bind_shape_matrix>') + self.writel(S_SKIN,1,'<controller id="'+contid+'">') + if (skel_source!=None): + self.writel(S_SKIN,2,'<skin source="#'+skel_source+'">') + else: + self.writel(S_SKIN,2,'<skin source="#'+meshid+'">') + + self.writel(S_SKIN,3,'<bind_shape_matrix>'+strmtx(node.matrix_world)+'</bind_shape_matrix>') #Joint Names - self.writel(S_CONT,3,'<source id="'+contid+'-joints">') + self.writel(S_SKIN,3,'<source id="'+contid+'-joints">') name_values="" for v in si["bone_names"]: name_values+=" "+v - self.writel(S_CONT,4,'<Name_array id="'+contid+'-joints-array" count="'+str(len(si["bone_names"]))+'">'+name_values+'</Name_array>') - self.writel(S_CONT,4,'<technique_common>') - self.writel(S_CONT,4,'<accessor source="#'+contid+'-joints-array" count="'+str(len(si["bone_names"]))+'" stride="1">') - self.writel(S_CONT,5,'<param name="JOINT" type="Name"/>') - self.writel(S_CONT,4,'</accessor>') - self.writel(S_CONT,4,'</technique_common>') - self.writel(S_CONT,3,'</source>') + self.writel(S_SKIN,4,'<Name_array id="'+contid+'-joints-array" count="'+str(len(si["bone_names"]))+'">'+name_values+'</Name_array>') + self.writel(S_SKIN,4,'<technique_common>') + self.writel(S_SKIN,4,'<accessor source="#'+contid+'-joints-array" count="'+str(len(si["bone_names"]))+'" stride="1">') + self.writel(S_SKIN,5,'<param name="JOINT" type="Name"/>') + self.writel(S_SKIN,4,'</accessor>') + self.writel(S_SKIN,4,'</technique_common>') + self.writel(S_SKIN,3,'</source>') #Pose Matrices! - self.writel(S_CONT,3,'<source id="'+contid+'-bind_poses">') + self.writel(S_SKIN,3,'<source id="'+contid+'-bind_poses">') pose_values="" for v in si["bone_bind_poses"]: pose_values+=" "+strmtx(v) - self.writel(S_CONT,4,'<float_array id="'+contid+'-bind_poses-array" count="'+str(len(si["bone_bind_poses"])*16)+'">'+pose_values+'</float_array>') - self.writel(S_CONT,4,'<technique_common>') - self.writel(S_CONT,4,'<accessor source="#'+contid+'-bind_poses-array" count="'+str(len(si["bone_bind_poses"]))+'" stride="16">') - self.writel(S_CONT,5,'<param name="TRANSFORM" type="float4x4"/>') - self.writel(S_CONT,4,'</accessor>') - self.writel(S_CONT,4,'</technique_common>') - self.writel(S_CONT,3,'</source>') + self.writel(S_SKIN,4,'<float_array id="'+contid+'-bind_poses-array" count="'+str(len(si["bone_bind_poses"])*16)+'">'+pose_values+'</float_array>') + self.writel(S_SKIN,4,'<technique_common>') + self.writel(S_SKIN,4,'<accessor source="#'+contid+'-bind_poses-array" count="'+str(len(si["bone_bind_poses"]))+'" stride="16">') + self.writel(S_SKIN,5,'<param name="TRANSFORM" type="float4x4"/>') + self.writel(S_SKIN,4,'</accessor>') + self.writel(S_SKIN,4,'</technique_common>') + self.writel(S_SKIN,3,'</source>') #Skin Weights! - self.writel(S_CONT,3,'<source id="'+contid+'-skin_weights">') + self.writel(S_SKIN,3,'<source id="'+contid+'-skin_weights">') skin_weights="" skin_weights_total=0 for v in vertices: @@ -576,22 +811,22 @@ class DaeExporter: for w in v.weights: skin_weights+=" "+str(w) - self.writel(S_CONT,4,'<float_array id="'+contid+'-skin_weights-array" count="'+str(skin_weights_total)+'">'+skin_weights+'</float_array>') - self.writel(S_CONT,4,'<technique_common>') - self.writel(S_CONT,4,'<accessor source="#'+contid+'-skin_weights-array" count="'+str(skin_weights_total)+'" stride="1">') - self.writel(S_CONT,5,'<param name="WEIGHT" type="float"/>') - self.writel(S_CONT,4,'</accessor>') - self.writel(S_CONT,4,'</technique_common>') - self.writel(S_CONT,3,'</source>') - - - self.writel(S_CONT,3,'<joints>') - self.writel(S_CONT,4,'<input semantic="JOINT" source="#'+contid+'-joints"/>') - self.writel(S_CONT,4,'<input semantic="INV_BIND_MATRIX" source="#'+contid+'-bind_poses"/>') - self.writel(S_CONT,3,'</joints>') - self.writel(S_CONT,3,'<vertex_weights count="'+str(len(vertices))+'">') - self.writel(S_CONT,4,'<input semantic="JOINT" source="#'+contid+'-joints" offset="0"/>') - self.writel(S_CONT,4,'<input semantic="WEIGHT" source="#'+contid+'-skin_weights" offset="1"/>') + self.writel(S_SKIN,4,'<float_array id="'+contid+'-skin_weights-array" count="'+str(skin_weights_total)+'">'+skin_weights+'</float_array>') + self.writel(S_SKIN,4,'<technique_common>') + self.writel(S_SKIN,4,'<accessor source="#'+contid+'-skin_weights-array" count="'+str(skin_weights_total)+'" stride="1">') + self.writel(S_SKIN,5,'<param name="WEIGHT" type="float"/>') + self.writel(S_SKIN,4,'</accessor>') + self.writel(S_SKIN,4,'</technique_common>') + self.writel(S_SKIN,3,'</source>') + + + self.writel(S_SKIN,3,'<joints>') + self.writel(S_SKIN,4,'<input semantic="JOINT" source="#'+contid+'-joints"/>') + self.writel(S_SKIN,4,'<input semantic="INV_BIND_MATRIX" source="#'+contid+'-bind_poses"/>') + self.writel(S_SKIN,3,'</joints>') + self.writel(S_SKIN,3,'<vertex_weights count="'+str(len(vertices))+'">') + self.writel(S_SKIN,4,'<input semantic="JOINT" source="#'+contid+'-joints" offset="0"/>') + self.writel(S_SKIN,4,'<input semantic="WEIGHT" source="#'+contid+'-skin_weights" offset="1"/>') vcounts="" vs="" vcount=0 @@ -601,20 +836,20 @@ class DaeExporter: vs+=" "+str(b) vs+=" "+str(vcount) vcount+=1 - self.writel(S_CONT,4,'<vcount>'+vcounts+'</vcount>') - self.writel(S_CONT,4,'<v>'+vs+'</v>') - self.writel(S_CONT,3,'</vertex_weights>') + self.writel(S_SKIN,4,'<vcount>'+vcounts+'</vcount>') + self.writel(S_SKIN,4,'<v>'+vs+'</v>') + self.writel(S_SKIN,3,'</vertex_weights>') - self.writel(S_CONT,2,'</skin>') - self.writel(S_CONT,1,'</controller>') + self.writel(S_SKIN,2,'</skin>') + self.writel(S_SKIN,1,'</controller>') meshdata["skin_id"]=contid return meshdata - def export_mesh_node(self,node,il,shapename=None): + def export_mesh_node(self,node,il): if (node.data==None): return @@ -624,14 +859,19 @@ class DaeExporter: if (node.parent.type=="ARMATURE"): armature=node.parent - meshdata = self.export_mesh(node,armature,shapename) + meshdata = self.export_mesh(node,armature) + close_controller=False - if (armature==None): - self.writel(S_NODES,il,'<instance_geometry url="#'+meshdata["id"]+'">') - else: + if ("skin_id" in meshdata): + close_controller=True self.writel(S_NODES,il,'<instance_controller url="#'+meshdata["skin_id"]+'">') for sn in self.skeleton_info[armature]["skeleton_nodes"]: self.writel(S_NODES,il+1,'<skeleton>#'+sn+'</skeleton>') + elif ("morph_id" in meshdata): + self.writel(S_NODES,il,'<instance_controller url="#'+meshdata["morph_id"]+'">') + close_controller=True + elif (armature==None): + self.writel(S_NODES,il,'<instance_geometry url="#'+meshdata["id"]+'">') if (len(meshdata["material_assign"])>0): @@ -644,17 +884,17 @@ class DaeExporter: self.writel(S_NODES,il+2,'</technique_common>') self.writel(S_NODES,il+1,'</bind_material>') - if (armature==None): - self.writel(S_NODES,il,'</instance_geometry>') - else: + if (close_controller): self.writel(S_NODES,il,'</instance_controller>') + else: + self.writel(S_NODES,il,'</instance_geometry>') def export_armature_bone(self,bone,il,si): boneid = self.new_id("bone") boneidx = si["bone_count"] si["bone_count"]+=1 - bonesid = si["name"]+"-"+str(boneidx) + bonesid = si["id"]+"-"+str(boneidx) si["bone_index"][bone.name]=boneidx si["bone_ids"][bone]=boneid si["bone_names"].append(bonesid) @@ -683,7 +923,7 @@ class DaeExporter: self.skeletons.append(node) armature = node.data - self.skeleton_info[node]={ "bone_count":0, "name":node.name, "bone_index":{},"bone_ids":{},"bone_names":[],"bone_bind_poses":[],"skeleton_nodes":[],"armature_xform":node.matrix_world } + self.skeleton_info[node]={ "bone_count":0, "id":self.new_id("skelbones"),"name":node.name, "bone_index":{},"bone_ids":{},"bone_names":[],"bone_bind_poses":[],"skeleton_nodes":[],"armature_xform":node.matrix_world } @@ -739,7 +979,7 @@ class DaeExporter: light=node.data lightid=self.new_id("light") self.writel(S_LAMPS,1,'<light id="'+lightid+'" name="'+light.name+'">') - self.writel(S_LAMPS,2,'<optics>') + #self.writel(S_LAMPS,2,'<optics>') self.writel(S_LAMPS,3,'<technique_common>') if (light.type=="POINT"): @@ -767,7 +1007,7 @@ class DaeExporter: self.writel(S_LAMPS,3,'</technique_common>') - self.writel(S_LAMPS,2,'</optics>') + #self.writel(S_LAMPS,2,'</optics>') self.writel(S_LAMPS,1,'</light>') @@ -912,21 +1152,18 @@ class DaeExporter: - def export_node(self,node,il,shapename=None): + def export_node(self,node,il): if (not self.is_node_valid(node)): return bpy.context.scene.objects.active = node - if shapename != None: - self.writel(S_NODES,il,'<node id="'+self.validate_id(node.name + '_' + shapename)+'" name="'+node.name+'_'+shapename+'" type="NODE">') - else: - self.writel(S_NODES,il,'<node id="'+self.validate_id(node.name)+'" name="'+node.name+'" type="NODE">') + self.writel(S_NODES,il,'<node id="'+self.validate_id(node.name)+'" name="'+node.name+'" type="NODE">') il+=1 self.writel(S_NODES,il,'<matrix sid="transform">'+strmtx(node.matrix_local)+'</matrix>') print("NODE TYPE: "+node.type+" NAME: "+node.name) if (node.type=="MESH"): - self.export_mesh_node(node,il,shapename) + self.export_mesh_node(node,il) elif (node.type=="CURVE"): self.export_curve_node(node,il) elif (node.type=="ARMATURE"): @@ -937,22 +1174,9 @@ class DaeExporter: self.export_lamp_node(node,il) self.valid_nodes.append(node) - if shapename==None: - for x in node.children: - self.export_node(x,il) - if node.type=="MESH" and self.config["export_shapekeys"]: - for k in range(0,len(node.data.shape_keys.key_blocks)): - shape = node.data.shape_keys.key_blocks[k] - oldval = shape.value - shape.value = 1.0 - node.active_shape_key_index = k - p = node.data - v = node.to_mesh(bpy.context.scene, True, "RENDER") - node.data = v - self.export_node(node,il,shape.name) - node.data = p - node.data.update() - shape.value = oldval + for x in node.children: + self.export_node(x,il) + il-=1 self.writel(S_NODES,il,'</node>') @@ -1003,18 +1227,22 @@ class DaeExporter: self.writel(S_ASSET,0,'</asset>') - def export_animation_transform_channel(self,target,transform_keys): + def export_animation_transform_channel(self,target,keys,matrices=True): - frame_total=len(transform_keys) + frame_total=len(keys) anim_id=self.new_id("anim") self.writel(S_ANIM,1,'<animation id="'+anim_id+'">') source_frames = "" source_transforms = "" source_interps = "" - for k in transform_keys: + for k in keys: source_frames += " "+str(k[0]) - source_transforms += " "+strmtx(k[1]) + if (matrices): + source_transforms += " "+strmtx(k[1]) + else: + source_transforms += " "+str(k[1]) + source_interps +=" LINEAR" @@ -1022,27 +1250,38 @@ class DaeExporter: self.writel(S_ANIM,2,'<source id="'+anim_id+'-input">') self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-input-array" count="'+str(frame_total)+'">'+source_frames+'</float_array>') self.writel(S_ANIM,3,'<technique_common>') - self.writel(S_ANIM,4,'<accessor source="'+anim_id+'-input-array" count="'+str(frame_total)+'" stride="1">') + self.writel(S_ANIM,4,'<accessor source="#'+anim_id+'-input-array" count="'+str(frame_total)+'" stride="1">') self.writel(S_ANIM,5,'<param name="TIME" type="float"/>') self.writel(S_ANIM,4,'</accessor>') self.writel(S_ANIM,3,'</technique_common>') self.writel(S_ANIM,2,'</source>') - # Transform Source - self.writel(S_ANIM,2,'<source id="'+anim_id+'-transform-output">') - self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-transform-output-array" count="'+str(frame_total*16)+'">'+source_transforms+'</float_array>') - self.writel(S_ANIM,3,'<technique_common>') - self.writel(S_ANIM,4,'<accessor source="'+anim_id+'-transform-output-array" count="'+str(frame_total)+'" stride="16">') - self.writel(S_ANIM,5,'<param name="TRANSFORM" type="float4x4"/>') - self.writel(S_ANIM,4,'</accessor>') - self.writel(S_ANIM,3,'</technique_common>') - self.writel(S_ANIM,2,'</source>') + if (matrices): + # Transform Source + self.writel(S_ANIM,2,'<source id="'+anim_id+'-transform-output">') + self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-transform-output-array" count="'+str(frame_total*16)+'">'+source_transforms+'</float_array>') + self.writel(S_ANIM,3,'<technique_common>') + self.writel(S_ANIM,4,'<accessor source="#'+anim_id+'-transform-output-array" count="'+str(frame_total)+'" stride="16">') + self.writel(S_ANIM,5,'<param name="TRANSFORM" type="float4x4"/>') + self.writel(S_ANIM,4,'</accessor>') + self.writel(S_ANIM,3,'</technique_common>') + self.writel(S_ANIM,2,'</source>') + else: + # Value Source + self.writel(S_ANIM,2,'<source id="'+anim_id+'-transform-output">') + self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-transform-output-array" count="'+str(frame_total)+'">'+source_transforms+'</float_array>') + self.writel(S_ANIM,3,'<technique_common>') + self.writel(S_ANIM,4,'<accessor source="#'+anim_id+'-transform-output-array" count="'+str(frame_total)+'" stride="1">') + self.writel(S_ANIM,5,'<param name="X" type="float"/>') + self.writel(S_ANIM,4,'</accessor>') + self.writel(S_ANIM,3,'</technique_common>') + self.writel(S_ANIM,2,'</source>') # Interpolation Source self.writel(S_ANIM,2,'<source id="'+anim_id+'-interpolation-output">') self.writel(S_ANIM,3,'<Name_array id="'+anim_id+'-interpolation-output-array" count="'+str(frame_total)+'">'+source_interps+'</Name_array>') self.writel(S_ANIM,3,'<technique_common>') - self.writel(S_ANIM,4,'<accessor source="'+anim_id+'-interpolation-output-array" count="'+str(frame_total)+'" stride="1">') + self.writel(S_ANIM,4,'<accessor source="#'+anim_id+'-interpolation-output-array" count="'+str(frame_total)+'" stride="1">') self.writel(S_ANIM,5,'<param name="INTERPOLATION" type="Name"/>') self.writel(S_ANIM,4,'</accessor>') self.writel(S_ANIM,3,'</technique_common>') @@ -1053,7 +1292,10 @@ class DaeExporter: self.writel(S_ANIM,3,'<input semantic="OUTPUT" source="#'+anim_id+'-transform-output"/>') self.writel(S_ANIM,3,'<input semantic="INTERPOLATION" source="#'+anim_id+'-interpolation-output"/>') self.writel(S_ANIM,2,'</sampler>') - self.writel(S_ANIM,2,'<channel source="#'+anim_id+'-sampler" target="'+target+'/transform"/>') + if (matrices): + self.writel(S_ANIM,2,'<channel source="#'+anim_id+'-sampler" target="'+target+'/transform"/>') + else: + self.writel(S_ANIM,2,'<channel source="#'+anim_id+'-sampler" target="'+target+'"/>') self.writel(S_ANIM,1,'</animation>') return [anim_id] @@ -1075,6 +1317,7 @@ class DaeExporter: tcn = [] xform_cache={} + blend_cache={} # Change frames first, export objects last # This improves performance enormously @@ -1089,9 +1332,26 @@ class DaeExporter: if (not node in self.valid_nodes): continue if (allowed!=None and not (node in allowed)): - continue + if (node.type=="MESH" and node.data!=None and (node in self.armature_for_morph) and (self.armature_for_morph[node] in allowed)): + pass #all good you pass with flying colors for morphs inside of action + else: + continue + if (node.type=="MESH" and node.data!=None and node.data.shape_keys!=None and (node.data in self.mesh_cache) and len(node.data.shape_keys.key_blocks)): + target = self.mesh_cache[node.data]["morph_id"] + for i in range(len(node.data.shape_keys.key_blocks)): + + if (i==0): + continue + + name=target+"-morph-weights("+str(i-1)+")" + if (not (name in blend_cache)): + blend_cache[name]=[] + + blend_cache[name].append( (key,node.data.shape_keys.key_blocks[i].value) ) + if (node.type=="MESH" and node.parent and node.parent.type=="ARMATURE"): + continue #In Collada, nodes that have skin modifier must not export animation, animate the skin instead. if (len(node.constraints)>0 or node.animation_data!=None): @@ -1108,6 +1368,7 @@ class DaeExporter: if (node.type=="ARMATURE"): #All bones exported for now + for bone in node.data.bones: bone_name=self.skeleton_info[node]["bone_ids"][bone] @@ -1138,7 +1399,9 @@ class DaeExporter: #export animation xml for nid in xform_cache: - tcn+=self.export_animation_transform_channel(nid,xform_cache[nid]) + tcn+=self.export_animation_transform_channel(nid,xform_cache[nid],True) + for nid in blend_cache: + tcn+=self.export_animation_transform_channel(nid,blend_cache[nid],False) return tcn @@ -1197,13 +1460,15 @@ class DaeExporter: print("Export anim: "+x.name) self.writel(S_ANIM_CLIPS,1,'<animation_clip name="'+x.name+'" start="'+str(start)+'" end="'+str(end)+'">') for z in tcn: - self.writel(S_ANIM_CLIPS,2,'<instance_animation url="#'+z+'">') + self.writel(S_ANIM_CLIPS,2,'<instance_animation url="#'+z+'"/>') self.writel(S_ANIM_CLIPS,1,'</animation_clip>') self.writel(S_ANIM_CLIPS,0,'</library_animation_clips>') for s in self.skeletons: + if (s.animation_data==None): + continue if s in cached_actions: s.animation_data.action = bpy.data.actions[cached_actions[s]] else: @@ -1230,6 +1495,19 @@ class DaeExporter: self.export_scene() self.writel(S_GEOM,0,'</library_geometries>') + + #morphs always go before skin controllers + if S_MORPH in self.sections: + for l in self.sections[S_MORPH]: + self.writel(S_CONT,0,l) + del self.sections[S_MORPH] + + #morphs always go before skin controllers + if S_SKIN in self.sections: + for l in self.sections[S_SKIN]: + self.writel(S_CONT,0,l) + del self.sections[S_SKIN] + self.writel(S_CONT,0,'</library_controllers>') self.writel(S_CAMS,0,'</library_cameras>') self.writel(S_LAMPS,0,'</library_lights>') @@ -1276,6 +1554,7 @@ class DaeExporter: self.skeleton_info={} self.config=kwargs self.valid_nodes=[] + self.armature_for_morph={} |