From db2381de7afffc932d051ec9fc853bfe06645060 Mon Sep 17 00:00:00 2001
From: Bil Bas (Spooner)
Date: Thu, 19 Feb 2015 15:45:49 +0000
Subject: Correctly halt on error in sprintf parsing (fixes #1393)
---
modules/gdscript/gd_script.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'modules')
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 0aa115ffb..2a1e7a18d 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -337,7 +337,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
Variant::evaluate(op,*a,*b,*dst,valid);
if (!valid) {
- if (false && dst->get_type()==Variant::STRING) {
+ if (dst->get_type()==Variant::STRING) {
//return a string when invalid with the error
err_text=*dst;
} else {
--
cgit v1.2.3-70-g09d2
From 748311ec42b6818f5481ad4ac4152f40ff1a8a6f Mon Sep 17 00:00:00 2001
From: Bil Bas (Spooner)
Date: Thu, 19 Feb 2015 16:59:37 +0000
Subject: Added info about operator after bespoke error message.
---
modules/gdscript/gd_script.cpp | 1 +
1 file changed, 1 insertion(+)
(limited to 'modules')
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 2a1e7a18d..bf4e9b8d8 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -340,6 +340,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (dst->get_type()==Variant::STRING) {
//return a string when invalid with the error
err_text=*dst;
+ err_text += " in operator '"+Variant::get_operator_name(op)+"'.";
} else {
err_text="Invalid operands '"+Variant::get_type_name(a->get_type())+"' and '"+Variant::get_type_name(b->get_type())+"' in operator '"+Variant::get_operator_name(op)+"'.";
}
--
cgit v1.2.3-70-g09d2
From bfad3923878aa9b485f90a37bc04944828e35f27 Mon Sep 17 00:00:00 2001
From: Nathan Warden
Date: Fri, 20 Feb 2015 16:28:48 -0500
Subject: Updated the variable in the lerp function to be weight instead of
percent.
---
doc/base/classes.xml | 2 +-
modules/gdscript/gd_functions.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
(limited to 'modules')
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 7c5530682..8271c5f7b 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -261,7 +261,7 @@
-
+
Linear interpolates between two values by a normalized value.
diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp
index b616d8f22..f37b2f645 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -1101,7 +1101,7 @@ MethodInfo GDFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_LERP: {
- MethodInfo mi("lerp",PropertyInfo(Variant::REAL,"a"),PropertyInfo(Variant::REAL,"b"), PropertyInfo(Variant::REAL,"c"));
+ MethodInfo mi("lerp",PropertyInfo(Variant::REAL,"from"),PropertyInfo(Variant::REAL,"to"), PropertyInfo(Variant::REAL,"weight"));
mi.return_val.type=Variant::REAL;
return mi;
} break;
--
cgit v1.2.3-70-g09d2
From a1f715a4da71fbc2b7d6fad68624bf8b22c6da17 Mon Sep 17 00:00:00 2001
From: Juan Linietsky
Date: Mon, 2 Mar 2015 00:54:10 -0300
Subject: support for 2D shadow casters
Added support for 2D shadow casters.
*DANGER* Shaders in CanvasItem CHANGED, if you are using shader in a
CanvasItem and pull this, you will lose them. Shaders now work through a
2D material system similar to 3D. If you don't want to lose the 2D
shader code, save the shader as a .shd, then create a material in
CanvasItem and re-assign the shader.
---
core/io/resource_format_binary.cpp | 10 +
core/io/resource_format_xml.cpp | 5 +
core/math/camera_matrix.cpp | 19 +-
core/variant_op.cpp | 3 +
demos/3d/kinematic_char/cubelib.res | Bin 11431 -> 11530 bytes
demos/3d/kinematic_char/level.scn | Bin 15323 -> 15556 bytes
drivers/SCsub | 1 -
drivers/gles2/rasterizer_gles2.cpp | 598 ++++++++++++++++++++-
drivers/gles2/rasterizer_gles2.h | 62 ++-
drivers/gles2/shaders/SCsub | 1 +
drivers/gles2/shaders/canvas.glsl | 123 ++++-
drivers/gles2/shaders/canvas_shadow.glsl | 62 +++
drivers/windows/file_access_windows.cpp | 20 +-
modules/gdscript/gd_script.cpp | 5 +-
platform/android/audio_driver_opensl.cpp | 8 +
platform/android/os_android.cpp | 2 +-
platform/windows/detect.py | 4 +-
scene/2d/canvas_item.cpp | 309 +++++++----
scene/2d/canvas_item.h | 59 +-
scene/2d/light_2d.cpp | 49 +-
scene/2d/light_2d.h | 8 +
scene/2d/light_occluder_2d.cpp | 201 +++++++
scene/2d/light_occluder_2d.h | 73 +++
scene/3d/camera.cpp | 6 +-
scene/3d/visual_instance.cpp | 15 +
scene/3d/visual_instance.h | 4 +
scene/register_scene_types.cpp | 4 +
scene/scene_string_names.cpp | 1 +
scene/scene_string_names.h | 1 +
servers/visual/rasterizer.h | 67 ++-
servers/visual/visual_server_raster.cpp | 377 +++++++++++--
servers/visual/visual_server_raster.h | 61 ++-
servers/visual/visual_server_wrap_mt.h | 30 +-
servers/visual_server.h | 33 +-
tools/editor/editor_node.cpp | 2 +
tools/editor/icons/icon_canvas_item_material.png | Bin 0 -> 835 bytes
tools/editor/icons/icon_canvas_modulate.png | Bin 0 -> 441 bytes
tools/editor/icons/icon_light_occluder_2d.png | Bin 0 -> 516 bytes
tools/editor/icons/icon_occluder_polygon_2d.png | Bin 0 -> 581 bytes
.../plugins/collision_polygon_2d_editor_plugin.cpp | 1 +
.../plugins/light_occluder_2d_editor_plugin.cpp | 500 +++++++++++++++++
.../plugins/light_occluder_2d_editor_plugin.h | 87 +++
tools/editor/property_editor.cpp | 40 +-
43 files changed, 2583 insertions(+), 268 deletions(-)
create mode 100644 drivers/gles2/shaders/canvas_shadow.glsl
create mode 100644 scene/2d/light_occluder_2d.cpp
create mode 100644 scene/2d/light_occluder_2d.h
create mode 100644 tools/editor/icons/icon_canvas_item_material.png
create mode 100644 tools/editor/icons/icon_canvas_modulate.png
create mode 100644 tools/editor/icons/icon_light_occluder_2d.png
create mode 100644 tools/editor/icons/icon_occluder_polygon_2d.png
create mode 100644 tools/editor/plugins/light_occluder_2d_editor_plugin.cpp
create mode 100644 tools/editor/plugins/light_occluder_2d_editor_plugin.h
(limited to 'modules')
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index e2371fe24..ead698465 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1778,6 +1778,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
f->store_32(VERSION_MINOR);
f->store_32(FORMAT_VERSION);
+ if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
+ f->close();
+ return ERR_CANT_CREATE;
+ }
+
//f->store_32(saved_resources.size()+external_resources.size()); // load steps -not needed
save_unicode_string(p_resource->get_type());
uint64_t md_at = f->get_pos();
@@ -1910,6 +1915,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
f->store_buffer((const uint8_t*)"RSRC",4); //magic at end
+ if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
+ f->close();
+ return ERR_CANT_CREATE;
+ }
+
f->close();
diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp
index 75384d4ab..033b4d5e5 100644
--- a/core/io/resource_format_xml.cpp
+++ b/core/io/resource_format_xml.cpp
@@ -2592,6 +2592,11 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
}
exit_tag("resource_file");
+ if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
+ f->close();
+ return ERR_CANT_CREATE;
+ }
+
f->close();
//memdelete(f);
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index a60dea737..fbe5f8c74 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -121,7 +121,7 @@ void CameraMatrix::set_orthogonal(float p_size, float p_aspect, float p_znear, f
void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, float p_top, float p_near, float p_far) {
-
+#if 0
///@TODO, give a check to this. I'm not sure if it's working.
set_identity();
@@ -133,10 +133,27 @@ void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, floa
matrix[2][3]=-(2*p_far*p_near) / (p_far-p_near);
matrix[3][2]=-1;
matrix[3][3]=0;
+#else
+ float *te = &matrix[0][0];
+ float x = 2 * p_near / ( p_right - p_left );
+ float y = 2 * p_near / ( p_top - p_bottom );
+
+ float a = ( p_right + p_left ) / ( p_right - p_left );
+ float b = ( p_top + p_bottom ) / ( p_top - p_bottom );
+ float c = - ( p_far + p_near ) / ( p_far - p_near );
+ float d = - 2 * p_far * p_near / ( p_far - p_near );
+
+ te[0] = x; te[4] = 0; te[8] = a; te[12] = 0;
+ te[1] = 0; te[5] = y; te[9] = b; te[13] = 0;
+ te[2] = 0; te[6] = 0; te[10] = c; te[14] = d;
+ te[3] = 0; te[7] = 0; te[11] = - 1; te[15] = 0;
+
+#endif
}
+
float CameraMatrix::get_z_far() const {
const float * matrix = (const float*)this->matrix;
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 21bbc8c7e..d6129e150 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -552,6 +552,9 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
if (p_b.type==MATRIX32) {
_RETURN( *p_a._data._matrix32 * *p_b._data._matrix32 );
};
+ if (p_b.type==VECTOR2) {
+ _RETURN( p_a._data._matrix32->xform( *(const Vector2*)p_b._data._mem) );
+ };
r_valid=false;
return;
} break;
diff --git a/demos/3d/kinematic_char/cubelib.res b/demos/3d/kinematic_char/cubelib.res
index 66b999d78..27f2b9b3b 100644
Binary files a/demos/3d/kinematic_char/cubelib.res and b/demos/3d/kinematic_char/cubelib.res differ
diff --git a/demos/3d/kinematic_char/level.scn b/demos/3d/kinematic_char/level.scn
index a276fe22e..7ccb2430c 100644
Binary files a/demos/3d/kinematic_char/level.scn and b/demos/3d/kinematic_char/level.scn differ
diff --git a/drivers/SCsub b/drivers/SCsub
index 46334468b..a1a2191cb 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -10,7 +10,6 @@ SConscript('alsa/SCsub');
SConscript('pulseaudio/SCsub');
SConscript('windows/SCsub');
SConscript('gles2/SCsub');
-SConscript('gles1/SCsub');
SConscript('gl_context/SCsub');
SConscript('openssl/SCsub');
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index aba0b5ca9..aa7bad0b8 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -971,7 +971,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
- if ((!texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha()==Image::ALPHA_BLEND) {
+ if (!(texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha()==Image::ALPHA_BLEND) {
texture->has_alpha=true;
}
@@ -2525,7 +2525,7 @@ Error RasterizerGLES2::_surface_set_arrays(Surface *p_surface, uint8_t *p_mem,ui
void RasterizerGLES2::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) {
ERR_EXPLAIN("OpenGL Rasterizer does not support custom surfaces. Running on wrong platform?");
- ERR_FAIL_V();
+ ERR_FAIL();
}
Array RasterizerGLES2::mesh_get_surface_arrays(RID p_mesh,int p_surface) const {
@@ -4116,6 +4116,10 @@ void RasterizerGLES2::begin_frame() {
shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter")));
#endif
+ canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF5,shadow_filter==SHADOW_FILTER_PCF5);
+ canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF13,shadow_filter==SHADOW_FILTER_PCF13);
+ canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM);
+
window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height );
double time = (OS::get_singleton()->get_ticks_usec()/1000); // get msec
@@ -7874,7 +7878,8 @@ void RasterizerGLES2::canvas_begin() {
canvas_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
canvas_texscreen_used=false;
uses_texpixel_size=false;
- canvas_last_shader=RID();
+
+ canvas_last_material=NULL;
}
@@ -8364,6 +8369,476 @@ void RasterizerGLES2::canvas_set_transform(const Matrix32& p_transform) {
//canvas_transform = Variant(p_transform);
}
+RID RasterizerGLES2::canvas_light_occluder_create() {
+
+ CanvasOccluder *co = memnew( CanvasOccluder );
+ co->index_id=0;
+ co->vertex_id=0;
+ co->len=0;
+
+ return canvas_occluder_owner.make_rid(co);
+}
+
+void RasterizerGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const DVector& p_lines) {
+
+ CanvasOccluder *co = canvas_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!co);
+
+ co->lines=p_lines;
+
+ if (p_lines.size()!=co->len) {
+
+ if (co->index_id)
+ glDeleteBuffers(1,&co->index_id);
+ if (co->vertex_id)
+ glDeleteBuffers(1,&co->vertex_id);
+
+ co->index_id=0;
+ co->vertex_id=0;
+ co->len=0;
+
+ }
+
+ if (p_lines.size()) {
+
+
+
+ DVector geometry;
+ DVector indices;
+ int lc = p_lines.size();
+
+ geometry.resize(lc*6);
+ indices.resize(lc*3);
+
+ DVector::Write vw=geometry.write();
+ DVector::Write iw=indices.write();
+
+
+ DVector::Read lr=p_lines.read();
+
+ const int POLY_HEIGHT = 16384;
+
+ for(int i=0;ivertex_id) {
+ glGenBuffers(1,&co->vertex_id);
+ glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id);
+ glBufferData(GL_ARRAY_BUFFER,lc*6*sizeof(real_t),vw.ptr(),GL_STATIC_DRAW);
+ } else {
+
+ glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id);
+ glBufferSubData(GL_ARRAY_BUFFER,0,lc*6*sizeof(real_t),vw.ptr());
+
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+
+ if (!co->index_id) {
+
+ glGenBuffers(1,&co->index_id);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,lc*3*sizeof(uint16_t),iw.ptr(),GL_STATIC_DRAW);
+ } else {
+
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id);
+ glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,lc*3*sizeof(uint16_t),iw.ptr());
+ }
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind
+
+ co->len=lc;
+
+ }
+
+
+
+}
+
+RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
+
+ CanvasLightShadow *cls = memnew( CanvasLightShadow );
+ if (p_width>max_texture_size)
+ p_width=max_texture_size;
+
+ cls->size=p_width;
+ glActiveTexture(GL_TEXTURE0);
+
+ glGenFramebuffers(1, &cls->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
+
+ // Create a render buffer
+ glGenRenderbuffers(1, &cls->rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, cls->rbo);
+
+ // Create a texture for storing the depth
+ glGenTextures(1, &cls->depth);
+ glBindTexture(GL_TEXTURE_2D, cls->depth);
+ 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);
+
+ cls->height=16;
+
+ //print_line("ERROR? "+itos(glGetError()));
+ if ( read_depth_supported ) {
+
+ // We'll use a depth texture to store the depths in the shadow map
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, cls->size, cls->height, 0,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
+#ifdef GLEW_ENABLED
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
+ // Attach the depth texture to FBO depth attachment point
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D, cls->depth, 0);
+
+#ifdef GLEW_ENABLED
+ glDrawBuffer(GL_NONE);
+#endif
+ } else {
+ // We'll use a RGBA texture into which we pack the depth info
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ // Attach the RGBA texture to FBO color attachment point
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, cls->depth, 0);
+
+ // Allocate 16-bit depth buffer
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height);
+
+ // Attach the render buffer as depth buffer - will be ignored
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, cls->rbo);
+
+
+ }
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ //printf("errnum: %x\n",status);
+#ifdef GLEW_ENABLED
+ if (read_depth_supported) {
+ glDrawBuffer(GL_BACK);
+ }
+#endif
+ glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer);
+ DEBUG_TEST_ERROR("2D Shadow Buffer Init");
+ ERR_FAIL_COND_V( status != GL_FRAMEBUFFER_COMPLETE, RID() );
+
+#ifdef GLEW_ENABLED
+ if (read_depth_supported) {
+ glDrawBuffer(GL_BACK);
+ }
+#endif
+
+ return canvas_light_shadow_owner.make_rid(cls);
+}
+
+void RasterizerGLES2::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) {
+
+ CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_buffer);
+ ERR_FAIL_COND(!cls);
+
+
+ glDisable(GL_BLEND);
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_DITHER);
+ glDisable(GL_CULL_FACE);
+ glDepthFunc(GL_LEQUAL);
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(true);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
+
+ if (!use_rgba_shadowmaps)
+ glColorMask(0, 0, 0, 0);
+
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ canvas_shadow_shader.bind();
+
+ const int vp_height = 10;
+
+ glViewport(0, 0, cls->size,cls->height);
+ _glClearDepth(1.0f);
+ glClearColor(1,1,1,1);
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ VS::CanvasOccluderPolygonCullMode cull=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
+
+
+ for(int i=0;i<4;i++) {
+
+ //make sure it remains orthogonal, makes easy to read angle later
+
+ Transform light;
+ light.origin[0]=p_light_xform[2][0];
+ light.origin[1]=p_light_xform[2][1];
+ light.basis[0][0]=p_light_xform[0][0];
+ light.basis[0][1]=p_light_xform[1][0];
+ light.basis[1][0]=p_light_xform[0][1];
+ light.basis[1][1]=p_light_xform[1][1];
+
+ //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
+
+ /// p_near=1;
+ CameraMatrix projection;
+ {
+ real_t fov = 90;
+ real_t near = p_near;
+ real_t far = p_far;
+ real_t aspect = 1.0;
+
+ real_t ymax = near * Math::tan( Math::deg2rad( fov * 0.5 ) );
+ real_t ymin = - ymax;
+ real_t xmin = ymin * aspect;
+ real_t xmax = ymax * aspect;
+
+ projection.set_frustum( xmin, xmax, ymin, ymax, near, far );
+ }
+
+ Vector3 cam_target=Matrix3(Vector3(0,0,Math_PI*2*(i/4.0))).xform(Vector3(0,1,0));
+ projection = projection * CameraMatrix(Transform().looking_at(cam_target,Vector3(0,0,-1)).affine_inverse());
+
+ //print_line("near: "+rtos(p_near));
+ //print_line("far: "+rtos(p_far));
+ //projection.set_perspective(60,size/float(vp_height),p_near,p_far);
+
+ // CameraMatrix light_mat = projection * CameraMatrix(camera);
+
+ canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::PROJECTION_MATRIX,projection);
+ canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::LIGHT_MATRIX,light);
+
+ if (i==0)
+ *p_xform_cache=projection;
+
+ glViewport(0, (cls->height/4)*i, cls->size,cls->height/4);
+
+ CanvasLightOccluderInstance *instance=p_occluders;
+
+ while(instance) {
+
+ CanvasOccluder *cc = canvas_occluder_owner.get(instance->polygon_buffer);
+ if (!cc || cc->len==0 || !(p_light_mask&instance->light_mask)) {
+
+ instance=instance->next;
+ continue;
+ }
+
+ canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::WORLD_MATRIX,instance->xform_cache);
+ if (cull!=instance->cull_cache) {
+
+ cull=instance->cull_cache;
+ switch(cull) {
+ case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: {
+
+ glDisable(GL_CULL_FACE);
+
+ } break;
+ case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: {
+
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ } break;
+ case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: {
+
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+
+ } break;
+ }
+ }
+/*
+ if (i==0) {
+ for(int i=0;ilines.size();i++) {
+ Vector2 p = instance->xform_cache.xform(cc->lines.get(i));
+ Plane pp(Vector3(p.x,p.y,0),1);
+ pp.normal = light.xform(pp.normal);
+ pp = projection.xform4(pp);
+ print_line(itos(i)+": "+pp.normal/pp.d);
+ //pp=light_mat.xform4(pp);
+ //print_line(itos(i)+": "+pp.normal/pp.d);
+ }
+ }
+*/
+ glBindBuffer(GL_ARRAY_BUFFER,cc->vertex_id);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,cc->index_id);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0);
+ glDrawElements(GL_TRIANGLES,cc->len*3,GL_UNSIGNED_SHORT,0);
+
+
+ instance=instance->next;
+ }
+
+
+ }
+
+ glDisableVertexAttribArray(VS::ARRAY_VERTEX);
+ glBindBuffer(GL_ARRAY_BUFFER,0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+
+ if (shadow_filter==SHADOW_FILTER_ESM) {
+ //blur the buffer
+#if 0
+ //this is ignord, it did not make any difference..
+ if (read_depth_supported) {
+ glDepthFunc(GL_ALWAYS);
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(false);
+ }
+ glDisable(GL_CULL_FACE);
+ glViewport(0, 0, cls->size,cls->height);
+
+ int passes=1;
+ CanvasLightShadow *blur = canvas_light_shadow_owner.get(canvas_shadow_blur);
+
+ copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,true);
+ copy_shader.bind();
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,1);
+ copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,1);
+ glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
+
+ for(int i=0;ifbo);
+ glActiveTexture(GL_TEXTURE0);
+
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,cls->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,cls->rgba);
+
+
+ {
+ Vector2 src_sb_uv[4]={
+ Vector2( 0, 1),
+ Vector2( 1, 1),
+ Vector2( 1, 0),
+ Vector2( 0, 0)
+ };
+ static const Vector2 dst_pos[4]={
+ Vector2(-1, 1),
+ Vector2( 1, 1),
+ Vector2( 1,-1),
+ Vector2(-1,-1)
+ };
+
+
+
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/cls->size);
+ _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv);
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,blur->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,blur->rgba);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
+
+ {
+ float hlimit = float(cls->size) / blur->size;
+ //hlimit*=2.0;
+ Vector2 src_sb_uv[4]={
+ Vector2( 0, 1),
+ Vector2( hlimit, 1),
+ Vector2( hlimit, 0),
+ Vector2( 0, 0)
+ };
+ static const Vector2 dst_pos[4]={
+ Vector2(-1, 1),
+ Vector2( 1, 1),
+ Vector2( 1,-1),
+ Vector2(-1,-1)
+ };
+
+
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/blur->size);
+ _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv);
+ }
+
+ }
+ copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,false);
+ glDepthFunc(GL_LEQUAL);
+#endif
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer);
+ glColorMask(1, 1, 1, 1);
+
+
+
+}
+
+
+void RasterizerGLES2::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) {
+
+ CanvasLight* light=p_lights_with_shadow;
+
+ canvas_begin(); //reset
+
+ int h = 10;
+ int w = viewport.width;
+ int ofs = h;
+ while(light) {
+
+ if (light->shadow_buffer.is_valid()) {
+
+ CanvasLightShadow * sb = canvas_light_shadow_owner.get(light->shadow_buffer);
+ if (sb) {
+ glActiveTexture(GL_TEXTURE0);
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,sb->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,sb->rgba);
+ _draw_textured_quad(Rect2(h,ofs,w-h*2,h),Rect2(0,0,sb->size,10),Size2(sb->size,10),false,false);
+ ofs+=h*2;
+
+ }
+ }
+
+ light=light->shadows_next_ptr;
+ }
+
+}
+
void RasterizerGLES2::_canvas_normal_set_flip(const Vector2& p_flip) {
if (p_flip==normal_flip)
@@ -8508,14 +8983,14 @@ void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem
}
-void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItem *shader_owner,Shader* shader) {
+void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* shader) {
if (canvas_shader.bind())
rebind_texpixel_size=true;
- if (shader_owner->shader_version!=shader->version) {
+ if (material->shader_version!=shader->version) {
//todo optimize uniforms
- shader_owner->shader_version=shader->version;
+ material->shader_version=shader->version;
}
if (shader->has_texscreen && framebuffer.active) {
@@ -8558,14 +9033,14 @@ void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItem *shader_owner,
}
-void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItem *shader_owner,Shader* shader) {
+void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* shader) {
//this can be optimized..
int tex_id=1;
int idx=0;
for(Map::Element *E=shader->uniforms.front();E;E=E->next()) {
- Map::Element *F=shader_owner->shader_param.find(E->key());
+ Map::Element *F=material->shader_param.find(E->key());
if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) {
@@ -8623,6 +9098,8 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_modulate=p_modulate;
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+ bool reset_modulate=false;
+
while(p_item_list) {
CanvasItem *ci=p_item_list;
@@ -8632,12 +9109,13 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect);
}
memdelete(ci->vp_render);
- ci->vp_render=NULL;
- canvas_last_shader=RID();
+ ci->vp_render=NULL;
+ canvas_last_material=NULL;
canvas_use_modulate=p_modulate!=Color(1,1,1,1);
canvas_modulate=p_modulate;
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
rebind_shader=true;
+ reset_modulate=true;
}
@@ -8660,13 +9138,14 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
//begin rect
- CanvasItem *shader_owner = ci->shader_owner?ci->shader_owner:ci;
+ CanvasItem *material_owner = ci->material_owner?ci->material_owner:ci;
+ CanvasItemMaterial *material = material_owner->material;
- if (shader_owner->shader!=canvas_last_shader || rebind_shader) {
+ if (material!=canvas_last_material || rebind_shader) {
Shader *shader = NULL;
- if (shader_owner->shader.is_valid()) {
- shader = this->shader_owner.get(shader_owner->shader);
+ if (material && material->shader.is_valid()) {
+ shader = shader_owner.get(material->shader);
if (shader && !shader->valid) {
shader=NULL;
}
@@ -8676,7 +9155,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
if (shader) {
canvas_shader.set_custom_shader(shader->custom_code_id);
- _canvas_item_setup_shader_params(shader_owner,shader);
+ _canvas_item_setup_shader_params(material,shader);
} else {
shader_cache=NULL;
canvas_shader.set_custom_shader(0);
@@ -8688,16 +9167,26 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
if (canvas_use_modulate)
- canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
- canvas_last_shader=shader_owner->shader;
+ reset_modulate=true;
+ canvas_last_material=material;
rebind_shader=false;
}
- if (shader_cache) {
+ if (material && shader_cache) {
+
+ _canvas_item_setup_shader_uniforms(material,shader_cache);
+ }
- _canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
+ if (material && material->unshaded) {
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,Color(1,1,1,1));
+ reset_modulate=true;
+ } else if (reset_modulate) {
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
+ reset_modulate=false;
}
+
+
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
@@ -8747,7 +9236,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
_canvas_item_render_commands(ci,current_clip,reclip);
- if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light) {
+ if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && (!material || !material->unshaded)) {
CanvasLight *light = p_light;
bool light_used=false;
@@ -8785,13 +9274,15 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
normal_flip=Vector2(1,1);
}
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,light->shadow_buffer.is_valid());
+
bool light_rebind = canvas_shader.bind();
if (light_rebind) {
- if (shader_owner && shader_cache) {
- _canvas_item_setup_shader_params(shader_owner,shader_cache);
- _canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
+ if (material && shader_cache) {
+ _canvas_item_setup_shader_params(material,shader_cache);
+ _canvas_item_setup_shader_uniforms(material,shader_cache);
}
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
@@ -8800,6 +9291,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
if (canvas_use_modulate)
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,Vector2(1,1));
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE,1.0/light->shadow_buffer_size);
}
@@ -8808,6 +9300,23 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
+ if (light->shadow_buffer.is_valid()) {
+
+ CanvasLightShadow *cls = canvas_light_shadow_owner.get(light->shadow_buffer);
+ glActiveTexture(GL_TEXTURE0+max_texture_units-3);
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,cls->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,cls->rgba);
+
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_TEXTURE,max_texture_units-3);
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache);
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse());
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult);
+
+ }
+
+
glActiveTexture(GL_TEXTURE0+max_texture_units-2);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_TEXTURE,max_texture_units-2);
Texture *t = texture_owner.get(light->texture);
@@ -8831,12 +9340,13 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,false);
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,false);
canvas_shader.bind();
- if (shader_owner && shader_cache) {
- _canvas_item_setup_shader_params(shader_owner,shader_cache);
- _canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
+ if (material && shader_cache) {
+ _canvas_item_setup_shader_params(material,shader_cache);
+ _canvas_item_setup_shader_uniforms(material,shader_cache);
}
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
@@ -9067,6 +9577,11 @@ bool RasterizerGLES2::is_environment(const RID& p_rid) const {
}
bool RasterizerGLES2::is_shader(const RID& p_rid) const {
+ return shader_owner.owns(p_rid);
+}
+
+bool RasterizerGLES2::is_canvas_light_occluder(const RID& p_rid) const {
+
return false;
}
@@ -9244,7 +9759,30 @@ void RasterizerGLES2::free(const RID& p_rid) {
glDeleteTextures(1,&sampled_light->texture);
sampled_light_owner.free(p_rid);
memdelete( sampled_light );
+ } else if (canvas_occluder_owner.owns(p_rid)) {
+
+ CanvasOccluder *co = canvas_occluder_owner.get(p_rid);
+ if (co->index_id)
+ glDeleteBuffers(1,&co->index_id);
+ if (co->vertex_id)
+ glDeleteBuffers(1,&co->vertex_id);
+
+ canvas_occluder_owner.free(p_rid);
+ memdelete(co);
+
+ } else if (canvas_light_shadow_owner.owns(p_rid)) {
+
+ CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid);
+ glDeleteFramebuffers(1,&cls->fbo);
+ glDeleteRenderbuffers(1,&cls->rbo);
+ glDeleteTextures(1,&cls->depth);
+ if (!read_depth_supported) {
+ glDeleteTextures(1,&cls->rgba);
+ }
+
+ canvas_light_shadow_owner.free(p_rid);
+ memdelete(cls);
};
}
@@ -9779,10 +10317,12 @@ void RasterizerGLES2::init() {
material_shader.init();
canvas_shader.init();
copy_shader.init();
+ canvas_shadow_shader.init();
#ifdef GLEW_ENABLED
material_shader.set_conditional(MaterialShaderGLES2::USE_GLES_OVER_GL,true);
canvas_shader.set_conditional(CanvasShaderGLES2::USE_GLES_OVER_GL,true);
+ canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_GLES_OVER_GL,true);
copy_shader.set_conditional(CopyShaderGLES2::USE_GLES_OVER_GL,true);
#endif
@@ -9923,8 +10463,11 @@ void RasterizerGLES2::init() {
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_texture_size);
//read_depth_supported=false;
+ canvas_shadow_blur = canvas_light_shadow_buffer_create(max_texture_size);
+
{
//shadowmaps
OS::VideoMode vm=OS::get_singleton()->get_video_mode();
@@ -9946,6 +10489,7 @@ void RasterizerGLES2::init() {
//material_shader
material_shader.set_conditional(MaterialShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps);
+ canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps);
}
@@ -9978,7 +10522,7 @@ void RasterizerGLES2::init() {
void RasterizerGLES2::finish() {
-
+ free(canvas_shadow_blur);
}
int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) {
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index 173ca1418..f09714f50 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -51,6 +51,7 @@
#include "drivers/gles2/shaders/material.glsl.h"
#include "drivers/gles2/shaders/canvas.glsl.h"
+#include "drivers/gles2/shaders/canvas_shadow.glsl.h"
#include "drivers/gles2/shaders/blur.glsl.h"
#include "drivers/gles2/shaders/copy.glsl.h"
#include "drivers/gles2/shader_compiler_gles2.h"
@@ -816,6 +817,7 @@ class RasterizerGLES2 : public Rasterizer {
bool current_depth_mask;
VS::MaterialBlendMode current_blend_mode;
bool use_fast_texture_filter;
+ int max_texture_size;
bool fragment_lighting;
RID shadow_material;
@@ -1160,6 +1162,7 @@ class RasterizerGLES2 : public Rasterizer {
void _process_glow_and_bloom();
//void _update_blur_buffer();
+
/*********/
/* FRAME */
/*********/
@@ -1178,6 +1181,45 @@ class RasterizerGLES2 : public Rasterizer {
} _rinfo;
+ /*******************/
+ /* CANVAS OCCLUDER */
+ /*******************/
+
+
+ struct CanvasOccluder {
+
+ GLuint vertex_id; // 0 means, unconfigured
+ GLuint index_id; // 0 means, unconfigured
+ DVector lines;
+ int len;
+ };
+
+ RID_Owner canvas_occluder_owner;
+
+ /***********************/
+ /* CANVAS LIGHT SHADOW */
+ /***********************/
+
+
+ struct CanvasLightShadow {
+
+ int size;
+ int height;
+ GLuint fbo;
+ GLuint rbo;
+ GLuint depth;
+ GLuint rgba; //for older devices
+
+ GLuint blur;
+
+ };
+
+ RID_Owner canvas_light_shadow_owner;
+
+ RID canvas_shadow_blur;
+
+ /* ETC */
+
RenderTarget *current_rt;
bool current_rt_transparent;
bool current_rt_vflip;
@@ -1192,7 +1234,7 @@ class RasterizerGLES2 : public Rasterizer {
bool uses_texpixel_size;
bool rebind_texpixel_size;
Transform canvas_transform;
- RID canvas_last_shader;
+ CanvasItemMaterial *canvas_last_material;
bool canvas_texscreen_used;
Vector2 normal_flip;
_FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2& p_flip);
@@ -1227,10 +1269,12 @@ class RasterizerGLES2 : public Rasterizer {
VS::ScenarioDebugMode current_debug;
RID overdraw_material;
+
mutable MaterialShaderGLES2 material_shader;
mutable CanvasShaderGLES2 canvas_shader;
BlurShaderGLES2 blur_shader;
CopyShaderGLES2 copy_shader;
+ mutable CanvasShadowShaderGLES2 canvas_shadow_shader;
mutable ShaderCompilerGLES2 shader_precompiler;
@@ -1254,8 +1298,8 @@ class RasterizerGLES2 : public Rasterizer {
template
_FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip);
- _FORCE_INLINE_ void _canvas_item_setup_shader_params(CanvasItem *shader_owner,Shader* p_shader);
- _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItem *shader_owner,Shader* p_shader);
+ _FORCE_INLINE_ void _canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* p_shader);
+ _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* p_shader);
public:
/* TEXTURE API */
@@ -1572,7 +1616,17 @@ public:
virtual void canvas_set_transform(const Matrix32& p_transform);
virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light);
+ virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow);
+ /* CANVAS LIGHT SHADOW */
+
+ //buffer
+ virtual RID canvas_light_shadow_buffer_create(int p_width);
+ virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache);
+
+ //occluder
+ virtual RID canvas_light_occluder_create();
+ virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector& p_lines);
/* ENVIRONMENT */
@@ -1611,6 +1665,8 @@ public:
virtual bool is_environment(const RID& p_rid) const;
virtual bool is_shader(const RID& p_rid) const;
+ virtual bool is_canvas_light_occluder(const RID& p_rid) const;
+
virtual void free(const RID& p_rid);
virtual void init();
diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub
index c665cf903..9679223b1 100644
--- a/drivers/gles2/shaders/SCsub
+++ b/drivers/gles2/shaders/SCsub
@@ -3,6 +3,7 @@ Import('env')
if env['BUILDERS'].has_key('GLSL120GLES'):
env.GLSL120GLES('material.glsl');
env.GLSL120GLES('canvas.glsl');
+ env.GLSL120GLES('canvas_shadow.glsl');
env.GLSL120GLES('blur.glsl');
env.GLSL120GLES('copy.glsl');
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index 227a8b7bd..9022f30d7 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -34,6 +34,10 @@ varying vec4 local_rot;
uniform vec2 normal_flip;
#endif
+#ifdef USE_SHADOWS
+highp varying vec2 pos;
+#endif
+
#endif
#if defined(ENABLE_VAR1_INTERP)
@@ -63,6 +67,8 @@ VERTEX_SHADER_CODE
outvec = modelview_matrix * outvec;
#endif
+
+
#ifdef USE_PIXEL_SNAP
outvec.xy=floor(outvec.xy+0.5);
@@ -75,6 +81,9 @@ VERTEX_SHADER_CODE
light_uv_interp.xy = (light_matrix * outvec).xy;
light_uv_interp.zw = outvec.xy-light_pos;
+#ifdef USE_SHADOWS
+ pos=outvec.xy;
+#endif
#if defined(NORMAL_USED)
local_rot.xy=normalize( (modelview_matrix * ( extra_matrix * vec4(1.0,0.0,0.0,0.0) )).xy )*normal_flip.x;
@@ -154,6 +163,15 @@ varying vec4 local_rot;
uniform sampler2D shadow_texture;
uniform float shadow_attenuation;
+uniform highp mat4 shadow_matrix;
+uniform highp mat4 light_local_matrix;
+highp varying vec2 pos;
+uniform float shadowpixel_size;
+
+#ifdef SHADOW_ESM
+uniform float shadow_esm_multiplier;
+#endif
+
#endif
#endif
@@ -173,10 +191,6 @@ void main() {
vec3 normal = vec3(0,0,1);
#endif
-#ifdef USE_MODULATE
-
- color*=modulate;
-#endif
color *= texture2D( texture, uv_interp );
#if defined(ENABLE_SCREEN_UV)
@@ -191,6 +205,12 @@ FRAGMENT_SHADER_CODE
color = vec4(vec3(enc32),1.0);
#endif
+#ifdef USE_MODULATE
+
+ color*=modulate;
+#endif
+
+
#ifdef USE_LIGHTING
#if defined(NORMAL_USED)
@@ -201,13 +221,96 @@ FRAGMENT_SHADER_CODE
vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color;
#ifdef USE_SHADOWS
- //this might not be that great on mobile?
- float light_dist = length(light_texture.zw);
- float light_angle = atan2(light_texture.x,light_texture.z) + 1.0 * 0.5;
- float shadow_dist = texture2D(shadow_texture,vec2(light_angle,0));
- if (light_dist>shadow_dist) {
- light*=shadow_attenuation;
+
+
+ vec2 lpos = (light_local_matrix * vec4(pos,0.0,1.0)).xy;
+ float angle_to_light = -atan(lpos.x,lpos.y);
+ float PI = 3.14159265358979323846264;
+ /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays
+ float ang*/
+
+ float su,sz;
+
+ float abs_angle = abs(angle_to_light);
+ vec2 point;
+ float sh;
+ if (abs_angle<45.0*PI/180.0) {
+ point = lpos;
+ sh=0+(1.0/8.0);
+ } else if (abs_angle>135.0*PI/180.0) {
+ point = -lpos;
+ sh = 0.5+(1.0/8.0);
+ } else if (angle_to_light>0) {
+
+ point = vec2(lpos.y,-lpos.x);
+ sh = 0.25+(1.0/8.0);
+ } else {
+
+ point = vec2(-lpos.y,lpos.x);
+ sh = 0.75+(1.0/8.0);
+
+ }
+
+
+ vec4 s = shadow_matrix * vec4(point,0.0,1.0);
+ s.xyz/=s.w;
+ su=s.x*0.5+0.5;
+ sz=s.z*0.5+0.5;
+
+ float shadow_attenuation;
+
+#ifdef SHADOW_PCF5
+
+ shadow_attenuation=0.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).z
+#include "Shlwapi.h"
#include "file_access_windows.h"
+
#include
#include
#include
#include
#include "print_string.h"
+
#ifdef _MSC_VER
#define S_ISREG(m) ((m)&_S_IFREG)
#endif
@@ -111,10 +115,20 @@ void FileAccessWindows::close() {
//unlink(save_path.utf8().get_data());
//print_line("renaming..");
- _wunlink(save_path.c_str()); //unlink if exists
- int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());
+ //_wunlink(save_path.c_str()); //unlink if exists
+ //int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());
+
+
+ bool rename_error;
+ if (!PathFileExistsW(save_path.c_str())) {
+ //creating new file
+ rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str())!=0;
+ } else {
+ //atomic replace for existing file
+ rename_error = !ReplaceFileW(save_path.c_str(), (save_path+".tmp").c_str(), NULL, 2|4, NULL, NULL);
+ }
save_path="";
- ERR_FAIL_COND( rename_error != 0);
+ ERR_FAIL_COND( rename_error );
}
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 0aa115ffb..d3a9abf4b 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -2696,7 +2696,10 @@ Error ResourceFormatSaverGDScript::save(const String &p_path,const RES& p_resour
}
file->store_string(source);
-
+ if (file->get_error()!=OK && file->get_error()!=ERR_FILE_EOF) {
+ memdelete(file);
+ return ERR_CANT_CREATE;
+ }
file->close();
memdelete(file);
return OK;
diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp
index 857d1a4a5..4c0c095e1 100644
--- a/platform/android/audio_driver_opensl.cpp
+++ b/platform/android/audio_driver_opensl.cpp
@@ -396,6 +396,14 @@ void AudioDriverOpenSL::finish(){
void AudioDriverOpenSL::set_pause(bool p_pause) {
pause=p_pause;
+
+ if (active) {
+ if (pause) {
+ (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED);
+ } else {
+ (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
+ }
+ }
}
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 6f1c03b59..6b91c01df 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -151,7 +151,7 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
sample_manager = memnew( SampleManagerMallocSW );
audio_server = memnew( AudioServerSW(sample_manager) );
- audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,false);
+ audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,true);
audio_server->init();
spatial_sound_server = memnew( SpatialSoundServerSW );
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 16dd695c5..62bab00f7 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -115,7 +115,7 @@ def configure(env):
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
env.Append(CCFLAGS=['/DGLEW_ENABLED'])
- LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32']
+ LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI','Shlwapi', 'wsock32', 'shell32','advapi32']
env.Append(LINKFLAGS=[p+env["LIBSUFFIX"] for p in LIBS])
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
@@ -229,7 +229,7 @@ def configure(env):
env.Append(CCFLAGS=['-DWINDOWS_ENABLED','-mwindows'])
env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLEW_ENABLED'])
- env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','wsock32','kernel32'])
+ env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','shlwapi','wsock32','kernel32'])
if (env["bits"]=="32" and env["mingw64_for_32"]!="yes"):
# env.Append(LIBS=['gcc_s'])
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 223adaf9b..4a1842100 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -36,6 +36,192 @@
#include "scene/resources/texture.h"
#include "scene/resources/style_box.h"
+
+bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value) {
+
+ if (p_name==SceneStringNames::get_singleton()->shader_shader) {
+ set_shader(p_value);
+ return true;
+ } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
+ set_unshaded(p_value);
+ print_line("set unshaded");
+ return true;
+ } else {
+
+ if (shader.is_valid()) {
+
+
+ StringName pr = shader->remap_param(p_name);
+ if (!pr) {
+ String n = p_name;
+ if (n.find("param/")==0) { //backwards compatibility
+ pr = n.substr(6,n.length());
+ }
+ }
+ if (pr) {
+ VisualServer::get_singleton()->canvas_item_material_set_shader_param(material,pr,p_value);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
+
+
+ if (p_name==SceneStringNames::get_singleton()->shader_shader) {
+
+ r_ret=get_shader();
+ return true;
+ } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
+
+
+ r_ret=unshaded;
+ return true;
+ } else {
+
+ if (shader.is_valid()) {
+
+ StringName pr = shader->remap_param(p_name);
+ if (pr) {
+ r_ret=VisualServer::get_singleton()->canvas_item_material_get_shader_param(material,pr);
+ return true;
+ }
+ }
+
+ }
+
+
+ return false;
+}
+
+
+void CanvasItemMaterial::_get_property_list( List *p_list) const {
+
+ p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemShader,CanvasItemShaderGraph" ) );
+ p_list->push_back( PropertyInfo( Variant::BOOL, "shader/unshaded") );
+
+ if (!shader.is_null()) {
+
+ shader->get_param_list(p_list);
+ }
+
+}
+
+void CanvasItemMaterial::set_shader(const Ref& p_shader) {
+
+ ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM);
+#ifdef TOOLS_ENABLED
+
+ if (shader.is_valid()) {
+ shader->disconnect("changed",this,"_shader_changed");
+ }
+#endif
+ shader=p_shader;
+
+#ifdef TOOLS_ENABLED
+
+ if (shader.is_valid()) {
+ shader->connect("changed",this,"_shader_changed");
+ }
+#endif
+
+ RID rid;
+ if (shader.is_valid())
+ rid=shader->get_rid();
+
+ VS::get_singleton()->canvas_item_material_set_shader(material,rid);
+ _change_notify(); //properties for shader exposed
+ emit_changed();
+}
+
+Ref CanvasItemMaterial::get_shader() const{
+
+ return shader;
+}
+
+void CanvasItemMaterial::set_shader_param(const StringName& p_param,const Variant& p_value){
+
+ VS::get_singleton()->canvas_item_material_set_shader_param(material,p_param,p_value);
+}
+
+Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{
+
+ return VS::get_singleton()->canvas_item_material_get_shader_param(material,p_param);
+}
+
+void CanvasItemMaterial::_shader_changed() {
+
+
+}
+
+RID CanvasItemMaterial::get_rid() const {
+
+ return material;
+}
+
+void CanvasItemMaterial::set_unshaded(bool p_unshaded) {
+
+ unshaded=p_unshaded;
+ VS::get_singleton()->canvas_item_material_set_unshaded(material,p_unshaded);
+}
+
+bool CanvasItemMaterial::is_unshaded() const{
+
+ return unshaded;
+}
+
+void CanvasItemMaterial::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader);
+ ObjectTypeDB::bind_method(_MD("get_shader:Shader"),&CanvasItemMaterial::get_shader);
+ ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param);
+ ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param);
+ ObjectTypeDB::bind_method(_MD("set_unshaded","unshaded"),&CanvasItemMaterial::set_unshaded);
+ ObjectTypeDB::bind_method(_MD("is_unshaded"),&CanvasItemMaterial::is_unshaded);
+
+}
+
+void CanvasItemMaterial::get_argument_options(const StringName& p_function,int p_idx,List*r_options) const {
+
+ String f = p_function.operator String();
+ if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) {
+
+ if (shader.is_valid()) {
+ List pl;
+ shader->get_param_list(&pl);
+ for (List::Element *E=pl.front();E;E=E->next()) {
+ r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
+ }
+ }
+ }
+ Resource::get_argument_options(p_function,p_idx,r_options);
+}
+
+CanvasItemMaterial::CanvasItemMaterial() {
+
+ material=VS::get_singleton()->canvas_item_material_create();
+ unshaded=false;
+}
+
+CanvasItemMaterial::~CanvasItemMaterial(){
+
+ VS::get_singleton()->free(material);
+}
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////
+
+
+
bool CanvasItem::is_visible() const {
if (!is_inside_tree())
@@ -730,111 +916,35 @@ bool CanvasItem::is_draw_behind_parent_enabled() const{
return behind;
}
-void CanvasItem::set_shader(const Ref& p_shader) {
-
- ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM);
-
-#ifdef TOOLS_ENABLED
-
- if (shader.is_valid()) {
- shader->disconnect("changed",this,"_shader_changed");
- }
-#endif
- shader=p_shader;
-
-#ifdef TOOLS_ENABLED
+void CanvasItem::set_material(const Ref& p_material) {
- if (shader.is_valid()) {
- shader->connect("changed",this,"_shader_changed");
- }
-#endif
+ material=p_material;
RID rid;
- if (shader.is_valid())
- rid=shader->get_rid();
- VS::get_singleton()->canvas_item_set_shader(canvas_item,rid);
- _change_notify(); //properties for shader exposed
-}
-
-void CanvasItem::set_use_parent_shader(bool p_use_parent_shader) {
-
- use_parent_shader=p_use_parent_shader;
- VS::get_singleton()->canvas_item_set_use_parent_shader(canvas_item,p_use_parent_shader);
+ if (material.is_valid())
+ rid=material->get_rid();
+ VS::get_singleton()->canvas_item_set_material(canvas_item,rid);
+ _change_notify(); //properties for material exposed
}
-bool CanvasItem::get_use_parent_shader() const{
+void CanvasItem::set_use_parent_material(bool p_use_parent_material) {
- return use_parent_shader;
+ use_parent_material=p_use_parent_material;
+ VS::get_singleton()->canvas_item_set_use_parent_material(canvas_item,p_use_parent_material);
}
-Ref CanvasItem::get_shader() const{
+bool CanvasItem::get_use_parent_material() const{
- return shader;
+ return use_parent_material;
}
-void CanvasItem::set_shader_param(const StringName& p_param,const Variant& p_value) {
+Ref CanvasItem::get_material() const{
- VS::get_singleton()->canvas_item_set_shader_param(canvas_item,p_param,p_value);
+ return material;
}
-Variant CanvasItem::get_shader_param(const StringName& p_param) const {
-
- return VS::get_singleton()->canvas_item_get_shader_param(canvas_item,p_param);
-}
-
-bool CanvasItem::_set(const StringName& p_name, const Variant& p_value) {
-
- if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
- if (pr) {
- set_shader_param(pr,p_value);
- return true;
- }
- }
- return false;
-}
-bool CanvasItem::_get(const StringName& p_name,Variant &r_ret) const{
- if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
- if (pr) {
- r_ret=get_shader_param(pr);
- return true;
- }
- }
- return false;
-
-}
-void CanvasItem::_get_property_list( List *p_list) const{
-
- if (shader.is_valid()) {
- shader->get_param_list(p_list);
- }
-}
-
-#ifdef TOOLS_ENABLED
-void CanvasItem::_shader_changed() {
-
- _change_notify();
-}
-#endif
-
-void CanvasItem::get_argument_options(const StringName& p_function,int p_idx,List*r_options) const {
-
- if (p_idx==0 && shader.is_valid() && (p_function.operator String()=="get_shader_param" || p_function.operator String()=="set_shader_param")) {
-
- List pl;
- shader->get_param_list(&pl);
- for(List::Element *E=pl.front();E;E=E->next()) {
- r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
- }
-
- return;
- }
-
- Node::get_argument_options(p_function,p_idx,r_options);
-}
void CanvasItem::_bind_methods() {
@@ -880,9 +990,6 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top);
ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top);
-#ifdef TOOLS_ENABLED
- ObjectTypeDB::bind_method(_MD("_shader_changed"),&CanvasItem::_shader_changed);
-#endif
//ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0));
@@ -901,20 +1008,18 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform);
ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
ObjectTypeDB::bind_method(_MD("get_global_transform"),&CanvasItem::get_global_transform);
+ ObjectTypeDB::bind_method(_MD("get_global_transform_with_canvas"),&CanvasItem::get_global_transform_with_canvas);
ObjectTypeDB::bind_method(_MD("get_viewport_transform"),&CanvasItem::get_viewport_transform);
ObjectTypeDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect);
ObjectTypeDB::bind_method(_MD("get_canvas"),&CanvasItem::get_canvas);
ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d);
//ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
- ObjectTypeDB::bind_method(_MD("set_shader","shader"),&CanvasItem::set_shader);
- ObjectTypeDB::bind_method(_MD("get_shader"),&CanvasItem::get_shader);
- ObjectTypeDB::bind_method(_MD("set_use_parent_shader","enable"),&CanvasItem::set_use_parent_shader);
- ObjectTypeDB::bind_method(_MD("get_use_parent_shader"),&CanvasItem::get_use_parent_shader);
-
- ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItem::set_shader_param);
- ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItem::get_shader_param);
+ ObjectTypeDB::bind_method(_MD("set_material","material:CanvasItemMaterial"),&CanvasItem::set_material);
+ ObjectTypeDB::bind_method(_MD("get_material:CanvasItemMaterial"),&CanvasItem::get_material);
+ ObjectTypeDB::bind_method(_MD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material);
+ ObjectTypeDB::bind_method(_MD("get_use_parent_material"),&CanvasItem::get_use_parent_material);
BIND_VMETHOD(MethodInfo("_draw"));
@@ -926,8 +1031,8 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/light_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"),_SCS("get_light_mask") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"shader/shader",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph"), _SCS("set_shader"),_SCS("get_shader") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"shader/use_parent"), _SCS("set_use_parent_shader"),_SCS("get_use_parent_shader") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"material/material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"),_SCS("get_material") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"material/use_parent"), _SCS("set_use_parent_material"),_SCS("get_use_parent_material") );
//exporting these two things doesn't really make much sense i think
//ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") );
//ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled"));
@@ -1004,7 +1109,7 @@ CanvasItem::CanvasItem() : xform_change(this) {
block_transform_notify=false;
// viewport=NULL;
canvas_layer=NULL;
- use_parent_shader=false;
+ use_parent_material=false;
global_invalid=true;
light_mask=1;
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 2441d205c..0c7be261a 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -40,6 +40,41 @@ class Font;
class StyleBox;
+class CanvasItemMaterial : public Resource{
+
+ OBJ_TYPE(CanvasItemMaterial,Resource);
+ RID material;
+ Ref shader;
+ bool unshaded;
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List *p_list) const;
+
+ void _shader_changed();
+ static void _bind_methods();
+
+ void get_argument_options(const StringName& p_function,int p_idx,List*r_options) const;
+
+public:
+
+ void set_shader(const Ref& p_shader);
+ Ref get_shader() const;
+
+ void set_shader_param(const StringName& p_param,const Variant& p_value);
+ Variant get_shader_param(const StringName& p_param) const;
+
+ void set_unshaded(bool p_unshaded);
+ bool is_unshaded() const;
+
+ virtual RID get_rid() const;
+ CanvasItemMaterial();
+ ~CanvasItemMaterial();
+};
+
+
class CanvasItem : public Node {
OBJ_TYPE( CanvasItem, Node );
@@ -81,9 +116,9 @@ private:
bool drawing;
bool block_transform_notify;
bool behind;
- bool use_parent_shader;
+ bool use_parent_material;
- Ref shader;
+ Ref material;
mutable Matrix32 global_transform;
mutable bool global_invalid;
@@ -104,9 +139,6 @@ private:
void _queue_sort_children();
void _sort_children();
-#ifdef TOOLS_ENABLED
- void _shader_changed();
-#endif
void _notify_transform(CanvasItem *p_node);
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
@@ -114,11 +146,6 @@ private:
protected:
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List *p_list) const;
-
-
_FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); }
void item_rect_changed();
@@ -216,16 +243,12 @@ public:
RID get_canvas() const;
Ref get_world_2d() const;
- void set_shader(const Ref& p_shader);
- Ref get_shader() const;
+ void set_material(const Ref& p_material);
+ Ref get_material() const;
- void set_use_parent_shader(bool p_use_parent_shader);
- bool get_use_parent_shader() const;
+ void set_use_parent_material(bool p_use_parent_material);
+ bool get_use_parent_material() const;
- void set_shader_param(const StringName& p_param,const Variant& p_value);
- Variant get_shader_param(const StringName& p_param) const;
-
- void get_argument_options(const StringName& p_function,int p_idx,List*r_options) const;
CanvasItem();
~CanvasItem();
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index cea8c06d3..93be0c397 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -170,6 +170,29 @@ bool Light2D::is_shadow_enabled() const {
return shadow;
}
+void Light2D::set_shadow_buffer_size( int p_size ) {
+
+ shadow_buffer_size=p_size;
+ VS::get_singleton()->canvas_light_set_shadow_buffer_size(canvas_light,shadow_buffer_size);
+}
+
+int Light2D::get_shadow_buffer_size() const {
+
+ return shadow_buffer_size;
+}
+
+void Light2D::set_shadow_esm_multiplier( float p_multiplier) {
+
+ shadow_esm_multiplier=p_multiplier;
+ VS::get_singleton()->canvas_light_set_shadow_esm_multiplier(canvas_light,p_multiplier);
+}
+
+float Light2D::get_shadow_esm_multiplier() const{
+
+ return shadow_esm_multiplier;
+}
+
+
void Light2D::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
@@ -229,18 +252,26 @@ void Light2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled);
+ ObjectTypeDB::bind_method(_MD("set_shadow_buffer_size","size"),&Light2D::set_shadow_buffer_size);
+ ObjectTypeDB::bind_method(_MD("get_shadow_buffer_size"),&Light2D::get_shadow_buffer_size);
+
+ ObjectTypeDB::bind_method(_MD("set_shadow_esm_multiplier","multiplier"),&Light2D::set_shadow_esm_multiplier);
+ ObjectTypeDB::bind_method(_MD("get_shadow_esm_multiplier"),&Light2D::get_shadow_esm_multiplier);
+
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture_offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"height"),_SCS("set_height"),_SCS("get_height"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"subtract"),_SCS("set_subtract_mode"),_SCS("get_subtract_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow_enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow/enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),_SCS("set_shadow_buffer_size"),_SCS("get_shadow_buffer_size"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier"));
}
@@ -258,6 +289,8 @@ Light2D::Light2D() {
layer_max=0;
item_mask=1;
subtract_mode=false;
+ shadow_buffer_size=2048;
+ shadow_esm_multiplier=80;
}
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index dbfd233d3..89f351c3c 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -17,6 +17,8 @@ private:
int layer_min;
int layer_max;
int item_mask;
+ int shadow_buffer_size;
+ float shadow_esm_multiplier;
bool subtract_mode;
Ref texture;
Vector2 texture_offset;
@@ -68,6 +70,12 @@ public:
void set_shadow_enabled( bool p_enabled);
bool is_shadow_enabled() const;
+ void set_shadow_buffer_size( int p_size );
+ int get_shadow_buffer_size() const;
+
+ void set_shadow_esm_multiplier( float p_multiplier);
+ float get_shadow_esm_multiplier() const;
+
virtual Rect2 get_item_rect() const;
Light2D();
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
new file mode 100644
index 000000000..186ea2e24
--- /dev/null
+++ b/scene/2d/light_occluder_2d.cpp
@@ -0,0 +1,201 @@
+#include "light_occluder_2d.h"
+
+
+void OccluderPolygon2D::set_polygon(const DVector& p_polygon) {
+
+ polygon=p_polygon;
+ VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,p_polygon,closed);
+ emit_changed();
+}
+
+DVector OccluderPolygon2D::get_polygon() const{
+
+ return polygon;
+}
+
+void OccluderPolygon2D::set_closed(bool p_closed) {
+
+ if (closed==p_closed)
+ return;
+ closed=p_closed;
+ VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,polygon,closed);
+ emit_changed();
+}
+
+bool OccluderPolygon2D::is_closed() const{
+
+ return closed;
+}
+
+void OccluderPolygon2D::set_cull_mode(CullMode p_mode){
+
+ cull=p_mode;
+ VS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon,VS::CanvasOccluderPolygonCullMode(p_mode));
+}
+
+OccluderPolygon2D::CullMode OccluderPolygon2D::get_cull_mode() const{
+
+ return cull;
+}
+
+
+RID OccluderPolygon2D::get_rid() const {
+
+ return occ_polygon;
+}
+
+void OccluderPolygon2D::_bind_methods() {
+
+
+ ObjectTypeDB::bind_method(_MD("set_closed","closed"),&OccluderPolygon2D::set_closed);
+ ObjectTypeDB::bind_method(_MD("is_closed"),&OccluderPolygon2D::is_closed);
+
+ ObjectTypeDB::bind_method(_MD("set_cull_mode","cull_mode"),&OccluderPolygon2D::set_cull_mode);
+ ObjectTypeDB::bind_method(_MD("get_cull_mode"),&OccluderPolygon2D::get_cull_mode);
+
+ ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&OccluderPolygon2D::set_polygon);
+ ObjectTypeDB::bind_method(_MD("get_polygon"),&OccluderPolygon2D::get_polygon);
+
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"closed"),_SCS("set_closed"),_SCS("is_closed"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mode",PROPERTY_HINT_ENUM,"Disabled,ClockWise,CounterClockWise"),_SCS("set_cull_mode"),_SCS("get_cull_mode"));
+
+ BIND_CONSTANT(CULL_DISABLED);
+ BIND_CONSTANT(CULL_CLOCKWISE);
+ BIND_CONSTANT(CULL_COUNTER_CLOCKWISE);
+}
+
+
+OccluderPolygon2D::OccluderPolygon2D() {
+
+ occ_polygon=VS::get_singleton()->canvas_occluder_polygon_create();
+ closed=true;
+ cull=CULL_DISABLED;
+}
+
+OccluderPolygon2D::~OccluderPolygon2D() {
+
+ VS::get_singleton()->free(occ_polygon);
+}
+
+#ifdef DEBUG_ENABLED
+void LightOccluder2D::_poly_changed() {
+
+ update();
+}
+#endif
+
+
+void LightOccluder2D::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_CANVAS) {
+
+ VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,get_canvas());
+ VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
+
+ }
+ if (p_what==NOTIFICATION_TRANSFORM_CHANGED) {
+
+ VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ if (get_tree()->is_editor_hint()) {
+
+ if (occluder_polygon.is_valid()) {
+
+ DVector poly = occluder_polygon->get_polygon();
+
+ if (poly.size()) {
+ if (occluder_polygon->is_closed()) {
+ Vector color;
+ color.push_back(Color(0,0,0,0.6));
+ draw_polygon(Variant(poly),color);
+ } else {
+
+ int ps=poly.size();
+ DVector::Read r = poly.read();
+ for(int i=0;icanvas_light_occluder_attach_to_canvas(occluder,RID());
+ }
+
+
+}
+
+void LightOccluder2D::set_occluder_polygon(const Ref& p_polygon) {
+
+#ifdef DEBUG_ENABLED
+ if (occluder_polygon.is_valid())
+ occluder_polygon->disconnect("changed",this,"_poly_changed");
+#endif
+ occluder_polygon=p_polygon;
+
+ if (occluder_polygon.is_valid())
+ VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,occluder_polygon->get_rid());
+ else
+ VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,RID());
+
+#ifdef DEBUG_ENABLED
+ if (occluder_polygon.is_valid())
+ occluder_polygon->connect("changed",this,"_poly_changed");
+ update();
+#endif
+
+}
+
+Ref LightOccluder2D::get_occluder_polygon() const {
+
+ return occluder_polygon;
+}
+
+void LightOccluder2D::set_occluder_light_mask(int p_mask) {
+
+ mask=p_mask;
+ VS::get_singleton()->canvas_light_occluder_set_light_mask(occluder,mask);
+}
+
+int LightOccluder2D::get_occluder_light_mask() const{
+
+ return mask;
+}
+
+void LightOccluder2D::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_occluder_polygon","polygon:OccluderPolygon2D"),&LightOccluder2D::set_occluder_polygon);
+ ObjectTypeDB::bind_method(_MD("get_occluder_polygon:OccluderPolygon2D"),&LightOccluder2D::get_occluder_polygon);
+
+ ObjectTypeDB::bind_method(_MD("set_occluder_light_mask","mask"),&LightOccluder2D::set_occluder_light_mask);
+ ObjectTypeDB::bind_method(_MD("get_occluder_light_mask"),&LightOccluder2D::get_occluder_light_mask);
+
+#ifdef DEBUG_ENABLED
+ ObjectTypeDB::bind_method("_poly_changed",&LightOccluder2D::_poly_changed);
+#endif
+
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D"),_SCS("set_occluder_polygon"),_SCS("get_occluder_polygon"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_occluder_light_mask"),_SCS("get_occluder_light_mask"));
+}
+
+LightOccluder2D::LightOccluder2D() {
+
+ occluder=VS::get_singleton()->canvas_light_occluder_create();
+ mask=1;
+}
+
+LightOccluder2D::~LightOccluder2D() {
+
+ VS::get_singleton()->free(occluder);
+}
+
diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h
new file mode 100644
index 000000000..0343e3697
--- /dev/null
+++ b/scene/2d/light_occluder_2d.h
@@ -0,0 +1,73 @@
+#ifndef LIGHTOCCLUDER2D_H
+#define LIGHTOCCLUDER2D_H
+
+#include "scene/2d/node_2d.h"
+
+class OccluderPolygon2D : public Resource {
+
+ OBJ_TYPE(OccluderPolygon2D,Resource);
+public:
+
+ enum CullMode {
+ CULL_DISABLED,
+ CULL_CLOCKWISE,
+ CULL_COUNTER_CLOCKWISE
+ };
+private:
+
+
+ RID occ_polygon;
+ DVector polygon;
+ bool closed;
+ CullMode cull;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ void set_polygon(const DVector& p_polygon);
+ DVector get_polygon() const;
+
+ void set_closed(bool p_closed);
+ bool is_closed() const;
+
+ void set_cull_mode(CullMode p_mode);
+ CullMode get_cull_mode() const;
+
+ virtual RID get_rid() const;
+ OccluderPolygon2D();
+ ~OccluderPolygon2D();
+
+};
+
+VARIANT_ENUM_CAST(OccluderPolygon2D::CullMode);
+
+class LightOccluder2D : public Node2D {
+ OBJ_TYPE(LightOccluder2D,Node2D);
+
+ RID occluder;
+ bool enabled;
+ int mask;
+ Ref occluder_polygon;
+
+#ifdef DEBUG_ENABLED
+ void _poly_changed();
+#endif
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_occluder_polygon(const Ref& p_polygon);
+ Ref get_occluder_polygon() const;
+
+ void set_occluder_light_mask(int p_mask);
+ int get_occluder_light_mask() const;
+
+ LightOccluder2D();
+ ~LightOccluder2D();
+};
+
+#endif // LIGHTOCCLUDER2D_H
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 95eafa0df..110913918 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -152,11 +152,11 @@ void Camera::_get_property_list( List *p_list) const {
case PROJECTION_PERSPECTIVE: {
- p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_NOEDITOR) );
+ p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_NOEDITOR) );
if (keep_aspect==KEEP_WIDTH)
- p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) );
+ p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) );
else
- p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) );
+ p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) );
} break;
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index a82c69e67..45c7fa912 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -310,6 +310,17 @@ int GeometryInstance::get_baked_light_texture_id() const{
return baked_light_texture_id;
}
+void GeometryInstance::set_extra_cull_margin(float p_margin) {
+
+ ERR_FAIL_COND(p_margin<0);
+ extra_cull_margin=p_margin;
+ VS::get_singleton()->instance_set_extra_visibility_margin(get_instance(),extra_cull_margin);
+}
+
+float GeometryInstance::get_extra_cull_margin() const{
+
+ return extra_cull_margin;
+}
void GeometryInstance::_bind_methods() {
@@ -328,6 +339,9 @@ void GeometryInstance::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_baked_light_texture_id","id"), &GeometryInstance::set_baked_light_texture_id);
ObjectTypeDB::bind_method(_MD("get_baked_light_texture_id"), &GeometryInstance::get_baked_light_texture_id);
+ ObjectTypeDB::bind_method(_MD("set_extra_cull_margin","margin"), &GeometryInstance::set_extra_cull_margin);
+ ObjectTypeDB::bind_method(_MD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
+
ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE);
@@ -336,6 +350,7 @@ void GeometryInstance::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/receive_shadows"), _SCS("set_flag"), _SCS("get_flag"),FLAG_RECEIVE_SHADOWS);
ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_begin",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_begin"), _SCS("get_draw_range_begin"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_end",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_end"), _SCS("get_draw_range_end"));
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "geometry/extra_cull_margin",PROPERTY_HINT_RANGE,"0,16384,0"), _SCS("set_extra_cull_margin"), _SCS("get_extra_cull_margin"));
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard_y"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD_FIX_Y);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE);
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index e9fefe1ba..e08acbe9a 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -108,6 +108,7 @@ private:
void _find_baked_light();
BakedLightInstance *baked_light_instance;
int baked_light_texture_id;
+ float extra_cull_margin;
void _baked_light_changed();
void _update_visibility();
@@ -132,6 +133,9 @@ public:
void set_baked_light_texture_id(int p_id);
int get_baked_light_texture_id() const;
+ void set_extra_cull_margin(float p_margin);
+ float get_extra_cull_margin() const;
+
GeometryInstance();
};
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index ff525203b..f90db4261 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -80,6 +80,7 @@
#include "scene/2d/particles_2d.h"
#include "scene/2d/path_2d.h"
#include "scene/2d/light_2d.h"
+#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/canvas_item.h"
#include "scene/2d/sprite.h"
@@ -454,6 +455,7 @@ void register_scene_types() {
//ObjectTypeDB::set_type_enabled("BodyVolumeCylinder",false);
//ObjectTypeDB::set_type_enabled("BodyVolumeConvexPolygon",false);
+ ObjectTypeDB::register_type();
ObjectTypeDB::register_virtual_type();
ObjectTypeDB::register_type();
ObjectTypeDB::register_type();
@@ -476,6 +478,8 @@ void register_scene_types() {
ObjectTypeDB::register_type();
ObjectTypeDB::register_type();
ObjectTypeDB::register_type();
+ ObjectTypeDB::register_type();
+ ObjectTypeDB::register_type();
ObjectTypeDB::register_type();
ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index af5e6d416..c30ff0044 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -41,6 +41,7 @@ SceneStringNames::SceneStringNames() {
visibility_changed=StaticCString::create("visibility_changed");
input_event=StaticCString::create("input_event");
shader_shader=StaticCString::create("shader/shader");
+ shader_unshaded=StaticCString::create("shader/unshaded");
enter_tree=StaticCString::create("enter_tree");
exit_tree=StaticCString::create("exit_tree");
item_rect_changed=StaticCString::create("item_rect_changed");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 14e5e83b8..184cbe347 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -56,6 +56,7 @@ public:
StringName _input_event;
StringName item_rect_changed;
StringName shader_shader;
+ StringName shader_unshaded;
StringName enter_tree;
StringName exit_tree;
StringName size_flags_changed;
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 4c9d0491b..62ab8b3c5 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -572,8 +572,8 @@ public:
struct CanvasLight {
+
bool enabled;
- bool shadow;
Color color;
Matrix32 xform;
float height;
@@ -586,21 +586,26 @@ public:
RID texture;
Vector2 texture_offset;
RID canvas;
+ RID shadow_buffer;
+ int shadow_buffer_size;
+ float shadow_esm_mult;
void *texture_cache; // implementation dependent
Rect2 rect_cache;
Matrix32 xform_cache;
+ float radius_cache; //used for shadow far plane
+ CameraMatrix shadow_matrix_cache;
Matrix32 light_shader_xform;
Vector2 light_shader_pos;
+ CanvasLight *shadows_next_ptr;
CanvasLight *filter_next_ptr;
CanvasLight *next_ptr;
CanvasLight() {
- enabled=true;
- shadow=false;
+ enabled=true;
color=Color(1,1,1);
height=0;
z_min=-1024;
@@ -612,9 +617,24 @@ public:
texture_cache=NULL;
next_ptr=NULL;
filter_next_ptr=NULL;
+ shadow_buffer_size=2048;
+ shadow_esm_mult=80;
+
}
};
+ struct CanvasItem;
+
+ struct CanvasItemMaterial {
+
+ RID shader;
+ Map shader_param;
+ uint32_t shader_version;
+ Set owners;
+ bool unshaded;
+
+ CanvasItemMaterial() {unshaded=false; shader_version=0; }
+ };
struct CanvasItem {
@@ -744,16 +764,14 @@ public:
mutable bool rect_dirty;
mutable Rect2 rect;
CanvasItem*next;
- RID shader;
- Map shader_param;
- uint32_t shader_version;
+ CanvasItemMaterial* material;
float final_opacity;
Matrix32 final_transform;
Rect2 final_clip_rect;
CanvasItem* final_clip_owner;
- CanvasItem* shader_owner;
+ CanvasItem* material_owner;
ViewportRender *vp_render;
Rect2 global_rect_cache;
@@ -881,8 +899,8 @@ public:
return rect;
}
- void clear() { for (int i=0;i& p_lines)=0;
+
+
+ virtual RID canvas_light_shadow_buffer_create(int p_width)=0;
+ struct CanvasLightOccluderInstance {
+
+
+ bool enabled;
+ RID canvas;
+ RID polygon;
+ RID polygon_buffer;
+ Rect2 aabb_cache;
+ Matrix32 xform;
+ Matrix32 xform_cache;
+ int light_mask;
+ VS::CanvasOccluderPolygonCullMode cull_cache;
+
+ CanvasLightOccluderInstance *next;
+
+ CanvasLightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
+ };
+
+
+
+ virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0;
/* ENVIRONMENT */
@@ -945,6 +992,8 @@ public:
virtual bool is_environment(const RID& p_rid) const=0;
virtual bool is_shader(const RID& p_rid) const=0;
+ virtual bool is_canvas_light_occluder(const RID& p_rid) const=0;
+
virtual void free(const RID& p_rid)=0;
virtual void init()=0;
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index feb14d8a9..3bcf0b8a3 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -3765,55 +3765,32 @@ void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, boo
}
-void VisualServerRaster::canvas_item_set_use_parent_shader(RID p_item, bool p_enable) {
+void VisualServerRaster::canvas_item_set_use_parent_material(RID p_item, bool p_enable) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
- canvas_item->use_parent_shader=p_enable;
+ canvas_item->use_parent_material=p_enable;
}
-void VisualServerRaster::canvas_item_set_shader(RID p_item, RID p_shader) {
+void VisualServerRaster::canvas_item_set_material(RID p_item, RID p_material) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
- canvas_item->shader=p_shader;
-}
-
-RID VisualServerRaster::canvas_item_get_shader(RID p_item) const{
-
- CanvasItem *canvas_item = canvas_item_owner.get( p_item );
- ERR_FAIL_COND_V(!canvas_item,RID());
- return canvas_item->shader;
-}
+ if (canvas_item->material)
+ canvas_item->material->owners.erase(canvas_item);
-void VisualServerRaster::canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value){
+ canvas_item->material=NULL;
- VS_CHANGED;
- CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
- ERR_FAIL_COND(!canvas_item);
- if (p_value.get_type()==Variant::NIL)
- canvas_item->shader_param.erase(p_param);
- else
- canvas_item->shader_param[p_param]=p_value;
-
-}
-Variant VisualServerRaster::canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const{
-
- CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
- ERR_FAIL_COND_V(!canvas_item,Variant());
- if (!canvas_item->shader_param.has(p_param)) {
- ERR_FAIL_COND_V(!canvas_item->shader.is_valid(),Variant());
- return rasterizer->shader_get_default_param(canvas_item->shader,p_param);
+ if (canvas_item_material_owner.owns(p_material)) {
+ canvas_item->material=canvas_item_material_owner.get(p_material);
+ canvas_item->material->owners.insert(canvas_item);
}
-
- return canvas_item->shader_param[p_param];
}
-
void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
VS_CHANGED;
@@ -3989,19 +3966,41 @@ void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_ena
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
- clight->shadow=p_enabled;
+
+ if (clight->shadow_buffer.is_valid()==p_enabled)
+ return;
+ if (p_enabled) {
+ clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
+ } else {
+ rasterizer->free(clight->shadow_buffer);
+ clight->shadow_buffer=RID();
+
+ }
}
+
void VisualServerRaster::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
+ ERR_FAIL_COND(p_size<32 || p_size>16384);
+
+ clight->shadow_buffer_size=nearest_power_of_2(p_size);
+
+
+ if (clight->shadow_buffer.is_valid()) {
+ rasterizer->free(clight->shadow_buffer);
+ clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
+ }
+
}
-void VisualServerRaster::canvas_light_set_shadow_filter(RID p_light, int p_size){
+
+void VisualServerRaster::canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier) {
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
+ clight->shadow_esm_mult=p_multiplier;
}
@@ -4009,26 +4008,217 @@ void VisualServerRaster::canvas_light_set_shadow_filter(RID p_light, int p_size)
RID VisualServerRaster::canvas_light_occluder_create() {
- return RID();
+ Rasterizer::CanvasLightOccluderInstance *occluder = memnew( Rasterizer::CanvasLightOccluderInstance );
+
+ return canvas_light_occluder_owner.make_rid( occluder );
+
}
void VisualServerRaster::canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas) {
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.erase(occluder);
+ }
+
+ if (!canvas_owner.owns(p_canvas))
+ p_canvas=RID();
+
+ occluder->canvas=p_canvas;
+ if (occluder->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.insert(occluder);
+ }
}
void VisualServerRaster::canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled){
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->enabled=p_enabled;
}
-void VisualServerRaster::canvas_light_occluder_set_shape(RID p_occluder,const DVector& p_shape){
+void VisualServerRaster::canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->polygon.is_valid()) {
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
+ if (occluder_poly) {
+ occluder_poly->owners.erase(occluder);
+ }
+ }
+ occluder->polygon=p_polygon;
+ occluder->polygon_buffer=RID();
+
+ if (occluder->polygon.is_valid()) {
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
+ if (!occluder_poly)
+ occluder->polygon=RID();
+ ERR_FAIL_COND(!occluder_poly);
+ occluder_poly->owners.insert(occluder);
+ occluder->polygon_buffer=occluder_poly->occluder;
+ occluder->aabb_cache=occluder_poly->aabb;
+ occluder->cull_cache=occluder_poly->cull_mode;
+ }
}
+
+void VisualServerRaster::canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->xform=p_xform;
+
+}
+
+void VisualServerRaster::canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->light_mask=p_mask;
+
+}
+
+
+RID VisualServerRaster::canvas_occluder_polygon_create() {
+
+ CanvasLightOccluderPolygon * occluder_poly = memnew( CanvasLightOccluderPolygon );
+ occluder_poly->occluder=rasterizer->canvas_light_occluder_create();
+ return canvas_light_occluder_polygon_owner.make_rid(occluder_poly);
+
+}
+
+void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const DVector& p_shape, bool p_close){
+
+ if (p_shape.size()<3) {
+ canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape);
+ return;
+ }
+
+ DVector lines;
+ int lc = p_shape.size()*2;
+
+ lines.resize(lc-(p_close?0:2));
+ {
+ DVector::Write w = lines.write();
+ DVector::Read r = p_shape.read();
+
+ int max=lc/2;
+ if (!p_close) {
+ max--;
+ }
+ for(int i=0;i& p_shape) {
+
+ CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
+ ERR_FAIL_COND(!occluder_poly);
+ ERR_FAIL_COND(p_shape.size()&1);
+
+ int lc = p_shape.size();
+ occluder_poly->aabb=Rect2();
+ {
+ DVector::Read r = p_shape.read();
+ for(int i=0;iaabb.pos=r[i];
+ else
+ occluder_poly->aabb.expand_to(r[i]);
+ }
+ }
+
+ rasterizer->canvas_light_occluder_set_polylines(occluder_poly->occluder,p_shape);
+ for( Set::Element *E=occluder_poly->owners.front();E;E=E->next()) {
+ E->get()->aabb_cache=occluder_poly->aabb;
+ }
+}
+
+void VisualServerRaster::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode) {
+
+ CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
+ ERR_FAIL_COND(!occluder_poly);
+ occluder_poly->cull_mode=p_mode;
+ for( Set::Element *E=occluder_poly->owners.front();E;E=E->next()) {
+ E->get()->cull_cache=p_mode;
+ }
+
+}
+
+RID VisualServerRaster::canvas_item_material_create() {
+
+ Rasterizer::CanvasItemMaterial *material = memnew( Rasterizer::CanvasItemMaterial );
+ return canvas_item_material_owner.make_rid(material);
+
+}
+
+void VisualServerRaster::canvas_item_material_set_shader(RID p_material, RID p_shader){
+
+ VS_CHANGED;
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+ material->shader=p_shader;
+
+}
+void VisualServerRaster::canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value){
+
+ VS_CHANGED;
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+ if (p_value.get_type()==Variant::NIL)
+ material->shader_param.erase(p_param);
+ else
+ material->shader_param[p_param]=p_value;
+
+
+}
+Variant VisualServerRaster::canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const{
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND_V(!material,Variant());
+ if (!material->shader_param.has(p_param)) {
+ ERR_FAIL_COND_V(!material->shader.is_valid(),Variant());
+ return rasterizer->shader_get_default_param(material->shader,p_param);
+ }
+
+ return material->shader_param[p_param];
+}
+
+void VisualServerRaster::canvas_item_material_set_unshaded(RID p_material, bool p_unshaded){
+
+ VS_CHANGED;
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+ material->unshaded=p_unshaded;
+
+}
+
+
/******** CANVAS *********/
@@ -4285,6 +4475,10 @@ void VisualServerRaster::free( RID p_rid ) {
E->get()->canvas=RID();
}
+ for (Set::Element *E=canvas->occluders.front();E;E=E->next()) {
+
+ E->get()->canvas=RID();
+ }
canvas_owner.free( p_rid );
@@ -4314,10 +4508,26 @@ void VisualServerRaster::free( RID p_rid ) {
canvas_item->child_items[i]->parent=RID();
}
+ if (canvas_item->material) {
+ canvas_item->material->owners.erase(canvas_item);
+ }
+
canvas_item_owner.free( p_rid );
memdelete( canvas_item );
+ } else if (canvas_item_material_owner.owns(p_rid)) {
+
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get(p_rid);
+ ERR_FAIL_COND(!material);
+ for(Set::Element *E=material->owners.front();E;E=E->next()) {
+
+ E->get()->material=NULL;
+ }
+
+ canvas_item_material_owner.free(p_rid);
+ memdelete(material);
+
} else if (canvas_light_owner.owns(p_rid)) {
Rasterizer::CanvasLight *canvas_light = canvas_light_owner.get(p_rid);
@@ -4329,9 +4539,44 @@ void VisualServerRaster::free( RID p_rid ) {
canvas->lights.erase(canvas_light);
}
+ if (canvas_light->shadow_buffer.is_valid())
+ rasterizer->free(canvas_light->shadow_buffer);
+
canvas_light_owner.free( p_rid );
memdelete( canvas_light );
+ } else if (canvas_light_occluder_owner.owns(p_rid)) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_rid);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->polygon.is_valid()) {
+
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon);
+ if (occluder_poly) {
+ occluder_poly->owners.erase(occluder);
+ }
+
+ }
+
+ canvas_light_occluder_owner.free( p_rid );
+ memdelete(occluder);
+
+ } else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
+
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_rid);
+ ERR_FAIL_COND(!occluder_poly);
+ rasterizer->free(occluder_poly->occluder);
+
+ while(occluder_poly->owners.size()) {
+
+ occluder_poly->owners.front()->get()->polygon=RID();
+ occluder_poly->owners.erase( occluder_poly->owners.front() );
+ }
+
+ canvas_light_occluder_polygon_owner.free( p_rid );
+ memdelete(occluder_poly);
+
} else if (scenario_owner.owns(p_rid)) {
Scenario *scenario=scenario_owner.get(p_rid);
@@ -6410,7 +6655,7 @@ void VisualServerRaster::_render_canvas_item_viewport(VisualServer* p_self,void
}
-void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner) {
+void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_material_owner) {
CanvasItem *ci = p_canvas_item;
@@ -6455,11 +6700,11 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
ci->vp_render=NULL;
}
- if (ci->use_parent_shader && p_shader_owner)
- ci->shader_owner=p_shader_owner;
+ if (ci->use_parent_material && p_material_owner)
+ ci->material_owner=p_material_owner;
else {
- p_shader_owner=ci;
- ci->shader_owner=NULL;
+ p_material_owner=ci;
+ ci->material_owner=NULL;
}
@@ -6493,7 +6738,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
if (child_items[i]->ontop)
continue;
- _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner);
+ _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner);
}
@@ -6524,7 +6769,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
if (!child_items[i]->ontop)
continue;
- _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner);
+ _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner);
}
}
@@ -6658,6 +6903,8 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
Rect2 clip_rect(0,0,viewport_rect.width,viewport_rect.height);
Rasterizer::CanvasLight *lights=NULL;
+ Rasterizer::CanvasLight *lights_with_shadow=NULL;
+ Rect2 shadow_rect;
for (Map::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
@@ -6676,6 +6923,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
cl->rect_cache=Rect2(-offset+cl->texture_offset,tsize);
cl->xform_cache=xf * cl->xform;
+
if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) {
cl->filter_next_ptr=lights;
lights=cl;
@@ -6685,16 +6933,55 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
scale.elements[2]=cl->rect_cache.pos;
cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse();
cl->light_shader_pos=cl->xform_cache[2];
+ if (cl->shadow_buffer.is_valid()) {
+ cl->shadows_next_ptr=lights_with_shadow;
+ if (lights_with_shadow==NULL) {
+ shadow_rect = cl->xform_cache.xform(cl->rect_cache);
+ } else {
+ shadow_rect=shadow_rect.merge( cl->xform_cache.xform(cl->rect_cache) );
+ }
+ lights_with_shadow=cl;
+ cl->radius_cache=cl->rect_cache.size.length();
+
+ }
}
+ }
+ }
+
+ canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get();
+ }
+
+ if (lights_with_shadow) {
+ //update shadows if any
+
+ Rasterizer::CanvasLightOccluderInstance * occluders=NULL;
+
+ //make list of occluders
+ for (Map::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
+
+ Matrix32 xf = p_viewport->global_transform * E->get().transform;
+ for(Set::Element *F=E->get().canvas->occluders.front();F;F=F->next()) {
+ F->get()->xform_cache = xf * F->get()->xform;
+ if (shadow_rect.intersects_transformed(F->get()->xform_cache,F->get()->aabb_cache)) {
+ F->get()->next=occluders;
+ occluders=F->get();
+
+ }
}
}
+ //update the light shadowmaps with them
+ Rasterizer::CanvasLight *light=lights_with_shadow;
+ while(light) {
- canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get();
+ rasterizer->canvas_light_shadow_buffer_update(light->shadow_buffer,light->xform_cache.affine_inverse(),light->item_mask,light->radius_cache/1000.0,light->radius_cache*1.1,occluders,&light->shadow_matrix_cache);
+ light=light->shadows_next_ptr;
+ }
+ rasterizer->set_viewport(viewport_rect); //must reset viewport afterwards
}
for (Map::Element *E=canvas_map.front();E;E=E->next()) {
@@ -6719,6 +7006,8 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
i++;
}
+
+ rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
}
//capture
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 9b2b0c9c1..b9a3f8336 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -371,7 +371,7 @@ class VisualServerRaster : public VisualServer {
-
+ mutable RID_Owner canvas_item_material_owner;
struct CanvasItem : public Rasterizer::CanvasItem {
@@ -384,7 +384,7 @@ class VisualServerRaster : public VisualServer {
bool sort_y;
float opacity;
float self_opacity;
- bool use_parent_shader;
+ bool use_parent_material;
Vector child_items;
@@ -396,7 +396,7 @@ class VisualServerRaster : public VisualServer {
opacity=1;
self_opacity=1;
sort_y=false;
- use_parent_shader=false;
+ use_parent_material=false;
z_relative=true;
}
};
@@ -410,6 +410,24 @@ class VisualServerRaster : public VisualServer {
}
};
+ struct CanvasLightOccluder;
+
+ struct CanvasLightOccluderPolygon {
+
+ bool active;
+ Rect2 aabb;
+ CanvasOccluderPolygonCullMode cull_mode;
+ RID occluder;
+ Set owners;
+
+ CanvasLightOccluderPolygon() { active=false; cull_mode=CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
+ };
+
+
+ RID_Owner canvas_light_occluder_polygon_owner;
+
+ RID_Owner canvas_light_occluder_owner;
+
struct CanvasLight;
struct Canvas {
@@ -422,6 +440,7 @@ class VisualServerRaster : public VisualServer {
};
Set lights;
+ Set occluders;
Vector child_items;
Color modulate;
@@ -610,7 +629,7 @@ class VisualServerRaster : public VisualServer {
void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect);
void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights);
- void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner);
+ void _render_canvas_item(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner);
void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights);
Vector _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
Vector _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
@@ -1131,15 +1150,8 @@ public:
virtual void canvas_item_set_z(RID p_item, int p_z);
virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
- virtual void canvas_item_set_shader(RID p_item, RID p_shader);
- virtual RID canvas_item_get_shader(RID p_item) const;
-
- virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable);
-
-
-
- virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value);
- virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const;
+ virtual void canvas_item_set_material(RID p_item, RID p_material);
+ virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
virtual RID canvas_light_create();
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas);
@@ -1156,17 +1168,36 @@ public:
virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable);
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size);
- virtual void canvas_light_set_shadow_filter(RID p_light, int p_size);
+ virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier);
virtual RID canvas_light_occluder_create();
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas);
virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled);
- virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector& p_shape);
+ virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon);
+ virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform);
+ virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask);
+
+
+ virtual RID canvas_occluder_polygon_create();
+ virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector& p_shape,bool p_close);
+ virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector& p_shape);
+ virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode);
+
+
virtual void canvas_item_clear(RID p_item);
virtual void canvas_item_raise(RID p_item);
+ /* CANVAS ITEM MATERIAL */
+
+ virtual RID canvas_item_material_create();
+ virtual void canvas_item_material_set_shader(RID p_material, RID p_shader);
+ virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value);
+ virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const;
+ virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded);
+
+
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians
virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor=0);
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 6c95b6ed5..1890f7b76 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -1139,14 +1139,9 @@ public:
FUNC2(canvas_item_set_z,RID,int);
FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool);
- FUNC2(canvas_item_set_shader,RID, RID );
- FUNC1RC(RID,canvas_item_get_shader,RID );
+ FUNC2(canvas_item_set_material,RID, RID );
- FUNC2(canvas_item_set_use_parent_shader,RID, bool );
-
-
- FUNC3(canvas_item_set_shader_param,RID,const StringName&,const Variant&);
- FUNC2RC(Variant,canvas_item_get_shader_param,RID,const StringName&);
+ FUNC2(canvas_item_set_use_parent_material,RID, bool );
FUNC1(canvas_item_clear,RID);
FUNC1(canvas_item_raise,RID);
@@ -1167,14 +1162,31 @@ public:
FUNC2(canvas_light_set_subtract_mode,RID,bool);
FUNC2(canvas_light_set_shadow_enabled,RID,bool);
FUNC2(canvas_light_set_shadow_buffer_size,RID,int);
- FUNC2(canvas_light_set_shadow_filter,RID,int);
+ FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float);
+
/* CANVAS OCCLUDER */
FUNC0R(RID,canvas_light_occluder_create);
FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID);
FUNC2(canvas_light_occluder_set_enabled,RID,bool);
- FUNC2(canvas_light_occluder_set_shape,RID,const DVector&);
+ FUNC2(canvas_light_occluder_set_polygon,RID,RID);
+ FUNC2(canvas_light_occluder_set_transform,RID,const Matrix32&);
+ FUNC2(canvas_light_occluder_set_light_mask,RID,int);
+
+
+ FUNC0R(RID,canvas_occluder_polygon_create);
+ FUNC3(canvas_occluder_polygon_set_shape,RID,const DVector&,bool);
+ FUNC2(canvas_occluder_polygon_set_shape_as_lines,RID,const DVector&);
+ FUNC2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode);
+
+ /* CANVAS MATERIAL */
+
+ FUNC0R(RID,canvas_item_material_create);
+ FUNC2(canvas_item_material_set_shader,RID,RID);
+ FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&);
+ FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&);
+ FUNC2(canvas_item_material_set_unshaded,RID,bool);
/* CURSOR */
FUNC2(cursor_set_rotation,float , int ); // radians
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 37368e32f..ccf6978ae 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -998,13 +998,9 @@ public:
virtual void canvas_item_clear(RID p_item)=0;
virtual void canvas_item_raise(RID p_item)=0;
- virtual void canvas_item_set_shader(RID p_item, RID p_shader)=0;
- virtual RID canvas_item_get_shader(RID p_item) const=0;
+ virtual void canvas_item_set_material(RID p_item, RID p_material)=0;
- virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable)=0;
-
- virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value)=0;
- virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const=0;
+ virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable)=0;
virtual RID canvas_light_create()=0;
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas)=0;
@@ -1021,13 +1017,34 @@ public:
virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable)=0;
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0;
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0;
- virtual void canvas_light_set_shadow_filter(RID p_light, int p_size)=0;
+ virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0;
+
virtual RID canvas_light_occluder_create()=0;
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas)=0;
virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled)=0;
- virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector& p_shape)=0;
+ virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon)=0;
+ virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform)=0;
+ virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask)=0;
+
+ virtual RID canvas_occluder_polygon_create()=0;
+ virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector& p_shape,bool p_closed)=0;
+ virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector& p_shape)=0;
+ enum CanvasOccluderPolygonCullMode {
+ CANVAS_OCCLUDER_POLYGON_CULL_DISABLED,
+ CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE,
+ CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE,
+ };
+ virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode)=0;
+
+ /* CANVAS ITEM MATERIAL */
+
+ virtual RID canvas_item_material_create()=0;
+ virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0;
+ virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0;
+ virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0;
+ virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded)=0;
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index cc1a05f7d..3d42867d9 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -90,6 +90,7 @@
#include "plugins/baked_light_editor_plugin.h"
#include "plugins/polygon_2d_editor_plugin.h"
#include "plugins/navigation_polygon_editor_plugin.h"
+#include "plugins/light_occluder_2d_editor_plugin.h"
// end
#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
#include "tools/editor/io_plugins/editor_scene_import_plugin.h"
@@ -4115,6 +4116,7 @@ EditorNode::EditorNode() {
add_editor_plugin( memnew( PathEditorPlugin(this) ) );
add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) );
add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) );
+ add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) );
add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) );
for(int i=0;iset_icon( get_icon("Edit","EditorIcons"));
+ button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
+ button_edit->set_pressed(true);
+ get_tree()->connect("node_removed",this,"_node_removed");
+ create_poly->connect("confirmed",this,"_create_poly");
+
+ } break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+
+ } break;
+ }
+
+}
+void LightOccluder2DEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ canvas_item_editor->get_viewport_control()->update();
+ }
+
+}
+
+
+Vector2 LightOccluder2DEditor::snap_point(const Vector2& p_point) const {
+
+ if (canvas_item_editor->is_snap_active()) {
+
+ return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
+
+ } else {
+ return p_point;
+ }
+}
+
+void LightOccluder2DEditor::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case MODE_CREATE: {
+
+ mode=MODE_CREATE;
+ button_create->set_pressed(true);
+ button_edit->set_pressed(false);
+ } break;
+ case MODE_EDIT: {
+
+ mode=MODE_EDIT;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(true);
+ } break;
+
+ }
+}
+
+void LightOccluder2DEditor::_wip_close(bool p_closed) {
+
+ undo_redo->create_action("Create Poly");
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",node->get_occluder_polygon()->get_polygon());
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",wip);
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_closed",node->get_occluder_polygon()->is_closed());
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_closed",p_closed);
+
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ wip.clear();
+ wip_active=false;
+ mode=MODE_EDIT;
+ button_edit->set_pressed(true);
+ button_create->set_pressed(false);
+ edited_point=-1;
+}
+
+bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) {
+
+
+ if (!node)
+ return false;
+
+ if (node->get_occluder_polygon().is_null()) {
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
+ create_poly->set_text("No OccluderPolygon2D resource on this node.\nCreate and assign one?");
+ create_poly->popup_centered_minsize();
+ }
+ return false;
+ }
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+
+ Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+
+
+ Vector2 gpoint = Point2(mb.x,mb.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=snap_point(cpoint);
+ cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ Vector poly = Variant(node->get_occluder_polygon()->get_polygon());
+
+ //first check if a point is to be added (segment split)
+ real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8);
+
+ switch(mode) {
+
+
+ case MODE_CREATE: {
+
+ if (mb.button_index==BUTTON_LEFT && mb.pressed) {
+
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back( cpoint );
+ wip_active=true;
+ edited_point_pos=cpoint;
+ canvas_item_editor->get_viewport_control()->update();
+ edited_point=1;
+ return true;
+ } else {
+
+
+ if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)1 && xform.xform(wip[wip.size()-1]).distance_to(gpoint)get_viewport_control()->update();
+ return true;
+
+ //add wip point
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
+ _wip_close(true);
+ }
+
+
+
+ } break;
+
+ case MODE_EDIT: {
+
+ if (mb.button_index==BUTTON_LEFT) {
+ if (mb.pressed) {
+
+ if (mb.mod.control) {
+
+
+ if (poly.size() < 3) {
+
+ undo_redo->create_action("Edit Poly");
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ poly.push_back(cpoint);
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ //search edges
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i=0) {
+
+ pre_move_edit=poly;
+ poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
+ edited_point=closest_idx+1;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ node->get_occluder_polygon()->set_polygon(Variant(poly));
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ } else {
+
+ //look for points to move
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i=0) {
+
+ pre_move_edit=poly;
+ edited_point=closest_idx;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ }
+ } else {
+
+ if (edited_point!=-1) {
+
+ //apply
+
+ ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
+ poly[edited_point]=edited_point_pos;
+ undo_redo->create_action("Edit Poly");
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",pre_move_edit);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ edited_point=-1;
+ return true;
+ }
+ }
+ } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+
+
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i=0) {
+
+
+ undo_redo->create_action("Edit Poly (Remove Point)");
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ poly.remove(closest_idx);
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ }
+
+
+
+ } break;
+ }
+
+
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mm=p_event.mouse_motion;
+
+ if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+
+ Vector2 gpoint = Point2(mm.x,mm.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=snap_point(cpoint);
+ edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ }
+
+ } break;
+ }
+
+ return false;
+}
+void LightOccluder2DEditor::_canvas_draw() {
+
+ if (!node || !node->get_occluder_polygon().is_valid())
+ return;
+
+ Control *vpc = canvas_item_editor->get_viewport_control();
+
+ Vector poly;
+
+ if (wip_active)
+ poly=wip;
+ else
+ poly=Variant(node->get_occluder_polygon()->get_polygon());
+
+
+ Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Ref handle= get_icon("EditorHandle","EditorIcons");
+
+ int len = poly.size();
+
+ for(int i=0;iget_occluder_polygon()->is_closed() || wip_active)) {
+
+ } else {
+ vpc->draw_line(point,next_point,col,2);
+ }
+ vpc->draw_texture(handle,point-handle->get_size()*0.5);
+ }
+}
+
+
+
+void LightOccluder2DEditor::edit(Node *p_collision_polygon) {
+
+ if (!canvas_item_editor) {
+ canvas_item_editor=CanvasItemEditor::get_singleton();
+ }
+
+ if (p_collision_polygon) {
+
+ node=p_collision_polygon->cast_to();
+ if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
+ wip.clear();
+ wip_active=false;
+ edited_point=-1;
+
+ } else {
+ node=NULL;
+
+ if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
+
+ }
+
+}
+
+void LightOccluder2DEditor::_create_poly() {
+
+ undo_redo->create_action("Create Occluder Polygon");
+ undo_redo->add_do_method(node,"set_occluder_polygon",Ref(memnew( OccluderPolygon2D)));
+ undo_redo->add_undo_method(node,"set_occluder_polygon",Variant(REF()));
+ undo_redo->commit_action();
+}
+
+void LightOccluder2DEditor::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("_menu_option"),&LightOccluder2DEditor::_menu_option);
+ ObjectTypeDB::bind_method(_MD("_canvas_draw"),&LightOccluder2DEditor::_canvas_draw);
+ ObjectTypeDB::bind_method(_MD("_node_removed"),&LightOccluder2DEditor::_node_removed);
+ ObjectTypeDB::bind_method(_MD("_create_poly"),&LightOccluder2DEditor::_create_poly);
+
+}
+
+
+LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) {
+
+ canvas_item_editor=NULL;
+ editor=p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ add_child( memnew( VSeparator ));
+ button_create = memnew( ToolButton );
+ add_child(button_create);
+ button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
+ button_create->set_toggle_mode(true);
+ button_create->set_tooltip("Create a new polygon from scratch");
+
+ button_edit = memnew( ToolButton );
+ add_child(button_edit);
+ button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
+ button_edit->set_toggle_mode(true);
+ button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.");
+
+ create_poly = memnew( ConfirmationDialog );
+ add_child(create_poly);
+ create_poly->get_ok()->set_text("Create");
+
+
+ //add_constant_override("separation",0);
+
+#if 0
+ options = memnew( MenuButton );
+ add_child(options);
+ options->set_area_as_parent_rect();
+ options->set_text("Polygon");
+ //options->get_popup()->add_item("Parse BBCODE",PARSE_BBCODE);
+ options->get_popup()->connect("item_pressed", this,"_menu_option");
+#endif
+
+ mode = MODE_EDIT;
+ wip_active=false;
+
+}
+
+
+void LightOccluder2DEditorPlugin::edit(Object *p_object) {
+
+ collision_polygon_editor->edit(p_object->cast_to());
+}
+
+bool LightOccluder2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_type("LightOccluder2D");
+}
+
+void LightOccluder2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ collision_polygon_editor->show();
+ } else {
+
+ collision_polygon_editor->hide();
+ collision_polygon_editor->edit(NULL);
+ }
+
+}
+
+LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ collision_polygon_editor = memnew( LightOccluder2DEditor(p_node) );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+
+ collision_polygon_editor->hide();
+
+
+
+}
+
+
+LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin()
+{
+}
+
diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.h b/tools/editor/plugins/light_occluder_2d_editor_plugin.h
new file mode 100644
index 000000000..5fb5631d0
--- /dev/null
+++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.h
@@ -0,0 +1,87 @@
+#ifndef LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
+#define LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
+
+
+
+#include "tools/editor/editor_plugin.h"
+#include "tools/editor/editor_node.h"
+#include "scene/2d/light_occluder_2d.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+
+/**
+ @author Juan Linietsky
+*/
+class CanvasItemEditor;
+
+class LightOccluder2DEditor : public HBoxContainer {
+
+ OBJ_TYPE(LightOccluder2DEditor, HBoxContainer );
+
+ UndoRedo *undo_redo;
+ enum Mode {
+
+ MODE_CREATE,
+ MODE_EDIT,
+
+ };
+
+ Mode mode;
+
+ ToolButton *button_create;
+ ToolButton *button_edit;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ LightOccluder2D *node;
+ MenuButton *options;
+
+ int edited_point;
+ Vector2 edited_point_pos;
+ Vector pre_move_edit;
+ Vector wip;
+ bool wip_active;
+
+ ConfirmationDialog *create_poly;
+
+ void _wip_close(bool p_closed);
+ void _canvas_draw();
+ void _menu_option(int p_option);
+ void _create_poly();
+
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ Vector2 snap_point(const Vector2& p_point) const;
+ bool forward_input_event(const InputEvent& p_event);
+ void edit(Node *p_collision_polygon);
+ LightOccluder2DEditor(EditorNode *p_editor);
+};
+
+class LightOccluder2DEditorPlugin : public EditorPlugin {
+
+ OBJ_TYPE( LightOccluder2DEditorPlugin, EditorPlugin );
+
+ LightOccluder2DEditor *collision_polygon_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); }
+
+ virtual String get_name() const { return "LightOccluder2D"; }
+ 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);
+
+ LightOccluder2DEditorPlugin(EditorNode *p_node);
+ ~LightOccluder2DEditorPlugin();
+
+};
+
+#endif // LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index a60068309..25c39b317 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -1857,8 +1857,33 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p
} else {
p_item->set_text(1,"<"+res->get_type()+">");
};
+
+ if (has_icon(res->get_type(),"EditorIcons")) {
+
+ p_item->set_icon(1,get_icon(res->get_type(),"EditorIcons"));
+ } else {
+
+ Dictionary d = p_item->get_metadata(0);
+ int hint=d.has("hint")?d["hint"].operator int():-1;
+ String hint_text=d.has("hint_text")?d["hint_text"]:"";
+ if (hint==PROPERTY_HINT_RESOURCE_TYPE) {
+
+ if (has_icon(hint_text,"EditorIcons")) {
+
+ p_item->set_icon(1,get_icon(hint_text,"EditorIcons"));
+
+ } else {
+ p_item->set_icon(1,get_icon("Object","EditorIcons"));
+
+ }
+ }
+ }
+
+
+
}
+
} break;
default: {};
}
@@ -2529,7 +2554,10 @@ void PropertyEditor::update_tree() {
item->set_editable( 1, !read_only );
item->add_button(1,get_icon("EditResource","EditorIcons"));
String type;
+ if (p.hint==PROPERTY_HINT_RESOURCE_TYPE)
+ type=p.hint_string;
bool notnil=false;
+
if (obj->get( p.name ).get_type() == Variant::NIL || obj->get( p.name ).operator RefPtr().is_null()) {
item->set_text(1,"");
@@ -2553,12 +2581,18 @@ void PropertyEditor::update_tree() {
};
notnil=true;
+ if (has_icon(res->get_type(),"EditorIcons")) {
+ type=res->get_type();
+ }
}
- if (p.hint==PROPERTY_HINT_RESOURCE_TYPE) {
+
+ if (type!=String()) {
+ if (type.find(",")!=-1)
+ type=type.get_slice(",",0);
//printf("prop %s , type %s\n",p.name.ascii().get_data(),p.hint_string.ascii().get_data());
- if (has_icon(p.hint_string,"EditorIcons"))
- item->set_icon( 0, get_icon(p.hint_string,"EditorIcons") );
+ if (has_icon(type,"EditorIcons"))
+ item->set_icon( 0, get_icon(type,"EditorIcons") );
else
item->set_icon( 0, get_icon("Object","EditorIcons") );
}
--
cgit v1.2.3-70-g09d2
From 4d2198110b4af7f203eeef95697255569e49bce7 Mon Sep 17 00:00:00 2001
From: Juan Linietsky
Date: Tue, 3 Mar 2015 14:39:13 -0300
Subject: merges from okam repo
---
SConstruct | 4 +
core/object.cpp | 8 +
core/object.h | 1 +
doc/base/classes.xml | 3 +-
drivers/gles2/rasterizer_gles2.cpp | 24 ++-
methods.py | 8 +
modules/gdscript/gd_tokenizer.cpp | 4 +-
modules/gridmap/grid_map.cpp | 3 +-
platform/android/AndroidManifest.xml.template | 3 +-
platform/android/SCsub | 2 +
platform/android/java_glue.cpp | 113 ++++++++++---
platform/bb10/SCsub | 10 +-
platform/bb10/bar/bar-descriptor.xml | 30 ++--
platform/bb10/detect.py | 2 -
platform/bb10/export/export.cpp | 79 ++++-----
platform/bb10/os_bb10.cpp | 2 +-
platform/iphone/gl_view.h | 2 +
platform/iphone/gl_view.mm | 52 ++++++
scene/2d/camera_2d.cpp | 11 ++
scene/2d/camera_2d.h | 189 +++++++++++-----------
scene/resources/shader_graph.h | 2 +
servers/visual/shader_language.cpp | 4 +-
tools/collada/collada.cpp | 2 +-
tools/collada/collada.h | 18 +++
tools/editor/editor_import_export.cpp | 30 +++-
tools/editor/editor_import_export.h | 3 +-
tools/editor/io_plugins/editor_import_collada.cpp | 11 +-
tools/export/blender25/io_scene_dae/export_dae.py | 71 ++++++--
28 files changed, 458 insertions(+), 233 deletions(-)
(limited to 'modules')
diff --git a/SConstruct b/SConstruct
index c68ca3989..2dc9fa1e7 100644
--- a/SConstruct
+++ b/SConstruct
@@ -67,12 +67,16 @@ env_base.android_source_modules=[]
env_base.android_source_files=[]
env_base.android_module_libraries=[]
env_base.android_manifest_chunk=""
+env_base.android_permission_chunk=""
+env_base.android_appattributes_chunk=""
env_base.disabled_modules=[]
env_base.__class__.android_module_source = methods.android_module_source
env_base.__class__.android_module_library = methods.android_module_library
env_base.__class__.android_module_file = methods.android_module_file
env_base.__class__.android_module_manifest = methods.android_module_manifest
+env_base.__class__.android_module_permission = methods.android_module_permission
+env_base.__class__.android_module_attribute = methods.android_module_attribute
env_base.__class__.disable_module = methods.disable_module
env_base.__class__.add_source_files = methods.add_source_files
diff --git a/core/object.cpp b/core/object.cpp
index 82144ab4b..2b83f728d 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1033,6 +1033,13 @@ void Object::add_user_signal(const MethodInfo& p_signal) {
signal_map[p_signal.name]=s;
}
+bool Object::_has_user_signal(const StringName& p_name) const {
+
+ if (!signal_map.has(p_name))
+ return false;
+ return signal_map[p_name].user.name.length()>0;
+}
+
struct _ObjectSignalDisconnectData {
StringName signal;
@@ -1431,6 +1438,7 @@ void Object::_bind_methods() {
// ObjectTypeDB::bind_method(_MD("call_deferred","method","arg1","arg2","arg3","arg4"),&Object::_call_deferred_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()));
ObjectTypeDB::bind_method(_MD("add_user_signal","signal","arguments"),&Object::_add_user_signal,DEFVAL(Array()));
+ ObjectTypeDB::bind_method(_MD("has_user_signal","signal"),&Object::_has_user_signal);
// ObjectTypeDB::bind_method(_MD("emit_signal","signal","arguments"),&Object::_emit_signal,DEFVAL(Array()));
diff --git a/core/object.h b/core/object.h
index 97ca50cb1..eb885f5d2 100644
--- a/core/object.h
+++ b/core/object.h
@@ -386,6 +386,7 @@ friend void postinitialize_handler(Object*);
Dictionary metadata;
void _add_user_signal(const String& p_name, const Array& p_pargs=Array());
+ bool _has_user_signal(const StringName& p_name) const;
Variant _emit_signal(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
Array _get_signal_list() const;
Array _get_signal_connection_list(const String& p_signal) const;
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 35de0106b..e5bdcfbc6 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -18902,7 +18902,8 @@
collider_id: collider id of the object agaisnt which the ray was stopped[br]
collider: collider object agaisnt which the ray was stopped[br]
rid: [RID] of the object agaisnt which the ray was stopped[br]
- If the ray did not intersect anything, then null is returned instead of a [Dictionary].
+ If the ray did not intersect anything, then an empty
+ dictionary (dir.empty()==true) is returned instead.
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 9375532f0..9cee702c0 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -4954,12 +4954,26 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_
Material::UniformData ud;
bool keep=true; //keep material value
- bool has_old = old_mparams.has(E->key());
+
+ Map::Element *OLD=old_mparams.find(E->key());
+ bool has_old = OLD;
bool old_inuse=has_old && old_mparams[E->key()].inuse;
- if (!has_old || !old_inuse)
+ ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP);
+
+ if (!has_old || !old_inuse) {
keep=false;
- else if (old_mparams[E->key()].value.get_type()!=E->value().default_value.get_type()) {
+ }
+ else if (OLD->get().value.get_type()!=E->value().default_value.get_type()) {
+
+ if (OLD->get().value.get_type()==Variant::INT && E->get().type==ShaderLanguage::TYPE_FLOAT) {
+ //handle common mistake using shaders (feeding ints instead of float)
+ OLD->get().value=float(OLD->get().value);
+ keep=true;
+ } else if (!ud.istexture && E->value().default_value.get_type()!=Variant::NIL) {
+
+ keep=false;
+ }
//type changed between old and new
/* if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) {
if (E->value().default_value.get_type()!=Variant::_RID) //hackfor textures
@@ -4968,11 +4982,9 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_
keep=false;*/
//value is invalid because type differs and default is not null
- if (E->value().default_value.get_type()!=Variant::NIL)
- keep=false;
+ ;
}
- ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP);
if (keep) {
ud.value=old_mparams[E->key()].value;
diff --git a/methods.py b/methods.py
index da1491e3f..9608b1b61 100755
--- a/methods.py
+++ b/methods.py
@@ -1291,6 +1291,14 @@ def android_module_manifest(self,file):
base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
f = open(base_path,"rb")
self.android_manifest_chunk+=f.read()
+def android_module_permission(self,file):
+ base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
+ f = open(base_path,"rb")
+ self.android_permission_chunk+=f.read()
+def android_module_attribute(self,file):
+ base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
+ f = open(base_path,"rb")
+ self.android_appattributes_chunk+=f.read()
def disable_module(self):
self.disabled_modules.append(self.current_module)
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp
index 6f968f208..71dbf81fb 100644
--- a/modules/gdscript/gd_tokenizer.cpp
+++ b/modules/gdscript/gd_tokenizer.cpp
@@ -538,9 +538,11 @@ void GDTokenizerText::_advance() {
is_node_path=true;
case '\'':
- string_mode=STRING_SINGLE_QUOTE;
case '"': {
+ if (GETCHAR(0)=='\'')
+ string_mode=STRING_SINGLE_QUOTE;
+
int i=1;
if (string_mode==STRING_DOUBLE_QUOTE && GETCHAR(i)=='"' && GETCHAR(i+1)=='"') {
i+=2;
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 7c344e1e9..441b274e3 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -122,7 +122,7 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
Octant &g = *octant_map[ok];
g.baked=b;
- g.bake_instance=VS::get_singleton()->instance_create();;
+ g.bake_instance=VS::get_singleton()->instance_create();;
VS::get_singleton()->instance_set_base(g.bake_instance,g.baked->get_rid());
VS::get_singleton()->instance_geometry_set_baked_light(g.bake_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID());
}
@@ -418,6 +418,7 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){
Octant *g = memnew( Octant );
g->dirty=true;
g->static_body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC);
+ PhysicsServer::get_singleton()->body_attach_object_instance_ID(g->static_body,get_instance_ID());
if (is_inside_world())
PhysicsServer::get_singleton()->body_set_space(g->static_body,get_world()->get_space());
diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template
index 60861db60..d31bdbfa5 100644
--- a/platform/android/AndroidManifest.xml.template
+++ b/platform/android/AndroidManifest.xml.template
@@ -10,7 +10,7 @@
android:largeScreens="true"
android:xlargeScreens="true"/>
-
+
+$$ADD_PERMISSION_CHUNKS$$
diff --git a/platform/android/SCsub b/platform/android/SCsub
index cffec5ae9..6feeb8b36 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -56,6 +56,8 @@ pp_basein = open(abspath+"/AndroidManifest.xml.template","rb")
pp_baseout = open(abspath+"/java/AndroidManifest.xml","wb")
manifest = pp_basein.read()
manifest = manifest.replace("$$ADD_APPLICATION_CHUNKS$$",env.android_manifest_chunk)
+manifest = manifest.replace("$$ADD_PERMISSION_CHUNKS$$",env.android_permission_chunk)
+manifest = manifest.replace("$$ADD_APPATTRIBUTE_CHUNKS$$",env.android_appattributes_chunk)
pp_baseout.write( manifest )
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 0312d1364..349db08e3 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -45,9 +45,18 @@ static JavaClassWrapper *java_class_wrapper=NULL;
static OS_Android *os_android=NULL;
-jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_arg, bool force_jobject = false) {
+struct jvalret {
- jvalue v;
+ jobject obj;
+ jvalue val;
+ jvalret() { obj=NULL; }
+
+
+};
+
+jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_arg, bool force_jobject = false) {
+
+ jvalret v;
switch(p_type) {
@@ -59,9 +68,12 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jvalue val;
val.z = (bool)(*p_arg);
jobject obj = env->NewObjectA(bclass, ctor, &val);
- v.l = obj;
+ v.val.l = obj;
+ v.obj=obj;
+ env->DeleteLocalRef(bclass);
} else {
- v.z=*p_arg;
+ v.val.z=*p_arg;
+
};
} break;
case Variant::INT: {
@@ -73,10 +85,13 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jvalue val;
val.i = (int)(*p_arg);
jobject obj = env->NewObjectA(bclass, ctor, &val);
- v.l = obj;
+ v.val.l = obj;
+ v.obj=obj;
+ env->DeleteLocalRef(bclass);
} else {
- v.i=*p_arg;
+ v.val.i=*p_arg;
+
};
} break;
case Variant::REAL: {
@@ -88,17 +103,20 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jvalue val;
val.d = (double)(*p_arg);
jobject obj = env->NewObjectA(bclass, ctor, &val);
- v.l = obj;
+ v.val.l = obj;
+ v.obj=obj;
+ env->DeleteLocalRef(bclass);
} else {
- v.f=*p_arg;
+ v.val.f=*p_arg;
};
} break;
case Variant::STRING: {
String s = *p_arg;
jstring jStr = env->NewStringUTF(s.utf8().get_data());
- v.l=jStr;
+ v.val.l=jStr;
+ v.obj=jStr;
} break;
case Variant::STRING_ARRAY: {
@@ -107,9 +125,12 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
for(int j=0;jSetObjectArrayElement(arr,j,env->NewStringUTF( sarray[j].utf8().get_data() ));
+ jstring str = env->NewStringUTF( sarray[j].utf8().get_data() );
+ env->SetObjectArrayElement(arr,j,str);
+ env->DeleteLocalRef(str);
}
- v.l=arr;
+ v.val.l=arr;
+ v.obj=arr;
} break;
@@ -124,27 +145,36 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jobjectArray jkeys = env->NewObjectArray(keys.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
for (int j=0; jSetObjectArrayElement(jkeys, j, env->NewStringUTF(String(keys[j]).utf8().get_data()));
+ jstring str = env->NewStringUTF(String(keys[j]).utf8().get_data());
+ env->SetObjectArrayElement(jkeys, j, str);
+ env->DeleteLocalRef(str);
};
jmethodID set_keys = env->GetMethodID(dclass, "set_keys", "([Ljava/lang/String;)V");
jvalue val;
val.l = jkeys;
env->CallVoidMethodA(jdict, set_keys, &val);
+ env->DeleteLocalRef(jkeys);
jobjectArray jvalues = env->NewObjectArray(keys.size(), env->FindClass("java/lang/Object"), NULL);
for (int j=0; jSetObjectArrayElement(jvalues, j, val.l);
+ jvalret v = _variant_to_jvalue(env, var.get_type(), &var, true);
+ env->SetObjectArrayElement(jvalues, j, v.val.l);
+ if (v.obj) {
+ env->DeleteLocalRef(v.obj);
+ }
};
jmethodID set_values = env->GetMethodID(dclass, "set_values", "([Ljava/lang/Object;)V");
val.l = jvalues;
env->CallVoidMethodA(jdict, set_values, &val);
+ env->DeleteLocalRef(jvalues);
+ env->DeleteLocalRef(dclass);
- v.l = jdict;
+ v.val.l = jdict;
+ v.obj=jdict;
} break;
case Variant::INT_ARRAY: {
@@ -153,7 +183,8 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jintArray arr = env->NewIntArray(array.size());
DVector::Read r = array.read();
env->SetIntArrayRegion(arr,0,array.size(),r.ptr());
- v.l=arr;
+ v.val.l=arr;
+ v.obj=arr;
} break;
case Variant::RAW_ARRAY: {
@@ -161,7 +192,8 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jbyteArray arr = env->NewByteArray(array.size());
DVector::Read r = array.read();
env->SetByteArrayRegion(arr,0,array.size(),reinterpret_cast(r.ptr()));
- v.l=arr;
+ v.val.l=arr;
+ v.obj=arr;
} break;
case Variant::REAL_ARRAY: {
@@ -170,12 +202,13 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jfloatArray arr = env->NewFloatArray(array.size());
DVector::Read r = array.read();
env->SetFloatArrayRegion(arr,0,array.size(),r.ptr());
- v.l=arr;
+ v.val.l=arr;
+ v.obj=arr;
} break;
default: {
- v.i = 0;
+ v.val.i = 0;
} break;
}
@@ -193,8 +226,11 @@ String _get_class_name(JNIEnv * env, jclass cls, bool* array) {
jboolean isarr = env->CallBooleanMethod(cls, isArray);
(*array) = isarr ? true : false;
}
+ String name = env->GetStringUTFChars( clsName, NULL );
+ env->DeleteLocalRef(clsName);
+
+ return name;
- return env->GetStringUTFChars( clsName, NULL );
};
@@ -223,6 +259,8 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
jstring string = (jstring) env->GetObjectArrayElement(arr, i);
const char *rawString = env->GetStringUTFChars(string, 0);
sarr.push_back(String(rawString));
+ env->DeleteLocalRef(string);
+
}
return sarr;
@@ -321,30 +359,34 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
jobjectArray arr = (jobjectArray)obj;
int objCount = env->GetArrayLength(arr);
- Array varr;
+ Array varr(true);
for (int i=0; iGetObjectArrayElement(arr, i);
Variant v = _jobject_to_variant(env, jobj);
varr.push_back(v);
+ env->DeleteLocalRef(jobj);
+
}
return varr;
};
- if (name == "com.android.godot.Dictionary") {
+ if (name == "java.util.HashMap" || name == "com.android.godot.Dictionary") {
- Dictionary ret;
+ Dictionary ret(true);
jclass oclass = c;
jmethodID get_keys = env->GetMethodID(oclass, "get_keys", "()[Ljava/lang/String;");
jobjectArray arr = (jobjectArray)env->CallObjectMethod(obj, get_keys);
StringArray keys = _jobject_to_variant(env, arr);
+ env->DeleteLocalRef(arr);
jmethodID get_values = env->GetMethodID(oclass, "get_values", "()[Ljava/lang/Object;");
arr = (jobjectArray)env->CallObjectMethod(obj, get_values);
Array vals = _jobject_to_variant(env, arr);
+ env->DeleteLocalRef(arr);
//print_line("adding " + String::num(keys.size()) + " to Dictionary!");
for (int i=0; iDeleteLocalRef(c);
+
return Variant();
};
@@ -432,9 +477,13 @@ public:
JNIEnv *env = ThreadAndroid::get_env();
//print_line("argcount "+String::num(p_argcount));
+ List to_erase;
for(int i=0;iget().argtypes[i], p_args[i]);
+ jvalret vr = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]);
+ v[i] = vr.val;
+ if (vr.obj)
+ to_erase.push_back(vr.obj);
}
//print_line("calling method!!");
@@ -468,6 +517,7 @@ public:
jobject o = env->CallObjectMethodA(instance,E->get().method,v);
String str = env->GetStringUTFChars((jstring)o, NULL );
ret=str;
+ env->DeleteLocalRef(o);
} break;
case Variant::STRING_ARRAY: {
@@ -475,6 +525,7 @@ public:
ret = _jobject_to_variant(env, arr);
+ env->DeleteLocalRef(arr);
} break;
case Variant::INT_ARRAY: {
@@ -488,6 +539,7 @@ public:
env->GetIntArrayRegion(arr,0,fCount,w.ptr());
w = DVector::Write();
ret=sarr;
+ env->DeleteLocalRef(arr);
} break;
case Variant::REAL_ARRAY: {
@@ -501,6 +553,7 @@ public:
env->GetFloatArrayRegion(arr,0,fCount,w.ptr());
w = DVector::Write();
ret=sarr;
+ env->DeleteLocalRef(arr);
} break;
case Variant::DICTIONARY: {
@@ -508,6 +561,7 @@ public:
//print_line("call dictionary");
jobject obj = env->CallObjectMethodA(instance, E->get().method, v);
ret = _jobject_to_variant(env, obj);
+ env->DeleteLocalRef(obj);
} break;
default: {
@@ -518,6 +572,10 @@ public:
} break;
}
+ while (to_erase.size()) {
+ env->DeleteLocalRef(to_erase.front()->get());
+ to_erase.pop_front();
+ }
//print_line("success");
return ret;
@@ -872,6 +930,7 @@ static void _initialize_java_modules() {
String modules = Globals::get_singleton()->get("android/modules");
Vector mods = modules.split(",",false);
+ print_line("ANDROID MODULES : " + modules);
__android_log_print(ANDROID_LOG_INFO,"godot","mod count: %i",mods.size());
if (mods.size()) {
@@ -1571,6 +1630,8 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env,
memnew_placement(&vlist[i], Variant);
vlist[i] = v;
vptr[i] = &vlist[i];
+ env->DeleteLocalRef(obj);
+
};
Variant::CallError err;
@@ -1588,13 +1649,15 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_calldeferred(JNIEnv * env
int count = env->GetArrayLength(params);
Variant args[VARIANT_ARG_MAX];
-// print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
+ //print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
for (int i=0; iGetObjectArrayElement(params, i);
if (obj)
args[i] = _jobject_to_variant(env, obj);
+ env->DeleteLocalRef(obj);
+
// print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type()));
};
diff --git a/platform/bb10/SCsub b/platform/bb10/SCsub
index 2e8ef4700..24f2b5d24 100644
--- a/platform/bb10/SCsub
+++ b/platform/bb10/SCsub
@@ -18,13 +18,5 @@ if env['bb10_lgles_override'] == "yes":
prog = None
-if env["target"]=="release":
- prog = env_bps.Program('#platform/bb10/godot_bb10_opt', bb10_lib)
-else:
- prog = env_bps.Program('#platform/bb10/godot_bb10', bb10_lib)
-
-import os
-fname = os.path.basename(str(prog[0]))
-
-env.Command('#bin/'+fname, prog, Copy('bin/'+fname, prog[0]))
+prog = env_bps.Program('#bin/godot', bb10_lib)
diff --git a/platform/bb10/bar/bar-descriptor.xml b/platform/bb10/bar/bar-descriptor.xml
index df5d34e07..0ba70b718 100644
--- a/platform/bb10/bar/bar-descriptor.xml
+++ b/platform/bb10/bar/bar-descriptor.xml
@@ -1,65 +1,53 @@
-
+
-
-
-
com.godot.game
-
Godot Game
-
0.0.1
-
0
-
Game made with Godot Engine
-
You Name or Company
authorIDherePlease
-
-
landscape
false
none
false
-
core.games
read_device_identifying_information
access_internet
- assets
+ data.pck
- armle-v7
- godot_bb10.qnx.armle
+ armle-v7
+ godot.bb10.debug.qnx.armle
- armle-v7
- godot_bb10_opt.qnx.armle
+ armle-v7
+ godot.bb10.opt.qnx.armle
- icon.png
+ icon.png
-
-
-
+
diff --git a/platform/bb10/detect.py b/platform/bb10/detect.py
index 3ddb7a445..f134a9df1 100644
--- a/platform/bb10/detect.py
+++ b/platform/bb10/detect.py
@@ -81,8 +81,6 @@ def configure(env):
if (env["target"]=="release"):
env.Append(CCFLAGS=['-O3','-DRELEASE_BUILD'])
- env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
elif (env["target"]=="debug"):
diff --git a/platform/bb10/export/export.cpp b/platform/bb10/export/export.cpp
index d40cb82cd..7862ecd49 100644
--- a/platform/bb10/export/export.cpp
+++ b/platform/bb10/export/export.cpp
@@ -321,12 +321,29 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
//BE SUPER CAREFUL WITH THIS PLEASE!!!
//BLACKBERRY THIS IS YOUR FAULT FOR NOT MAKING A BETTER WAY!!
- if (bar_dir.ends_with("bb10_export")) {
- Error err = da->erase_contents_recursive();
- if (err!=OK) {
+ bool berr = bar_dir.ends_with("bb10_export");
+ if (berr) {
+ if (da->list_dir_begin()) {
EditorNode::add_io_error("Can't ensure that dir is empty:\n"+bar_dir);
- ERR_FAIL_COND_V(err!=OK,err);
- }
+ ERR_FAIL_COND_V(berr,FAILED);
+ };
+
+ String f = da->get_next();
+ while (f != "") {
+
+ if (f == "." || f == "..") {
+ f = da->get_next();
+ continue;
+ };
+ Error err = da->remove(bar_dir + "/" + f);
+ if (err != OK) {
+ EditorNode::add_io_error("Can't ensure that dir is empty:\n"+bar_dir);
+ ERR_FAIL_COND_V(err!=OK,err);
+ };
+ f = da->get_next();
+ };
+
+ da->list_dir_end();
} else {
print_line("ARE YOU CRAZY??? THIS IS A SERIOUS BUG HERE!!!");
@@ -405,52 +422,23 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
ret = unzGoToNextFile(pkg);
}
- ep.step("Finding Files..",1);
-
- Vector files=get_dependencies(false);
-
ep.step("Adding Files..",2);
- da->change_dir(bar_dir);
- da->make_dir("assets");
- Error err = da->change_dir("assets");
- ERR_FAIL_COND_V(err,err);
-
- String asset_dir=da->get_current_dir();
- if (!asset_dir.ends_with("/"))
- asset_dir+="/";
-
- for(int i=0;i data = get_exported_file(fname);
- /*
- FileAccess *f=FileAccess::open(files[i],FileAccess::READ);
- if (!f) {
- EditorNode::add_io_error("Couldn't read: "+String(files[i]));
- }
- ERR_CONTINUE(!f);
- data.resize(f->get_len());
- f->get_buffer(data.ptr(),data.size());
-*/
- String dst_path=fname;
- dst_path=dst_path.replace_first("res://",asset_dir);
-
- da->make_dir_recursive(dst_path.get_base_dir());
-
- ep.step("Adding File: "+String(files[i]).get_file(),3+i*100/files.size());
-
- FileAccessRef fr = FileAccess::open(dst_path,FileAccess::WRITE);
- fr->store_buffer(data.ptr(),data.size());
+ FileAccess* dst = FileAccess::open(bar_dir+"/data.pck", FileAccess::WRITE);
+ if (!dst) {
+ EditorNode::add_io_error("Can't copy executable file to:\n "+p_path);
+ return ERR_FILE_CANT_WRITE;
}
-
+ save_pack(dst, false, 1024);
+ dst->close();
+ memdelete(dst);
ep.step("Creating BAR Package..",104);
String bb_packager=EditorSettings::get_singleton()->get("blackberry/host_tools");
bb_packager=bb_packager.plus_file("blackberry-nativepackager");
if (OS::get_singleton()->get_name()=="Windows")
- bb_packager+=".exe";
+ bb_packager+=".bat";
if (!FileAccess::exists(bb_packager)) {
@@ -482,7 +470,7 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
int ec;
- err = OS::get_singleton()->execute(bb_packager,args,true,NULL,NULL,&ec);
+ Error err = OS::get_singleton()->execute(bb_packager,args,true,NULL,NULL,&ec);
if (err!=OK)
return err;
@@ -493,7 +481,6 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
}
-
bool EditorExportPlatformBB10::poll_devices() {
bool dc=devices_changed;
@@ -537,7 +524,7 @@ void EditorExportPlatformBB10::_device_poll_thread(void *ud) {
bb_deploy=bb_deploy.plus_file("blackberry-deploy");
bool windows = OS::get_singleton()->get_name()=="Windows";
if (windows)
- bb_deploy+=".exe";
+ bb_deploy+=".bat";
if (!FileAccess::exists(bb_deploy)) {
OS::get_singleton()->delay_usec(3000000);
@@ -639,7 +626,7 @@ Error EditorExportPlatformBB10::run(int p_device, bool p_dumb) {
String bb_deploy=EditorSettings::get_singleton()->get("blackberry/host_tools");
bb_deploy=bb_deploy.plus_file("blackberry-deploy");
if (OS::get_singleton()->get_name()=="Windows")
- bb_deploy+=".exe";
+ bb_deploy+=".bat";
if (!FileAccess::exists(bb_deploy)) {
EditorNode::add_io_error("Blackberry Deploy not found:\n"+bb_deploy);
diff --git a/platform/bb10/os_bb10.cpp b/platform/bb10/os_bb10.cpp
index ff43a68b1..d89033b1d 100644
--- a/platform/bb10/os_bb10.cpp
+++ b/platform/bb10/os_bb10.cpp
@@ -619,7 +619,7 @@ OSBB10::OSBB10() {
printf("godot bb10!\n");
getcwd(launch_dir, sizeof(launch_dir));
printf("launch dir %s\n", launch_dir);
- chdir("app/native/assets");
+ chdir("app/native");
launch_dir_ptr = launch_dir;
}
diff --git a/platform/iphone/gl_view.h b/platform/iphone/gl_view.h
index 8ae7c2f87..8eb96e7e9 100755
--- a/platform/iphone/gl_view.h
+++ b/platform/iphone/gl_view.h
@@ -93,6 +93,8 @@
- (BOOL)createFramebuffer;
- (void)destroyFramebuffer;
+- (void)audioRouteChangeListenerCallback:(NSNotification*)notification;
+
@property NSTimeInterval animationInterval;
@end
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index bee01d3c7..7d33c1131 100755
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -119,6 +119,8 @@ bool _play_video(String p_path, float p_volume, String p_audio_track, String p_s
name:AVPlayerItemDidPlayToEndTimeNotification
object:[_instance.avPlayer currentItem]];
+ [_instance.avPlayer addObserver:_instance forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:0];
+
[_instance.avPlayerLayer setFrame:_instance.bounds];
[_instance.layer addSublayer:_instance.avPlayerLayer];
[_instance.avPlayer play];
@@ -578,6 +580,39 @@ static void clear_touches() {
printf("inserting text with character %i\n", character[0]);
};
+- (void)audioRouteChangeListenerCallback:(NSNotification*)notification
+{
+ printf("*********** route changed!%i\n");
+ NSDictionary *interuptionDict = notification.userInfo;
+
+ NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
+
+ switch (routeChangeReason) {
+
+ case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
+ NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable");
+ NSLog(@"Headphone/Line plugged in");
+ break;
+
+ case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
+ NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable");
+ NSLog(@"Headphone/Line was pulled. Resuming video play....");
+ if (_is_video_playing) {
+
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+ [_instance.avPlayer play]; // NOTE: change this line according your current player implementation
+ NSLog(@"resumed play");
+ });
+ };
+ break;
+
+ case AVAudioSessionRouteChangeReasonCategoryChange:
+ // called at start - also when other audio wants to play
+ NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange");
+ break;
+ }
+}
+
// When created via code however, we get initWithFrame
-(id)initWithFrame:(CGRect)frame
@@ -593,6 +628,11 @@ static void clear_touches() {
init_touches();
self. multipleTouchEnabled = YES;
+ printf("******** adding observer for sound routing changes\n");
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:)
+ name:AVAudioSessionRouteChangeNotification
+ object:nil];
+
//self.autoresizesSubviews = YES;
//[self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth];
@@ -642,6 +682,18 @@ static void clear_touches() {
video_current_time = kCMTimeZero;
}
}
+
+ if (object == _instance.avPlayer && [keyPath isEqualToString:@"rate"]) {
+ NSLog(@"Player playback rate changed: %.5f", _instance.avPlayer.rate);
+ if (_is_video_playing() && _instance.avPlayer.rate == 0.0 && !_instance.avPlayer.error) {
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+ [_instance.avPlayer play]; // NOTE: change this line according your current player implementation
+ NSLog(@"resumed play");
+ });
+
+ NSLog(@" . . . PAUSED (or just started)");
+ }
+ }
}
- (void)playerItemDidReachEnd:(NSNotification *)notification {
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index b3897010b..b2d74b4ad 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -323,6 +323,16 @@ void Camera2D::make_current() {
}
}
+void Camera2D::clear_current() {
+
+ current=false;
+ if (is_inside_tree()) {
+ get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,group_name,"_make_current",(Object*)(NULL));
+ }
+
+}
+
+
void Camera2D::set_limit(Margin p_margin,int p_limit) {
ERR_FAIL_INDEX(p_margin,4);
@@ -435,6 +445,7 @@ void Camera2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_rotating"),&Camera2D::is_rotating);
ObjectTypeDB::bind_method(_MD("make_current"),&Camera2D::make_current);
+ ObjectTypeDB::bind_method(_MD("clear_current"),&Camera2D::clear_current);
ObjectTypeDB::bind_method(_MD("_make_current"),&Camera2D::_make_current);
ObjectTypeDB::bind_method(_MD("_update_scroll"),&Camera2D::_update_scroll);
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 116169cac..515f9711b 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -26,97 +26,98 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CAMERA_2D_H
-#define CAMERA_2D_H
-
-#include "scene/2d/node_2d.h"
-#include "scene/main/viewport.h"
-
-
-class Camera2D : public Node2D {
-
- OBJ_TYPE( Camera2D, Node2D );
-
-protected:
- Point2 camera_pos;
- Point2 smoothed_camera_pos;
- bool first;
-
- Viewport *viewport;
-
- StringName group_name;
- StringName canvas_group_name;
- RID canvas;
- Vector2 offset;
- Vector2 zoom;
- bool centered;
- bool rotating;
- bool current;
- float smoothing;
- int limit[4];
- float drag_margin[4];
-
- bool h_drag_enabled;
- bool v_drag_enabled;
- float h_ofs;
- float v_ofs;
-
-
- Point2 camera_screen_center;
- void _update_scroll();
-
- void _make_current(Object *p_which);
- void _set_current(bool p_current);
-protected:
-
- virtual Matrix32 get_camera_transform();
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void set_offset(const Vector2& p_offset);
- Vector2 get_offset() const;
-
- void set_centered(bool p_centered);
- bool is_centered() const;
-
- void set_rotating(bool p_rotating);
- bool is_rotating() const;
-
- void set_limit(Margin p_margin,int p_limit);
- int get_limit(Margin p_margin) const;
-
-
- void set_h_drag_enabled(bool p_enabled);
- bool is_h_drag_enabled() const;
-
- void set_v_drag_enabled(bool p_enabled);
- bool is_v_drag_enabled() const;
-
- void set_drag_margin(Margin p_margin,float p_drag_margin);
- float get_drag_margin(Margin p_margin) const;
-
- void set_v_offset(float p_offset);
- float get_v_offset() const;
-
- void set_h_offset(float p_offset);
- float get_h_offset() const;
-
- void set_follow_smoothing(float p_speed);
- float get_follow_smoothing() const;
-
- void make_current();
- bool is_current() const;
-
- void set_zoom(const Vector2& p_zoom);
- Vector2 get_zoom() const;
-
- Point2 get_camera_screen_center() const;
-
- Vector2 get_camera_pos() const;
- void force_update_scroll();
-
- Camera2D();
-};
-
-#endif // CAMERA_2D_H
+#ifndef CAMERA_2D_H
+#define CAMERA_2D_H
+
+#include "scene/2d/node_2d.h"
+#include "scene/main/viewport.h"
+
+
+class Camera2D : public Node2D {
+
+ OBJ_TYPE( Camera2D, Node2D );
+
+protected:
+ Point2 camera_pos;
+ Point2 smoothed_camera_pos;
+ bool first;
+
+ Viewport *viewport;
+
+ StringName group_name;
+ StringName canvas_group_name;
+ RID canvas;
+ Vector2 offset;
+ Vector2 zoom;
+ bool centered;
+ bool rotating;
+ bool current;
+ float smoothing;
+ int limit[4];
+ float drag_margin[4];
+
+ bool h_drag_enabled;
+ bool v_drag_enabled;
+ float h_ofs;
+ float v_ofs;
+
+
+ Point2 camera_screen_center;
+ void _update_scroll();
+
+ void _make_current(Object *p_which);
+ void _set_current(bool p_current);
+protected:
+
+ virtual Matrix32 get_camera_transform();
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_offset(const Vector2& p_offset);
+ Vector2 get_offset() const;
+
+ void set_centered(bool p_centered);
+ bool is_centered() const;
+
+ void set_rotating(bool p_rotating);
+ bool is_rotating() const;
+
+ void set_limit(Margin p_margin,int p_limit);
+ int get_limit(Margin p_margin) const;
+
+
+ void set_h_drag_enabled(bool p_enabled);
+ bool is_h_drag_enabled() const;
+
+ void set_v_drag_enabled(bool p_enabled);
+ bool is_v_drag_enabled() const;
+
+ void set_drag_margin(Margin p_margin,float p_drag_margin);
+ float get_drag_margin(Margin p_margin) const;
+
+ void set_v_offset(float p_offset);
+ float get_v_offset() const;
+
+ void set_h_offset(float p_offset);
+ float get_h_offset() const;
+
+ void set_follow_smoothing(float p_speed);
+ float get_follow_smoothing() const;
+
+ void make_current();
+ void clear_current();
+ bool is_current() const;
+
+ void set_zoom(const Vector2& p_zoom);
+ Vector2 get_zoom() const;
+
+ Point2 get_camera_screen_center() const;
+
+ Vector2 get_camera_pos() const;
+ void force_update_scroll();
+
+ Camera2D();
+};
+
+#endif // CAMERA_2D_H
diff --git a/scene/resources/shader_graph.h b/scene/resources/shader_graph.h
index 55d09b4c3..c515f6e10 100644
--- a/scene/resources/shader_graph.h
+++ b/scene/resources/shader_graph.h
@@ -66,6 +66,8 @@ public:
NODE_VEC_TO_XFORM, // 3 vec input, 1 xform output
NODE_SCALAR_INTERP, // scalar interpolation (with optional curve)
NODE_VEC_INTERP, // vec3 interpolation (with optional curve)
+ /*NODE_SCALAR_CURVE_REMAP,
+ NODE_VEC_CURVE_REMAP,*/
NODE_SCALAR_INPUT, // scalar uniform (assignable in material)
NODE_VEC_INPUT, // vec3 uniform (assignable in material)
NODE_RGB_INPUT, // color uniform (assignable in material)
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 9a76a009a..30499ca21 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -2058,7 +2058,9 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
at+=get_datatype_name(compute_node_type(op->arguments[i]));
}
- parser.set_error("Invalid arguments to operator "+String(token_names[op->op])+": "+at);
+ static const char *op_names[OP_MAX]={"=","+","-","*","/","+=","-=","*=","/=","-","!","==","!=","<=",">=","<",">","||","&&","call","()"};
+
+ parser.set_error("Invalid arguments to operator "+String(op_names[op->op])+": "+at);
return ERR_PARSE_ERROR;
}
expression.remove(next_op);
diff --git a/tools/collada/collada.cpp b/tools/collada/collada.cpp
index 97e9f5c36..b55edde80 100644
--- a/tools/collada/collada.cpp
+++ b/tools/collada/collada.cpp
@@ -817,7 +817,7 @@ void Collada::_parse_camera(XMLParser& parser) {
if (name=="perspective") {
camera.mode=CameraData::MODE_PERSPECTIVE;
- } else if (name=="orthogonal") {
+ } else if (name=="orthographic") {
camera.mode=CameraData::MODE_ORTHOGONAL;
} else if (name=="xfov") {
diff --git a/tools/collada/collada.h b/tools/collada/collada.h
index f523d24e0..7691d90c0 100644
--- a/tools/collada/collada.h
+++ b/tools/collada/collada.h
@@ -337,6 +337,24 @@ public:
if(normal==p_vert.normal) {
if(uv==p_vert.uv) {
if(uv2==p_vert.uv2) {
+
+ if (!weights.empty() || !p_vert.weights.empty()) {
+
+ if (weights.size()==p_vert.weights.size()) {
+
+ for(int i=0;i 0) {
+ pad = p_alignment - rest;
+ };
+
+ return pad;
+};
Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path, const Vector& p_data,int p_file,int p_total) {
@@ -930,11 +940,19 @@ Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path
pd->ep->step("Storing File: "+p_path,2+p_file*100/p_total);
pd->count++;
pd->ftmp->store_buffer(p_data.ptr(),p_data.size());
+ if (pd->alignment > 1) {
+
+ int pad = _get_pad(pd->alignment, pd->ftmp->get_pos());
+ for (int i=0; iftmp->store_8(0);
+ };
+ };
return OK;
}
-Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
+Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles, int p_alignment) {
EditorProgress ep("savepack","Packing",102);
@@ -952,7 +970,6 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
dst->store_32(0);
}
-
size_t fcountpos = dst->get_pos();
dst->store_32(0);
@@ -961,11 +978,20 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
pd.f=dst;
pd.ftmp=tmp;
pd.count=0;
+ pd.alignment = p_alignment;
Error err = export_project_files(save_pack_file,&pd,p_make_bundles);
memdelete(tmp);
if (err)
return err;
+ if (p_alignment > 1) {
+ int pad = _get_pad(p_alignment, dst->get_pos());
+ for (int i=0; istore_8(0);
+ };
+ };
+
size_t ofsplus = dst->get_pos();
//append file
diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h
index 8305e3c88..b97dde12f 100644
--- a/tools/editor/editor_import_export.h
+++ b/tools/editor/editor_import_export.h
@@ -100,6 +100,7 @@ protected:
Vector file_ofs;
EditorProgress *ep;
int count;
+ int alignment;
};
@@ -121,7 +122,7 @@ public:
Error export_project_files(EditorExportSaveFunction p_func, void* p_udata,bool p_make_bundles);
- Error save_pack(FileAccess *p_where, bool p_make_bundles=false);
+ Error save_pack(FileAccess *p_where, bool p_make_bundles=false, int p_alignment = 1);
virtual String get_name() const =0;
virtual ImageCompression get_image_compression() const=0;
virtual Ref get_logo() const =0;
diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp
index 529ed3374..6dd46843c 100644
--- a/tools/editor/io_plugins/editor_import_collada.cpp
+++ b/tools/editor/io_plugins/editor_import_collada.cpp
@@ -285,13 +285,16 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) {
case Collada::CameraData::MODE_ORTHOGONAL: {
- if (cd.orthogonal.x_mag) {
+ if (cd.orthogonal.y_mag) {
- camera->set_orthogonal(cd.orthogonal.x_mag,cd.z_near,cd.z_far);
+ camera->set_keep_aspect_mode(Camera::KEEP_HEIGHT);
+ camera->set_orthogonal(cd.orthogonal.y_mag*2.0 ,cd.z_near,cd.z_far);
- } else if (!cd.orthogonal.x_mag && cd.orthogonal.y_mag) {
+ } else if (!cd.orthogonal.y_mag && cd.orthogonal.x_mag) {
- camera->set_orthogonal(cd.orthogonal.y_mag * cd.aspect,cd.z_near,cd.z_far);
+
+ camera->set_keep_aspect_mode(Camera::KEEP_WIDTH);
+ camera->set_orthogonal(cd.orthogonal.x_mag*2.0,cd.z_near,cd.z_far);
}
} break;
diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py
index 8161f05bf..5e5febfb1 100644
--- a/tools/export/blender25/io_scene_dae/export_dae.py
+++ b/tools/export/blender25/io_scene_dae/export_dae.py
@@ -94,8 +94,6 @@ def strarr(arr):
s+=" "
return s
-
-
class DaeExporter:
def validate_id(self,d):
@@ -132,10 +130,10 @@ class DaeExporter:
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)
+ for t in self.bones:
+ tup = tup + (float(t),)
+ for t in self.weights:
+ tup = tup + (float(t),)
return tup
@@ -212,8 +210,8 @@ class DaeExporter:
imgid = self.new_id("image")
if (not os.path.isfile(imgpath)):
- if img_tmp_path.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")):
- imgpath="images/"+os.path.basename(img_tmp_path)
+ if imgpath.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")):
+ imgpath="images/"+os.path.basename(imgpath)
else:
imgpath="images/"+image.name+".png"
@@ -512,12 +510,12 @@ class DaeExporter:
mat_assign=[]
uv_layer_count=len(mesh.uv_textures)
- if (len(mesh.uv_textures)):
+ if (has_tangents and 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
+ self.operator.report({'WARNING'},'CalcTangets failed for mesh "'+mesh.name+'", no tangets will be exported.')
+ #uv_layer_count=0
mesh.calc_normals_split()
has_tangents=False
@@ -591,16 +589,30 @@ class DaeExporter:
if (armature!=None):
wsum=0.0
+ zero_bones=[]
+
for vg in mv.groups:
if vg.group >= len(node.vertex_groups):
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)
wsum+=vg.weight
+ if (wsum==0.0):
+ if not self.wrongvtx_report:
+ self.operator.report({'WARNING'},'Mesh for object "'+node.name+'" has unassigned weights. This may look wrong in exported model.')
+ self.wrongvtx_report=True
+
+ #blender can have bones assigned that weight zero so they remain local
+ #this is the best it can be done?
+ v.bones.append(0)
+ v.weights.append(1)
+
+
tup = v.get_tup()
@@ -889,6 +901,15 @@ class DaeExporter:
if (node.parent!=None):
if (node.parent.type=="ARMATURE"):
armature=node.parent
+ armcount=0
+ for n in node.modifiers:
+ if (n.type=="ARMATURE"):
+ armcount+=1
+ if (armcount>1):
+ self.operator.report({'WARNING'},'Object "'+node.name+'" refers to more than one armature! This is unsopported.')
+
+
+
if (node.data.shape_keys!=None):
sk = node.data.shape_keys
@@ -940,6 +961,12 @@ class DaeExporter:
boneidx = si["bone_count"]
si["bone_count"]+=1
bonesid = si["id"]+"-"+str(boneidx)
+ if (bone.name in self.used_bones):
+ if (self.config["use_anim_action_all"]):
+ self.operator.report({'WARNING'},'Bone name "'+bone.name+'" used in more than one skeleton. Actions might export wrong.')
+ else:
+ self.used_bones.append(bone.name)
+
si["bone_index"][bone.name]=boneidx
si["bone_ids"][bone]=boneid
si["bone_names"].append(bonesid)
@@ -1002,12 +1029,12 @@ class DaeExporter:
self.writel(S_CAMS,5,' '+str(camera.clip_end)+' ')
self.writel(S_CAMS,4,'')
else:
- self.writel(S_CAMS,4,'')
- self.writel(S_CAMS,5,' '+str(camera.ortho_scale)+' ') # I think?
+ self.writel(S_CAMS,4,'')
+ self.writel(S_CAMS,5,' '+str(camera.ortho_scale*0.5)+' ') # I think?
self.writel(S_CAMS,5,' '+str(self.scene.render.resolution_x / self.scene.render.resolution_y)+' ')
self.writel(S_CAMS,5,' '+str(camera.clip_start)+' ')
self.writel(S_CAMS,5,' '+str(camera.clip_end)+' ')
- self.writel(S_CAMS,4,'')
+ self.writel(S_CAMS,4,'')
self.writel(S_CAMS,3,'')
self.writel(S_CAMS,2,'')
@@ -1534,10 +1561,14 @@ class DaeExporter:
for z in tcn:
self.writel(S_ANIM_CLIPS,2,'')
self.writel(S_ANIM_CLIPS,1,'')
+ if (len(tcn)==0):
+ self.operator.report({'WARNING'},'Animation clip "'+x.name+'" contains no tracks.')
+
self.writel(S_ANIM_CLIPS,0,'')
+
for i,s in enumerate(self.skeletons):
if (s.animation_data==None):
continue
@@ -1547,6 +1578,7 @@ class DaeExporter:
s.animation_data.action = None
for j,bone in enumerate(s.pose.bones):
bone.matrix_basis = tmp_mat[i][1][j]
+
else:
self.export_animation(self.scene.frame_start,self.scene.frame_end)
@@ -1617,7 +1649,8 @@ class DaeExporter:
f.write(bytes('\n',"UTF-8"))
return True
- def __init__(self,path,kwargs):
+ def __init__(self,path,kwargs,operator):
+ self.operator=operator
self.scene=bpy.context.scene
self.last_id=0
self.scene_name=self.new_id("scene")
@@ -1631,6 +1664,10 @@ class DaeExporter:
self.config=kwargs
self.valid_nodes=[]
self.armature_for_morph={}
+ self.used_bones=[]
+ self.wrongvtx_report=False
+
+
@@ -1642,9 +1679,11 @@ def save(operator, context,
**kwargs
):
- exp = DaeExporter(filepath,kwargs)
+ exp = DaeExporter(filepath,kwargs,operator)
exp.export()
+
+
return {'FINISHED'} # so the script wont run after we have batch exported.
--
cgit v1.2.3-70-g09d2