summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--SConstruct1
-rw-r--r--core/globals.cpp6
-rw-r--r--core/io/config_file.cpp7
-rw-r--r--core/math/math_funcs.cpp2
-rw-r--r--core/math/quick_hull.cpp3
-rw-r--r--core/object.cpp2
-rw-r--r--core/ustring.cpp36
-rw-r--r--core/ustring.h1
-rw-r--r--demos/2d/kinematic_char/player.gd3
-rw-r--r--demos/3d/platformer/tiles.resbin81338 -> 81631 bytes
-rw-r--r--drivers/gles1/rasterizer_gles1.cpp19
-rw-r--r--drivers/gles1/rasterizer_gles1.h11
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp500
-rw-r--r--drivers/gles2/rasterizer_gles2.h22
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp10
-rw-r--r--drivers/gles2/shader_compiler_gles2.h3
-rw-r--r--drivers/gles2/shaders/material.glsl68
-rw-r--r--drivers/ogg/SCsub3
-rw-r--r--drivers/theora/SCsub3
-rw-r--r--drivers/theoraplayer/SCsub14
-rw-r--r--drivers/vorbis/SCsub6
-rw-r--r--drivers/vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--drivers/windows/dir_access_windows.cpp12
-rw-r--r--modules/gdscript/gd_compiler.cpp10
-rw-r--r--modules/gdscript/gd_editor.cpp9
-rw-r--r--modules/gdscript/gd_parser.cpp155
-rw-r--r--modules/gdscript/gd_parser.h2
-rw-r--r--modules/gdscript/gd_script.cpp60
-rw-r--r--modules/gdscript/gd_script.h14
-rw-r--r--modules/gdscript/gd_tokenizer.cpp18
-rw-r--r--modules/gdscript/gd_tokenizer.h1
-rw-r--r--modules/gdscript/register_types.cpp4
-rw-r--r--modules/gridmap/grid_map.cpp2
-rw-r--r--platform/android/export/export.cpp44
-rw-r--r--platform/iphone/detect.py6
-rw-r--r--platform/isim/SCsub9
-rw-r--r--platform/isim/detect.py14
-rw-r--r--platform/windows/detect.py3
-rw-r--r--platform/windows/os_windows.cpp7
-rw-r--r--platform/x11/detect.py5
-rw-r--r--scene/2d/particles_2d.cpp8
-rw-r--r--scene/2d/physics_body_2d.cpp20
-rw-r--r--scene/2d/physics_body_2d.h5
-rw-r--r--scene/2d/sprite.cpp14
-rw-r--r--scene/2d/tile_map.cpp3
-rw-r--r--scene/3d/baked_light_instance.cpp78
-rw-r--r--scene/3d/baked_light_instance.h42
-rw-r--r--scene/3d/camera.cpp48
-rw-r--r--scene/3d/camera.h3
-rw-r--r--scene/3d/follow_camera.cpp778
-rw-r--r--scene/3d/follow_camera.h180
-rw-r--r--scene/3d/immediate_geometry.cpp50
-rw-r--r--scene/3d/immediate_geometry.h5
-rw-r--r--scene/3d/light.cpp49
-rw-r--r--scene/3d/light.h8
-rw-r--r--scene/3d/mesh_instance.cpp17
-rw-r--r--scene/3d/physics_body.cpp8
-rw-r--r--scene/3d/physics_body.h3
-rw-r--r--scene/3d/skeleton.cpp16
-rw-r--r--scene/3d/skeleton.h2
-rw-r--r--scene/3d/visual_instance.cpp12
-rw-r--r--scene/3d/visual_instance.h1
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/gui/base_button.cpp12
-rw-r--r--scene/gui/dialogs.cpp2
-rw-r--r--scene/gui/popup_menu.cpp2
-rw-r--r--scene/gui/tree.cpp3
-rw-r--r--scene/main/scene_main_loop.cpp20
-rw-r--r--scene/main/scene_main_loop.h10
-rw-r--r--scene/main/timer.cpp8
-rw-r--r--scene/main/viewport.cpp33
-rw-r--r--scene/main/viewport.h5
-rw-r--r--scene/register_scene_types.cpp3
-rw-r--r--scene/resources/baked_light.cpp94
-rw-r--r--scene/resources/baked_light.h25
-rw-r--r--scene/resources/material.cpp20
-rw-r--r--scene/resources/material.h1
-rw-r--r--scene/resources/mesh.cpp27
-rw-r--r--scene/resources/mesh.h1
-rw-r--r--scene/resources/shader_graph.cpp4
-rw-r--r--scene/resources/shape_2d.cpp2
-rw-r--r--scene/resources/surface_tool.cpp206
-rw-r--r--scene/resources/surface_tool.h10
-rw-r--r--servers/physics/body_sw.cpp11
-rw-r--r--servers/physics/body_sw.h1
-rw-r--r--servers/physics_2d/body_2d_sw.cpp13
-rw-r--r--servers/physics_2d/body_2d_sw.h3
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp8
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h5
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp16
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h4
-rw-r--r--servers/physics_2d/space_2d_sw.cpp4
-rw-r--r--servers/physics_2d_server.cpp10
-rw-r--r--servers/physics_2d_server.h7
-rw-r--r--servers/physics_server.cpp10
-rw-r--r--servers/visual/rasterizer.cpp10
-rw-r--r--servers/visual/rasterizer.h7
-rw-r--r--servers/visual/rasterizer_dummy.cpp20
-rw-r--r--servers/visual/rasterizer_dummy.h11
-rw-r--r--servers/visual/shader_language.cpp2
-rw-r--r--servers/visual/visual_server_raster.cpp655
-rw-r--r--servers/visual/visual_server_raster.h69
-rw-r--r--servers/visual/visual_server_wrap_mt.h19
-rw-r--r--servers/visual_server.cpp2
-rw-r--r--servers/visual_server.h33
-rw-r--r--tools/collada/collada.cpp9
-rw-r--r--tools/collada/collada.h24
-rw-r--r--tools/doc/doc_data.cpp5
-rw-r--r--tools/docdump/makemd.py2
-rw-r--r--tools/editor/editor_file_system.cpp2
-rw-r--r--tools/editor/editor_help.cpp2
-rw-r--r--tools/editor/editor_node.cpp4
-rw-r--r--tools/editor/editor_settings.cpp2
-rw-r--r--tools/editor/icons/icon_baked_light.pngbin0 -> 419 bytes
-rw-r--r--tools/editor/icons/icon_baked_light_instance.pngbin0 -> 380 bytes
-rw-r--r--tools/editor/icons/icon_panels_2_alt.pngbin0 -> 156 bytes
-rw-r--r--tools/editor/icons/icon_panels_3_alt.pngbin0 -> 167 bytes
-rw-r--r--tools/editor/icons/icon_particle_attractor_2d.pngbin0 -> 574 bytes
-rw-r--r--tools/editor/icons/icon_polygon_2d.pngbin0 -> 405 bytes
-rw-r--r--tools/editor/icons/icon_touch_screen_button.pngbin0 -> 434 bytes
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp26
-rw-r--r--tools/editor/plugins/baked_light_baker.cpp606
-rw-r--r--tools/editor/plugins/baked_light_baker.h48
-rw-r--r--tools/editor/plugins/baked_light_baker_cmpxchg.cpp84
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.cpp18
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.h5
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.cpp227
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.h68
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp4
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp317
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.h42
-rw-r--r--tools/editor/project_export.cpp4
-rw-r--r--tools/editor/project_manager.cpp6
-rw-r--r--tools/editor/scenes_dock.cpp5
-rw-r--r--tools/editor/spatial_editor_gizmos.cpp131
-rw-r--r--tools/export/blender25/install.txt16
-rw-r--r--tools/export/blender25/io_scene_dae/__init__.py27
-rw-r--r--tools/export/blender25/io_scene_dae/export_dae.py575
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
index 53534788a1..d4fb779ff1 100644
--- a/demos/3d/platformer/tiles.res
+++ b/demos/3d/platformer/tiles.res
Binary files differ
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(&current,0,sizeof(current));
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &current);
+
+ 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
new file mode 100644
index 0000000000..48039e264c
--- /dev/null
+++ b/tools/editor/icons/icon_baked_light.png
Binary files differ
diff --git a/tools/editor/icons/icon_baked_light_instance.png b/tools/editor/icons/icon_baked_light_instance.png
new file mode 100644
index 0000000000..77e53aa8f6
--- /dev/null
+++ b/tools/editor/icons/icon_baked_light_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_2_alt.png b/tools/editor/icons/icon_panels_2_alt.png
new file mode 100644
index 0000000000..2006f212ce
--- /dev/null
+++ b/tools/editor/icons/icon_panels_2_alt.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_3_alt.png b/tools/editor/icons/icon_panels_3_alt.png
new file mode 100644
index 0000000000..5195b799a5
--- /dev/null
+++ b/tools/editor/icons/icon_panels_3_alt.png
Binary files differ
diff --git a/tools/editor/icons/icon_particle_attractor_2d.png b/tools/editor/icons/icon_particle_attractor_2d.png
new file mode 100644
index 0000000000..bb66611e45
--- /dev/null
+++ b/tools/editor/icons/icon_particle_attractor_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_polygon_2d.png b/tools/editor/icons/icon_polygon_2d.png
new file mode 100644
index 0000000000..9deb63a248
--- /dev/null
+++ b/tools/editor/icons/icon_polygon_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_touch_screen_button.png b/tools/editor/icons/icon_touch_screen_button.png
new file mode 100644
index 0000000000..16e84927f1
--- /dev/null
+++ b/tools/editor/icons/icon_touch_screen_button.png
Binary files differ
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={}