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.
This commit is contained in:
parent
0e732637d0
commit
a1f715a4da
|
@ -1778,6 +1778,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
|
||||||
f->store_32(VERSION_MINOR);
|
f->store_32(VERSION_MINOR);
|
||||||
f->store_32(FORMAT_VERSION);
|
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
|
//f->store_32(saved_resources.size()+external_resources.size()); // load steps -not needed
|
||||||
save_unicode_string(p_resource->get_type());
|
save_unicode_string(p_resource->get_type());
|
||||||
uint64_t md_at = f->get_pos();
|
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
|
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();
|
f->close();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2592,6 +2592,11 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_tag("resource_file");
|
exit_tag("resource_file");
|
||||||
|
if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
|
||||||
|
f->close();
|
||||||
|
return ERR_CANT_CREATE;
|
||||||
|
}
|
||||||
|
|
||||||
f->close();
|
f->close();
|
||||||
//memdelete(f);
|
//memdelete(f);
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
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.
|
///@TODO, give a check to this. I'm not sure if it's working.
|
||||||
set_identity();
|
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[2][3]=-(2*p_far*p_near) / (p_far-p_near);
|
||||||
matrix[3][2]=-1;
|
matrix[3][2]=-1;
|
||||||
matrix[3][3]=0;
|
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 {
|
float CameraMatrix::get_z_far() const {
|
||||||
|
|
||||||
const float * matrix = (const float*)this->matrix;
|
const float * matrix = (const float*)this->matrix;
|
||||||
|
|
|
@ -552,6 +552,9 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
|
||||||
if (p_b.type==MATRIX32) {
|
if (p_b.type==MATRIX32) {
|
||||||
_RETURN( *p_a._data._matrix32 * *p_b._data._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;
|
r_valid=false;
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -10,7 +10,6 @@ SConscript('alsa/SCsub');
|
||||||
SConscript('pulseaudio/SCsub');
|
SConscript('pulseaudio/SCsub');
|
||||||
SConscript('windows/SCsub');
|
SConscript('windows/SCsub');
|
||||||
SConscript('gles2/SCsub');
|
SConscript('gles2/SCsub');
|
||||||
SConscript('gles1/SCsub');
|
|
||||||
SConscript('gl_context/SCsub');
|
SConscript('gl_context/SCsub');
|
||||||
SConscript('openssl/SCsub');
|
SConscript('openssl/SCsub');
|
||||||
|
|
||||||
|
|
|
@ -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;
|
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) {
|
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_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 {
|
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")));
|
shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter")));
|
||||||
#endif
|
#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 );
|
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
|
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_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
|
||||||
canvas_texscreen_used=false;
|
canvas_texscreen_used=false;
|
||||||
uses_texpixel_size=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);
|
//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<Vector2>& 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<float> geometry;
|
||||||
|
DVector<uint16_t> indices;
|
||||||
|
int lc = p_lines.size();
|
||||||
|
|
||||||
|
geometry.resize(lc*6);
|
||||||
|
indices.resize(lc*3);
|
||||||
|
|
||||||
|
DVector<float>::Write vw=geometry.write();
|
||||||
|
DVector<uint16_t>::Write iw=indices.write();
|
||||||
|
|
||||||
|
|
||||||
|
DVector<Vector2>::Read lr=p_lines.read();
|
||||||
|
|
||||||
|
const int POLY_HEIGHT = 16384;
|
||||||
|
|
||||||
|
for(int i=0;i<lc/2;i++) {
|
||||||
|
|
||||||
|
vw[i*12+0]=lr[i*2+0].x;
|
||||||
|
vw[i*12+1]=lr[i*2+0].y;
|
||||||
|
vw[i*12+2]=POLY_HEIGHT;
|
||||||
|
|
||||||
|
vw[i*12+3]=lr[i*2+1].x;
|
||||||
|
vw[i*12+4]=lr[i*2+1].y;
|
||||||
|
vw[i*12+5]=POLY_HEIGHT;
|
||||||
|
|
||||||
|
vw[i*12+6]=lr[i*2+1].x;
|
||||||
|
vw[i*12+7]=lr[i*2+1].y;
|
||||||
|
vw[i*12+8]=-POLY_HEIGHT;
|
||||||
|
|
||||||
|
vw[i*12+9]=lr[i*2+0].x;
|
||||||
|
vw[i*12+10]=lr[i*2+0].y;
|
||||||
|
vw[i*12+11]=-POLY_HEIGHT;
|
||||||
|
|
||||||
|
iw[i*6+0]=i*4+0;
|
||||||
|
iw[i*6+1]=i*4+1;
|
||||||
|
iw[i*6+2]=i*4+2;
|
||||||
|
|
||||||
|
iw[i*6+3]=i*4+2;
|
||||||
|
iw[i*6+4]=i*4+3;
|
||||||
|
iw[i*6+5]=i*4+0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//if same buffer len is being set, just use BufferSubData to avoid a pipeline flush
|
||||||
|
|
||||||
|
|
||||||
|
if (!co->vertex_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;i<cc->lines.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;i<passes;i++) {
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, blur->fbo);
|
||||||
|
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) {
|
void RasterizerGLES2::_canvas_normal_set_flip(const Vector2& p_flip) {
|
||||||
|
|
||||||
if (p_flip==normal_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())
|
if (canvas_shader.bind())
|
||||||
rebind_texpixel_size=true;
|
rebind_texpixel_size=true;
|
||||||
|
|
||||||
if (shader_owner->shader_version!=shader->version) {
|
if (material->shader_version!=shader->version) {
|
||||||
//todo optimize uniforms
|
//todo optimize uniforms
|
||||||
shader_owner->shader_version=shader->version;
|
material->shader_version=shader->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader->has_texscreen && framebuffer.active) {
|
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..
|
//this can be optimized..
|
||||||
int tex_id=1;
|
int tex_id=1;
|
||||||
int idx=0;
|
int idx=0;
|
||||||
for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) {
|
for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) {
|
||||||
|
|
||||||
Map<StringName,Variant>::Element *F=shader_owner->shader_param.find(E->key());
|
Map<StringName,Variant>::Element *F=material->shader_param.find(E->key());
|
||||||
|
|
||||||
if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) {
|
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_modulate=p_modulate;
|
||||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
|
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
|
||||||
|
|
||||||
|
bool reset_modulate=false;
|
||||||
|
|
||||||
while(p_item_list) {
|
while(p_item_list) {
|
||||||
|
|
||||||
CanvasItem *ci=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);
|
draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect);
|
||||||
}
|
}
|
||||||
memdelete(ci->vp_render);
|
memdelete(ci->vp_render);
|
||||||
ci->vp_render=NULL;
|
ci->vp_render=NULL;
|
||||||
canvas_last_shader=RID();
|
canvas_last_material=NULL;
|
||||||
canvas_use_modulate=p_modulate!=Color(1,1,1,1);
|
canvas_use_modulate=p_modulate!=Color(1,1,1,1);
|
||||||
canvas_modulate=p_modulate;
|
canvas_modulate=p_modulate;
|
||||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
|
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
|
||||||
rebind_shader=true;
|
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
|
//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;
|
Shader *shader = NULL;
|
||||||
if (shader_owner->shader.is_valid()) {
|
if (material && material->shader.is_valid()) {
|
||||||
shader = this->shader_owner.get(shader_owner->shader);
|
shader = shader_owner.get(material->shader);
|
||||||
if (shader && !shader->valid) {
|
if (shader && !shader->valid) {
|
||||||
shader=NULL;
|
shader=NULL;
|
||||||
}
|
}
|
||||||
|
@ -8676,7 +9155,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
|
||||||
|
|
||||||
if (shader) {
|
if (shader) {
|
||||||
canvas_shader.set_custom_shader(shader->custom_code_id);
|
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 {
|
} else {
|
||||||
shader_cache=NULL;
|
shader_cache=NULL;
|
||||||
canvas_shader.set_custom_shader(0);
|
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);
|
canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
|
||||||
if (canvas_use_modulate)
|
if (canvas_use_modulate)
|
||||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
|
reset_modulate=true;
|
||||||
canvas_last_shader=shader_owner->shader;
|
canvas_last_material=material;
|
||||||
rebind_shader=false;
|
rebind_shader=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader_cache) {
|
if (material && shader_cache) {
|
||||||
|
|
||||||
_canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
|
_canvas_item_setup_shader_uniforms(material,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::MODELVIEW_MATRIX,ci->final_transform);
|
||||||
canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
|
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<false>(ci,current_clip,reclip);
|
_canvas_item_render_commands<false>(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;
|
CanvasLight *light = p_light;
|
||||||
bool light_used=false;
|
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);
|
normal_flip=Vector2(1,1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,light->shadow_buffer.is_valid());
|
||||||
|
|
||||||
bool light_rebind = canvas_shader.bind();
|
bool light_rebind = canvas_shader.bind();
|
||||||
|
|
||||||
if (light_rebind) {
|
if (light_rebind) {
|
||||||
|
|
||||||
if (shader_owner && shader_cache) {
|
if (material && shader_cache) {
|
||||||
_canvas_item_setup_shader_params(shader_owner,shader_cache);
|
_canvas_item_setup_shader_params(material,shader_cache);
|
||||||
_canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
|
_canvas_item_setup_shader_uniforms(material,shader_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
|
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)
|
if (canvas_use_modulate)
|
||||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
|
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
|
||||||
canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,Vector2(1,1));
|
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_POS,light->light_shader_pos);
|
||||||
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color);
|
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color);
|
||||||
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
|
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);
|
glActiveTexture(GL_TEXTURE0+max_texture_units-2);
|
||||||
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_TEXTURE,max_texture_units-2);
|
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_TEXTURE,max_texture_units-2);
|
||||||
Texture *t = texture_owner.get(light->texture);
|
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_LIGHTING,false);
|
||||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
|
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
|
||||||
|
canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,false);
|
||||||
|
|
||||||
canvas_shader.bind();
|
canvas_shader.bind();
|
||||||
|
|
||||||
if (shader_owner && shader_cache) {
|
if (material && shader_cache) {
|
||||||
_canvas_item_setup_shader_params(shader_owner,shader_cache);
|
_canvas_item_setup_shader_params(material,shader_cache);
|
||||||
_canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
|
_canvas_item_setup_shader_uniforms(material,shader_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
|
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 {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9244,7 +9759,30 @@ void RasterizerGLES2::free(const RID& p_rid) {
|
||||||
glDeleteTextures(1,&sampled_light->texture);
|
glDeleteTextures(1,&sampled_light->texture);
|
||||||
sampled_light_owner.free(p_rid);
|
sampled_light_owner.free(p_rid);
|
||||||
memdelete( sampled_light );
|
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();
|
material_shader.init();
|
||||||
canvas_shader.init();
|
canvas_shader.init();
|
||||||
copy_shader.init();
|
copy_shader.init();
|
||||||
|
canvas_shadow_shader.init();
|
||||||
|
|
||||||
#ifdef GLEW_ENABLED
|
#ifdef GLEW_ENABLED
|
||||||
material_shader.set_conditional(MaterialShaderGLES2::USE_GLES_OVER_GL,true);
|
material_shader.set_conditional(MaterialShaderGLES2::USE_GLES_OVER_GL,true);
|
||||||
canvas_shader.set_conditional(CanvasShaderGLES2::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);
|
copy_shader.set_conditional(CopyShaderGLES2::USE_GLES_OVER_GL,true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -9923,8 +10463,11 @@ void RasterizerGLES2::init() {
|
||||||
|
|
||||||
|
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);
|
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_texture_size);
|
||||||
//read_depth_supported=false;
|
//read_depth_supported=false;
|
||||||
|
|
||||||
|
canvas_shadow_blur = canvas_light_shadow_buffer_create(max_texture_size);
|
||||||
|
|
||||||
{
|
{
|
||||||
//shadowmaps
|
//shadowmaps
|
||||||
OS::VideoMode vm=OS::get_singleton()->get_video_mode();
|
OS::VideoMode vm=OS::get_singleton()->get_video_mode();
|
||||||
|
@ -9946,6 +10489,7 @@ void RasterizerGLES2::init() {
|
||||||
|
|
||||||
//material_shader
|
//material_shader
|
||||||
material_shader.set_conditional(MaterialShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps);
|
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() {
|
void RasterizerGLES2::finish() {
|
||||||
|
|
||||||
|
free(canvas_shadow_blur);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) {
|
int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) {
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
|
|
||||||
#include "drivers/gles2/shaders/material.glsl.h"
|
#include "drivers/gles2/shaders/material.glsl.h"
|
||||||
#include "drivers/gles2/shaders/canvas.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/blur.glsl.h"
|
||||||
#include "drivers/gles2/shaders/copy.glsl.h"
|
#include "drivers/gles2/shaders/copy.glsl.h"
|
||||||
#include "drivers/gles2/shader_compiler_gles2.h"
|
#include "drivers/gles2/shader_compiler_gles2.h"
|
||||||
|
@ -816,6 +817,7 @@ class RasterizerGLES2 : public Rasterizer {
|
||||||
bool current_depth_mask;
|
bool current_depth_mask;
|
||||||
VS::MaterialBlendMode current_blend_mode;
|
VS::MaterialBlendMode current_blend_mode;
|
||||||
bool use_fast_texture_filter;
|
bool use_fast_texture_filter;
|
||||||
|
int max_texture_size;
|
||||||
|
|
||||||
bool fragment_lighting;
|
bool fragment_lighting;
|
||||||
RID shadow_material;
|
RID shadow_material;
|
||||||
|
@ -1160,6 +1162,7 @@ class RasterizerGLES2 : public Rasterizer {
|
||||||
void _process_glow_and_bloom();
|
void _process_glow_and_bloom();
|
||||||
//void _update_blur_buffer();
|
//void _update_blur_buffer();
|
||||||
|
|
||||||
|
|
||||||
/*********/
|
/*********/
|
||||||
/* FRAME */
|
/* FRAME */
|
||||||
/*********/
|
/*********/
|
||||||
|
@ -1178,6 +1181,45 @@ class RasterizerGLES2 : public Rasterizer {
|
||||||
} _rinfo;
|
} _rinfo;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************/
|
||||||
|
/* CANVAS OCCLUDER */
|
||||||
|
/*******************/
|
||||||
|
|
||||||
|
|
||||||
|
struct CanvasOccluder {
|
||||||
|
|
||||||
|
GLuint vertex_id; // 0 means, unconfigured
|
||||||
|
GLuint index_id; // 0 means, unconfigured
|
||||||
|
DVector<Vector2> lines;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
|
RID_Owner<CanvasOccluder> 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<CanvasLightShadow> canvas_light_shadow_owner;
|
||||||
|
|
||||||
|
RID canvas_shadow_blur;
|
||||||
|
|
||||||
|
/* ETC */
|
||||||
|
|
||||||
RenderTarget *current_rt;
|
RenderTarget *current_rt;
|
||||||
bool current_rt_transparent;
|
bool current_rt_transparent;
|
||||||
bool current_rt_vflip;
|
bool current_rt_vflip;
|
||||||
|
@ -1192,7 +1234,7 @@ class RasterizerGLES2 : public Rasterizer {
|
||||||
bool uses_texpixel_size;
|
bool uses_texpixel_size;
|
||||||
bool rebind_texpixel_size;
|
bool rebind_texpixel_size;
|
||||||
Transform canvas_transform;
|
Transform canvas_transform;
|
||||||
RID canvas_last_shader;
|
CanvasItemMaterial *canvas_last_material;
|
||||||
bool canvas_texscreen_used;
|
bool canvas_texscreen_used;
|
||||||
Vector2 normal_flip;
|
Vector2 normal_flip;
|
||||||
_FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2& p_flip);
|
_FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2& p_flip);
|
||||||
|
@ -1227,10 +1269,12 @@ class RasterizerGLES2 : public Rasterizer {
|
||||||
VS::ScenarioDebugMode current_debug;
|
VS::ScenarioDebugMode current_debug;
|
||||||
RID overdraw_material;
|
RID overdraw_material;
|
||||||
|
|
||||||
|
|
||||||
mutable MaterialShaderGLES2 material_shader;
|
mutable MaterialShaderGLES2 material_shader;
|
||||||
mutable CanvasShaderGLES2 canvas_shader;
|
mutable CanvasShaderGLES2 canvas_shader;
|
||||||
BlurShaderGLES2 blur_shader;
|
BlurShaderGLES2 blur_shader;
|
||||||
CopyShaderGLES2 copy_shader;
|
CopyShaderGLES2 copy_shader;
|
||||||
|
mutable CanvasShadowShaderGLES2 canvas_shadow_shader;
|
||||||
|
|
||||||
mutable ShaderCompilerGLES2 shader_precompiler;
|
mutable ShaderCompilerGLES2 shader_precompiler;
|
||||||
|
|
||||||
|
@ -1254,8 +1298,8 @@ class RasterizerGLES2 : public Rasterizer {
|
||||||
|
|
||||||
template<bool use_normalmap>
|
template<bool use_normalmap>
|
||||||
_FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip);
|
_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_params(CanvasItemMaterial *material,Shader* p_shader);
|
||||||
_FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItem *shader_owner,Shader* p_shader);
|
_FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* p_shader);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* TEXTURE API */
|
/* TEXTURE API */
|
||||||
|
@ -1572,7 +1616,17 @@ public:
|
||||||
virtual void canvas_set_transform(const Matrix32& p_transform);
|
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_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<Vector2>& p_lines);
|
||||||
|
|
||||||
/* ENVIRONMENT */
|
/* ENVIRONMENT */
|
||||||
|
|
||||||
|
@ -1611,6 +1665,8 @@ public:
|
||||||
virtual bool is_environment(const RID& p_rid) const;
|
virtual bool is_environment(const RID& p_rid) const;
|
||||||
virtual bool is_shader(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 free(const RID& p_rid);
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
|
@ -3,6 +3,7 @@ Import('env')
|
||||||
if env['BUILDERS'].has_key('GLSL120GLES'):
|
if env['BUILDERS'].has_key('GLSL120GLES'):
|
||||||
env.GLSL120GLES('material.glsl');
|
env.GLSL120GLES('material.glsl');
|
||||||
env.GLSL120GLES('canvas.glsl');
|
env.GLSL120GLES('canvas.glsl');
|
||||||
|
env.GLSL120GLES('canvas_shadow.glsl');
|
||||||
env.GLSL120GLES('blur.glsl');
|
env.GLSL120GLES('blur.glsl');
|
||||||
env.GLSL120GLES('copy.glsl');
|
env.GLSL120GLES('copy.glsl');
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@ varying vec4 local_rot;
|
||||||
uniform vec2 normal_flip;
|
uniform vec2 normal_flip;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_SHADOWS
|
||||||
|
highp varying vec2 pos;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_VAR1_INTERP)
|
#if defined(ENABLE_VAR1_INTERP)
|
||||||
|
@ -63,6 +67,8 @@ VERTEX_SHADER_CODE
|
||||||
outvec = modelview_matrix * outvec;
|
outvec = modelview_matrix * outvec;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_PIXEL_SNAP
|
#ifdef USE_PIXEL_SNAP
|
||||||
|
|
||||||
outvec.xy=floor(outvec.xy+0.5);
|
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.xy = (light_matrix * outvec).xy;
|
||||||
light_uv_interp.zw = outvec.xy-light_pos;
|
light_uv_interp.zw = outvec.xy-light_pos;
|
||||||
|
#ifdef USE_SHADOWS
|
||||||
|
pos=outvec.xy;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(NORMAL_USED)
|
#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;
|
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 sampler2D shadow_texture;
|
||||||
uniform float shadow_attenuation;
|
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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -173,10 +191,6 @@ void main() {
|
||||||
vec3 normal = vec3(0,0,1);
|
vec3 normal = vec3(0,0,1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_MODULATE
|
|
||||||
|
|
||||||
color*=modulate;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
color *= texture2D( texture, uv_interp );
|
color *= texture2D( texture, uv_interp );
|
||||||
#if defined(ENABLE_SCREEN_UV)
|
#if defined(ENABLE_SCREEN_UV)
|
||||||
|
@ -191,6 +205,12 @@ FRAGMENT_SHADER_CODE
|
||||||
color = vec4(vec3(enc32),1.0);
|
color = vec4(vec3(enc32),1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_MODULATE
|
||||||
|
|
||||||
|
color*=modulate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_LIGHTING
|
#ifdef USE_LIGHTING
|
||||||
|
|
||||||
#if defined(NORMAL_USED)
|
#if defined(NORMAL_USED)
|
||||||
|
@ -201,13 +221,96 @@ FRAGMENT_SHADER_CODE
|
||||||
|
|
||||||
vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color;
|
vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color;
|
||||||
#ifdef USE_SHADOWS
|
#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;
|
vec2 lpos = (light_local_matrix * vec4(pos,0.0,1.0)).xy;
|
||||||
float shadow_dist = texture2D(shadow_texture,vec2(light_angle,0));
|
float angle_to_light = -atan(lpos.x,lpos.y);
|
||||||
if (light_dist>shadow_dist) {
|
float PI = 3.14159265358979323846264;
|
||||||
light*=shadow_attenuation;
|
/*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<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation/=5.0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SHADOW_PCF13
|
||||||
|
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*3.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*4.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*5.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*6.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*3.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*4.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*5.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*6.0,sh)).z<sz?0.0:1.0;
|
||||||
|
shadow_attenuation/=13.0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SHADOW_ESM
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
float unnormalized = su/shadowpixel_size;
|
||||||
|
float fractional = fract(unnormalized);
|
||||||
|
unnormalized = floor(unnormalized);
|
||||||
|
float zc = texture2D(shadow_texture,vec2((unnormalized-0.5)*shadowpixel_size,sh)).z;
|
||||||
|
float zn = texture2D(shadow_texture,vec2((unnormalized+0.5)*shadowpixel_size,sh)).z;
|
||||||
|
float z = mix(zc,zn,fractional);
|
||||||
|
shadow_attenuation=clamp(exp(shadow_esm_multiplier* ( z - sz )),0.0,1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(SHADOW_PCF5) && !defined(SHADOW_PCF13) && !defined(SHADOW_ESM)
|
||||||
|
|
||||||
|
shadow_attenuation = texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
light*=shadow_attenuation;
|
||||||
//use shadows
|
//use shadows
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
[vertex]
|
||||||
|
|
||||||
|
#ifdef USE_GLES_OVER_GL
|
||||||
|
#define mediump
|
||||||
|
#define highp
|
||||||
|
#else
|
||||||
|
precision mediump float;
|
||||||
|
precision mediump int;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform highp mat4 projection_matrix;
|
||||||
|
uniform highp mat4 light_matrix;
|
||||||
|
uniform highp mat4 world_matrix;
|
||||||
|
|
||||||
|
attribute highp vec3 vertex; // attrib:0
|
||||||
|
|
||||||
|
#ifndef USE_DEPTH_SHADOWS
|
||||||
|
|
||||||
|
varying vec4 position_interp;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex,1.0)));
|
||||||
|
|
||||||
|
#ifndef USE_DEPTH_SHADOWS
|
||||||
|
position_interp = gl_Position;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[fragment]
|
||||||
|
|
||||||
|
#ifdef USE_GLES_OVER_GL
|
||||||
|
#define mediump
|
||||||
|
#define highp
|
||||||
|
#else
|
||||||
|
precision mediump float;
|
||||||
|
precision mediump int;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_DEPTH_SHADOWS
|
||||||
|
|
||||||
|
varying vec4 position_interp;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
#ifdef USE_DEPTH_SHADOWS
|
||||||
|
|
||||||
|
#else
|
||||||
|
highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias;
|
||||||
|
highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
|
||||||
|
comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
|
||||||
|
gl_FragColor = comp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -28,14 +28,18 @@
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
#ifdef WINDOWS_ENABLED
|
#ifdef WINDOWS_ENABLED
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include "Shlwapi.h"
|
||||||
#include "file_access_windows.h"
|
#include "file_access_windows.h"
|
||||||
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include "print_string.h"
|
#include "print_string.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define S_ISREG(m) ((m)&_S_IFREG)
|
#define S_ISREG(m) ((m)&_S_IFREG)
|
||||||
#endif
|
#endif
|
||||||
|
@ -111,10 +115,20 @@ void FileAccessWindows::close() {
|
||||||
|
|
||||||
//unlink(save_path.utf8().get_data());
|
//unlink(save_path.utf8().get_data());
|
||||||
//print_line("renaming..");
|
//print_line("renaming..");
|
||||||
_wunlink(save_path.c_str()); //unlink if exists
|
//_wunlink(save_path.c_str()); //unlink if exists
|
||||||
int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());
|
//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="";
|
save_path="";
|
||||||
ERR_FAIL_COND( rename_error != 0);
|
ERR_FAIL_COND( rename_error );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2696,7 +2696,10 @@ Error ResourceFormatSaverGDScript::save(const String &p_path,const RES& p_resour
|
||||||
}
|
}
|
||||||
|
|
||||||
file->store_string(source);
|
file->store_string(source);
|
||||||
|
if (file->get_error()!=OK && file->get_error()!=ERR_FILE_EOF) {
|
||||||
|
memdelete(file);
|
||||||
|
return ERR_CANT_CREATE;
|
||||||
|
}
|
||||||
file->close();
|
file->close();
|
||||||
memdelete(file);
|
memdelete(file);
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
@ -396,6 +396,14 @@ void AudioDriverOpenSL::finish(){
|
||||||
void AudioDriverOpenSL::set_pause(bool p_pause) {
|
void AudioDriverOpenSL::set_pause(bool p_pause) {
|
||||||
|
|
||||||
pause=p_pause;
|
pause=p_pause;
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
if (pause) {
|
||||||
|
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED);
|
||||||
|
} else {
|
||||||
|
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
|
||||||
sample_manager = memnew( SampleManagerMallocSW );
|
sample_manager = memnew( SampleManagerMallocSW );
|
||||||
audio_server = memnew( AudioServerSW(sample_manager) );
|
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();
|
audio_server->init();
|
||||||
|
|
||||||
spatial_sound_server = memnew( SpatialSoundServerSW );
|
spatial_sound_server = memnew( SpatialSoundServerSW );
|
||||||
|
|
|
@ -115,7 +115,7 @@ def configure(env):
|
||||||
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
|
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
|
||||||
|
|
||||||
env.Append(CCFLAGS=['/DGLEW_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(LINKFLAGS=[p+env["LIBSUFFIX"] for p in LIBS])
|
||||||
|
|
||||||
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
|
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
|
||||||
|
@ -229,7 +229,7 @@ def configure(env):
|
||||||
env.Append(CCFLAGS=['-DWINDOWS_ENABLED','-mwindows'])
|
env.Append(CCFLAGS=['-DWINDOWS_ENABLED','-mwindows'])
|
||||||
env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
|
env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
|
||||||
env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLEW_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"):
|
if (env["bits"]=="32" and env["mingw64_for_32"]!="yes"):
|
||||||
# env.Append(LIBS=['gcc_s'])
|
# env.Append(LIBS=['gcc_s'])
|
||||||
|
|
|
@ -36,6 +36,192 @@
|
||||||
#include "scene/resources/texture.h"
|
#include "scene/resources/texture.h"
|
||||||
#include "scene/resources/style_box.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<PropertyInfo> *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<Shader>& 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<Shader> 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<String>*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<PropertyInfo> pl;
|
||||||
|
shader->get_param_list(&pl);
|
||||||
|
for (List<PropertyInfo>::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 {
|
bool CanvasItem::is_visible() const {
|
||||||
|
|
||||||
if (!is_inside_tree())
|
if (!is_inside_tree())
|
||||||
|
@ -730,111 +916,35 @@ bool CanvasItem::is_draw_behind_parent_enabled() const{
|
||||||
return behind;
|
return behind;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanvasItem::set_shader(const Ref<Shader>& p_shader) {
|
void CanvasItem::set_material(const Ref<CanvasItemMaterial>& p_material) {
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
material=p_material;
|
||||||
RID rid;
|
RID rid;
|
||||||
if (shader.is_valid())
|
if (material.is_valid())
|
||||||
rid=shader->get_rid();
|
rid=material->get_rid();
|
||||||
VS::get_singleton()->canvas_item_set_shader(canvas_item,rid);
|
VS::get_singleton()->canvas_item_set_material(canvas_item,rid);
|
||||||
_change_notify(); //properties for shader exposed
|
_change_notify(); //properties for material exposed
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanvasItem::set_use_parent_shader(bool p_use_parent_shader) {
|
void CanvasItem::set_use_parent_material(bool p_use_parent_material) {
|
||||||
|
|
||||||
use_parent_shader=p_use_parent_shader;
|
use_parent_material=p_use_parent_material;
|
||||||
VS::get_singleton()->canvas_item_set_use_parent_shader(canvas_item,p_use_parent_shader);
|
VS::get_singleton()->canvas_item_set_use_parent_material(canvas_item,p_use_parent_material);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanvasItem::get_use_parent_shader() const{
|
bool CanvasItem::get_use_parent_material() const{
|
||||||
|
|
||||||
return use_parent_shader;
|
return use_parent_material;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Shader> CanvasItem::get_shader() const{
|
Ref<CanvasItemMaterial> CanvasItem::get_material() const{
|
||||||
|
|
||||||
return shader;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanvasItem::set_shader_param(const StringName& p_param,const Variant& p_value) {
|
|
||||||
|
|
||||||
VS::get_singleton()->canvas_item_set_shader_param(canvas_item,p_param,p_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
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<PropertyInfo> *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<String>*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<PropertyInfo> pl;
|
|
||||||
shader->get_param_list(&pl);
|
|
||||||
for(List<PropertyInfo>::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() {
|
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("_set_on_top","on_top"),&CanvasItem::_set_on_top);
|
||||||
ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_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("get_transform"),&CanvasItem::get_transform);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0));
|
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("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform);
|
||||||
ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_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"),&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_transform"),&CanvasItem::get_viewport_transform);
|
||||||
ObjectTypeDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect);
|
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_canvas"),&CanvasItem::get_canvas);
|
||||||
ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d);
|
ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d);
|
||||||
//ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
|
//ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_shader","shader"),&CanvasItem::set_shader);
|
ObjectTypeDB::bind_method(_MD("set_material","material:CanvasItemMaterial"),&CanvasItem::set_material);
|
||||||
ObjectTypeDB::bind_method(_MD("get_shader"),&CanvasItem::get_shader);
|
ObjectTypeDB::bind_method(_MD("get_material:CanvasItemMaterial"),&CanvasItem::get_material);
|
||||||
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_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"));
|
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/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::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::OBJECT,"material/material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"),_SCS("get_material") );
|
||||||
ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"shader/use_parent"), _SCS("set_use_parent_shader"),_SCS("get_use_parent_shader") );
|
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
|
//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/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"));
|
//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;
|
block_transform_notify=false;
|
||||||
// viewport=NULL;
|
// viewport=NULL;
|
||||||
canvas_layer=NULL;
|
canvas_layer=NULL;
|
||||||
use_parent_shader=false;
|
use_parent_material=false;
|
||||||
global_invalid=true;
|
global_invalid=true;
|
||||||
light_mask=1;
|
light_mask=1;
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,41 @@ class Font;
|
||||||
|
|
||||||
class StyleBox;
|
class StyleBox;
|
||||||
|
|
||||||
|
class CanvasItemMaterial : public Resource{
|
||||||
|
|
||||||
|
OBJ_TYPE(CanvasItemMaterial,Resource);
|
||||||
|
RID material;
|
||||||
|
Ref<Shader> 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<PropertyInfo> *p_list) const;
|
||||||
|
|
||||||
|
void _shader_changed();
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void set_shader(const Ref<Shader>& p_shader);
|
||||||
|
Ref<Shader> 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 {
|
class CanvasItem : public Node {
|
||||||
|
|
||||||
OBJ_TYPE( CanvasItem, Node );
|
OBJ_TYPE( CanvasItem, Node );
|
||||||
|
@ -81,9 +116,9 @@ private:
|
||||||
bool drawing;
|
bool drawing;
|
||||||
bool block_transform_notify;
|
bool block_transform_notify;
|
||||||
bool behind;
|
bool behind;
|
||||||
bool use_parent_shader;
|
bool use_parent_material;
|
||||||
|
|
||||||
Ref<Shader> shader;
|
Ref<CanvasItemMaterial> material;
|
||||||
|
|
||||||
mutable Matrix32 global_transform;
|
mutable Matrix32 global_transform;
|
||||||
mutable bool global_invalid;
|
mutable bool global_invalid;
|
||||||
|
@ -104,9 +139,6 @@ private:
|
||||||
void _queue_sort_children();
|
void _queue_sort_children();
|
||||||
void _sort_children();
|
void _sort_children();
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
|
||||||
void _shader_changed();
|
|
||||||
#endif
|
|
||||||
void _notify_transform(CanvasItem *p_node);
|
void _notify_transform(CanvasItem *p_node);
|
||||||
|
|
||||||
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
|
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
|
||||||
|
@ -114,11 +146,6 @@ private:
|
||||||
|
|
||||||
protected:
|
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<PropertyInfo> *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); }
|
_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();
|
void item_rect_changed();
|
||||||
|
@ -216,16 +243,12 @@ public:
|
||||||
RID get_canvas() const;
|
RID get_canvas() const;
|
||||||
Ref<World2D> get_world_2d() const;
|
Ref<World2D> get_world_2d() const;
|
||||||
|
|
||||||
void set_shader(const Ref<Shader>& p_shader);
|
void set_material(const Ref<CanvasItemMaterial>& p_material);
|
||||||
Ref<Shader> get_shader() const;
|
Ref<CanvasItemMaterial> get_material() const;
|
||||||
|
|
||||||
void set_use_parent_shader(bool p_use_parent_shader);
|
void set_use_parent_material(bool p_use_parent_material);
|
||||||
bool get_use_parent_shader() const;
|
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<String>*r_options) const;
|
|
||||||
|
|
||||||
CanvasItem();
|
CanvasItem();
|
||||||
~CanvasItem();
|
~CanvasItem();
|
||||||
|
|
|
@ -170,6 +170,29 @@ bool Light2D::is_shadow_enabled() const {
|
||||||
return shadow;
|
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) {
|
void Light2D::_notification(int p_what) {
|
||||||
|
|
||||||
if (p_what==NOTIFICATION_ENTER_TREE) {
|
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("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
|
||||||
ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_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::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::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::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,"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;
|
layer_max=0;
|
||||||
item_mask=1;
|
item_mask=1;
|
||||||
subtract_mode=false;
|
subtract_mode=false;
|
||||||
|
shadow_buffer_size=2048;
|
||||||
|
shadow_esm_multiplier=80;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ private:
|
||||||
int layer_min;
|
int layer_min;
|
||||||
int layer_max;
|
int layer_max;
|
||||||
int item_mask;
|
int item_mask;
|
||||||
|
int shadow_buffer_size;
|
||||||
|
float shadow_esm_multiplier;
|
||||||
bool subtract_mode;
|
bool subtract_mode;
|
||||||
Ref<Texture> texture;
|
Ref<Texture> texture;
|
||||||
Vector2 texture_offset;
|
Vector2 texture_offset;
|
||||||
|
@ -68,6 +70,12 @@ public:
|
||||||
void set_shadow_enabled( bool p_enabled);
|
void set_shadow_enabled( bool p_enabled);
|
||||||
bool is_shadow_enabled() const;
|
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;
|
virtual Rect2 get_item_rect() const;
|
||||||
|
|
||||||
Light2D();
|
Light2D();
|
||||||
|
|
|
@ -0,0 +1,201 @@
|
||||||
|
#include "light_occluder_2d.h"
|
||||||
|
|
||||||
|
|
||||||
|
void OccluderPolygon2D::set_polygon(const DVector<Vector2>& p_polygon) {
|
||||||
|
|
||||||
|
polygon=p_polygon;
|
||||||
|
VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,p_polygon,closed);
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
DVector<Vector2> 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<Vector2> poly = occluder_polygon->get_polygon();
|
||||||
|
|
||||||
|
if (poly.size()) {
|
||||||
|
if (occluder_polygon->is_closed()) {
|
||||||
|
Vector<Color> color;
|
||||||
|
color.push_back(Color(0,0,0,0.6));
|
||||||
|
draw_polygon(Variant(poly),color);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
int ps=poly.size();
|
||||||
|
DVector<Vector2>::Read r = poly.read();
|
||||||
|
for(int i=0;i<ps-1;i++) {
|
||||||
|
|
||||||
|
draw_line(r[i],r[i+1],Color(0,0,0,0.6),3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (p_what==NOTIFICATION_EXIT_CANVAS) {
|
||||||
|
|
||||||
|
VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,RID());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D>& 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<OccluderPolygon2D> 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);
|
||||||
|
}
|
||||||
|
|
|
@ -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<Vector2> polygon;
|
||||||
|
bool closed;
|
||||||
|
CullMode cull;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
static void _bind_methods();
|
||||||
|
public:
|
||||||
|
|
||||||
|
void set_polygon(const DVector<Vector2>& p_polygon);
|
||||||
|
DVector<Vector2> 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<OccluderPolygon2D> 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<OccluderPolygon2D>& p_polygon);
|
||||||
|
Ref<OccluderPolygon2D> get_occluder_polygon() const;
|
||||||
|
|
||||||
|
void set_occluder_light_mask(int p_mask);
|
||||||
|
int get_occluder_light_mask() const;
|
||||||
|
|
||||||
|
LightOccluder2D();
|
||||||
|
~LightOccluder2D();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LIGHTOCCLUDER2D_H
|
|
@ -152,11 +152,11 @@ void Camera::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||||
|
|
||||||
case PROJECTION_PERSPECTIVE: {
|
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)
|
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
|
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;
|
} break;
|
||||||
|
|
|
@ -310,6 +310,17 @@ int GeometryInstance::get_baked_light_texture_id() const{
|
||||||
return baked_light_texture_id;
|
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() {
|
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("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("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);
|
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);
|
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_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_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::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"), _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/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);
|
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE);
|
||||||
|
|
|
@ -108,6 +108,7 @@ private:
|
||||||
void _find_baked_light();
|
void _find_baked_light();
|
||||||
BakedLightInstance *baked_light_instance;
|
BakedLightInstance *baked_light_instance;
|
||||||
int baked_light_texture_id;
|
int baked_light_texture_id;
|
||||||
|
float extra_cull_margin;
|
||||||
|
|
||||||
void _baked_light_changed();
|
void _baked_light_changed();
|
||||||
void _update_visibility();
|
void _update_visibility();
|
||||||
|
@ -132,6 +133,9 @@ public:
|
||||||
void set_baked_light_texture_id(int p_id);
|
void set_baked_light_texture_id(int p_id);
|
||||||
int get_baked_light_texture_id() const;
|
int get_baked_light_texture_id() const;
|
||||||
|
|
||||||
|
void set_extra_cull_margin(float p_margin);
|
||||||
|
float get_extra_cull_margin() const;
|
||||||
|
|
||||||
GeometryInstance();
|
GeometryInstance();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
#include "scene/2d/particles_2d.h"
|
#include "scene/2d/particles_2d.h"
|
||||||
#include "scene/2d/path_2d.h"
|
#include "scene/2d/path_2d.h"
|
||||||
#include "scene/2d/light_2d.h"
|
#include "scene/2d/light_2d.h"
|
||||||
|
#include "scene/2d/light_occluder_2d.h"
|
||||||
|
|
||||||
#include "scene/2d/canvas_item.h"
|
#include "scene/2d/canvas_item.h"
|
||||||
#include "scene/2d/sprite.h"
|
#include "scene/2d/sprite.h"
|
||||||
|
@ -454,6 +455,7 @@ void register_scene_types() {
|
||||||
//ObjectTypeDB::set_type_enabled("BodyVolumeCylinder",false);
|
//ObjectTypeDB::set_type_enabled("BodyVolumeCylinder",false);
|
||||||
//ObjectTypeDB::set_type_enabled("BodyVolumeConvexPolygon",false);
|
//ObjectTypeDB::set_type_enabled("BodyVolumeConvexPolygon",false);
|
||||||
|
|
||||||
|
ObjectTypeDB::register_type<CanvasItemMaterial>();
|
||||||
ObjectTypeDB::register_virtual_type<CanvasItem>();
|
ObjectTypeDB::register_virtual_type<CanvasItem>();
|
||||||
ObjectTypeDB::register_type<Node2D>();
|
ObjectTypeDB::register_type<Node2D>();
|
||||||
ObjectTypeDB::register_type<Particles2D>();
|
ObjectTypeDB::register_type<Particles2D>();
|
||||||
|
@ -476,6 +478,8 @@ void register_scene_types() {
|
||||||
ObjectTypeDB::register_type<VisibilityEnabler2D>();
|
ObjectTypeDB::register_type<VisibilityEnabler2D>();
|
||||||
ObjectTypeDB::register_type<Polygon2D>();
|
ObjectTypeDB::register_type<Polygon2D>();
|
||||||
ObjectTypeDB::register_type<Light2D>();
|
ObjectTypeDB::register_type<Light2D>();
|
||||||
|
ObjectTypeDB::register_type<LightOccluder2D>();
|
||||||
|
ObjectTypeDB::register_type<OccluderPolygon2D>();
|
||||||
ObjectTypeDB::register_type<YSort>();
|
ObjectTypeDB::register_type<YSort>();
|
||||||
|
|
||||||
ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
|
ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
|
||||||
|
|
|
@ -41,6 +41,7 @@ SceneStringNames::SceneStringNames() {
|
||||||
visibility_changed=StaticCString::create("visibility_changed");
|
visibility_changed=StaticCString::create("visibility_changed");
|
||||||
input_event=StaticCString::create("input_event");
|
input_event=StaticCString::create("input_event");
|
||||||
shader_shader=StaticCString::create("shader/shader");
|
shader_shader=StaticCString::create("shader/shader");
|
||||||
|
shader_unshaded=StaticCString::create("shader/unshaded");
|
||||||
enter_tree=StaticCString::create("enter_tree");
|
enter_tree=StaticCString::create("enter_tree");
|
||||||
exit_tree=StaticCString::create("exit_tree");
|
exit_tree=StaticCString::create("exit_tree");
|
||||||
item_rect_changed=StaticCString::create("item_rect_changed");
|
item_rect_changed=StaticCString::create("item_rect_changed");
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
StringName _input_event;
|
StringName _input_event;
|
||||||
StringName item_rect_changed;
|
StringName item_rect_changed;
|
||||||
StringName shader_shader;
|
StringName shader_shader;
|
||||||
|
StringName shader_unshaded;
|
||||||
StringName enter_tree;
|
StringName enter_tree;
|
||||||
StringName exit_tree;
|
StringName exit_tree;
|
||||||
StringName size_flags_changed;
|
StringName size_flags_changed;
|
||||||
|
|
|
@ -572,8 +572,8 @@ public:
|
||||||
struct CanvasLight {
|
struct CanvasLight {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool shadow;
|
|
||||||
Color color;
|
Color color;
|
||||||
Matrix32 xform;
|
Matrix32 xform;
|
||||||
float height;
|
float height;
|
||||||
|
@ -586,21 +586,26 @@ public:
|
||||||
RID texture;
|
RID texture;
|
||||||
Vector2 texture_offset;
|
Vector2 texture_offset;
|
||||||
RID canvas;
|
RID canvas;
|
||||||
|
RID shadow_buffer;
|
||||||
|
int shadow_buffer_size;
|
||||||
|
float shadow_esm_mult;
|
||||||
|
|
||||||
|
|
||||||
void *texture_cache; // implementation dependent
|
void *texture_cache; // implementation dependent
|
||||||
Rect2 rect_cache;
|
Rect2 rect_cache;
|
||||||
Matrix32 xform_cache;
|
Matrix32 xform_cache;
|
||||||
|
float radius_cache; //used for shadow far plane
|
||||||
|
CameraMatrix shadow_matrix_cache;
|
||||||
|
|
||||||
Matrix32 light_shader_xform;
|
Matrix32 light_shader_xform;
|
||||||
Vector2 light_shader_pos;
|
Vector2 light_shader_pos;
|
||||||
|
|
||||||
|
CanvasLight *shadows_next_ptr;
|
||||||
CanvasLight *filter_next_ptr;
|
CanvasLight *filter_next_ptr;
|
||||||
CanvasLight *next_ptr;
|
CanvasLight *next_ptr;
|
||||||
|
|
||||||
CanvasLight() {
|
CanvasLight() {
|
||||||
enabled=true;
|
enabled=true;
|
||||||
shadow=false;
|
|
||||||
color=Color(1,1,1);
|
color=Color(1,1,1);
|
||||||
height=0;
|
height=0;
|
||||||
z_min=-1024;
|
z_min=-1024;
|
||||||
|
@ -612,9 +617,24 @@ public:
|
||||||
texture_cache=NULL;
|
texture_cache=NULL;
|
||||||
next_ptr=NULL;
|
next_ptr=NULL;
|
||||||
filter_next_ptr=NULL;
|
filter_next_ptr=NULL;
|
||||||
|
shadow_buffer_size=2048;
|
||||||
|
shadow_esm_mult=80;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CanvasItem;
|
||||||
|
|
||||||
|
struct CanvasItemMaterial {
|
||||||
|
|
||||||
|
RID shader;
|
||||||
|
Map<StringName,Variant> shader_param;
|
||||||
|
uint32_t shader_version;
|
||||||
|
Set<CanvasItem*> owners;
|
||||||
|
bool unshaded;
|
||||||
|
|
||||||
|
CanvasItemMaterial() {unshaded=false; shader_version=0; }
|
||||||
|
};
|
||||||
|
|
||||||
struct CanvasItem {
|
struct CanvasItem {
|
||||||
|
|
||||||
|
@ -744,16 +764,14 @@ public:
|
||||||
mutable bool rect_dirty;
|
mutable bool rect_dirty;
|
||||||
mutable Rect2 rect;
|
mutable Rect2 rect;
|
||||||
CanvasItem*next;
|
CanvasItem*next;
|
||||||
RID shader;
|
CanvasItemMaterial* material;
|
||||||
Map<StringName,Variant> shader_param;
|
|
||||||
uint32_t shader_version;
|
|
||||||
|
|
||||||
|
|
||||||
float final_opacity;
|
float final_opacity;
|
||||||
Matrix32 final_transform;
|
Matrix32 final_transform;
|
||||||
Rect2 final_clip_rect;
|
Rect2 final_clip_rect;
|
||||||
CanvasItem* final_clip_owner;
|
CanvasItem* final_clip_owner;
|
||||||
CanvasItem* shader_owner;
|
CanvasItem* material_owner;
|
||||||
ViewportRender *vp_render;
|
ViewportRender *vp_render;
|
||||||
|
|
||||||
Rect2 global_rect_cache;
|
Rect2 global_rect_cache;
|
||||||
|
@ -881,8 +899,8 @@ public:
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; shader_owner=NULL;}
|
void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL;}
|
||||||
CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; shader_version=0; shader_owner=NULL;}
|
CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; }
|
||||||
virtual ~CanvasItem() { clear(); }
|
virtual ~CanvasItem() { clear(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -905,7 +923,36 @@ public:
|
||||||
virtual void canvas_set_transform(const Matrix32& p_transform)=0;
|
virtual void canvas_set_transform(const Matrix32& p_transform)=0;
|
||||||
|
|
||||||
virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0;
|
virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0;
|
||||||
|
virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow)=0;
|
||||||
|
/* LIGHT SHADOW MAPPING */
|
||||||
|
|
||||||
|
virtual RID canvas_light_occluder_create()=0;
|
||||||
|
virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& 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 */
|
/* ENVIRONMENT */
|
||||||
|
|
||||||
|
@ -945,6 +992,8 @@ public:
|
||||||
virtual bool is_environment(const RID& p_rid) const=0;
|
virtual bool is_environment(const RID& p_rid) const=0;
|
||||||
virtual bool is_shader(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 free(const RID& p_rid)=0;
|
||||||
|
|
||||||
virtual void init()=0;
|
virtual void init()=0;
|
||||||
|
|
|
@ -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;
|
VS_CHANGED;
|
||||||
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
|
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
|
||||||
ERR_FAIL_COND(!canvas_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;
|
VS_CHANGED;
|
||||||
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
|
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
|
||||||
ERR_FAIL_COND(!canvas_item);
|
ERR_FAIL_COND(!canvas_item);
|
||||||
canvas_item->shader=p_shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
RID VisualServerRaster::canvas_item_get_shader(RID p_item) const{
|
if (canvas_item->material)
|
||||||
|
canvas_item->material->owners.erase(canvas_item);
|
||||||
|
|
||||||
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
|
canvas_item->material=NULL;
|
||||||
ERR_FAIL_COND_V(!canvas_item,RID());
|
|
||||||
return canvas_item->shader;
|
|
||||||
|
|
||||||
}
|
if (canvas_item_material_owner.owns(p_material)) {
|
||||||
|
canvas_item->material=canvas_item_material_owner.get(p_material);
|
||||||
void VisualServerRaster::canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value){
|
canvas_item->material->owners.insert(canvas_item);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return canvas_item->shader_param[p_param];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
|
void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
|
||||||
|
|
||||||
VS_CHANGED;
|
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);
|
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
|
||||||
ERR_FAIL_COND(!clight);
|
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){
|
void VisualServerRaster::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){
|
||||||
|
|
||||||
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
|
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
|
||||||
ERR_FAIL_COND(!clight);
|
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);
|
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
|
||||||
ERR_FAIL_COND(!clight);
|
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() {
|
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) {
|
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){
|
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<Vector2>& 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<Vector2>& p_shape, bool p_close){
|
||||||
|
|
||||||
|
if (p_shape.size()<3) {
|
||||||
|
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DVector<Vector2> lines;
|
||||||
|
int lc = p_shape.size()*2;
|
||||||
|
|
||||||
|
lines.resize(lc-(p_close?0:2));
|
||||||
|
{
|
||||||
|
DVector<Vector2>::Write w = lines.write();
|
||||||
|
DVector<Vector2>::Read r = p_shape.read();
|
||||||
|
|
||||||
|
int max=lc/2;
|
||||||
|
if (!p_close) {
|
||||||
|
max--;
|
||||||
|
}
|
||||||
|
for(int i=0;i<max;i++) {
|
||||||
|
|
||||||
|
Vector2 a = r[i];
|
||||||
|
Vector2 b = r[(i+1)%(lc/2)];
|
||||||
|
w[i*2+0]=a;
|
||||||
|
w[i*2+1]=b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& 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<Vector2>::Read r = p_shape.read();
|
||||||
|
for(int i=0;i<lc;i++) {
|
||||||
|
if (i==0)
|
||||||
|
occluder_poly->aabb.pos=r[i];
|
||||||
|
else
|
||||||
|
occluder_poly->aabb.expand_to(r[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rasterizer->canvas_light_occluder_set_polylines(occluder_poly->occluder,p_shape);
|
||||||
|
for( Set<Rasterizer::CanvasLightOccluderInstance*>::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<Rasterizer::CanvasLightOccluderInstance*>::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 *********/
|
/******** CANVAS *********/
|
||||||
|
|
||||||
|
|
||||||
|
@ -4285,6 +4475,10 @@ void VisualServerRaster::free( RID p_rid ) {
|
||||||
E->get()->canvas=RID();
|
E->get()->canvas=RID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
E->get()->canvas=RID();
|
||||||
|
}
|
||||||
|
|
||||||
canvas_owner.free( p_rid );
|
canvas_owner.free( p_rid );
|
||||||
|
|
||||||
|
@ -4314,10 +4508,26 @@ void VisualServerRaster::free( RID p_rid ) {
|
||||||
canvas_item->child_items[i]->parent=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 );
|
canvas_item_owner.free( p_rid );
|
||||||
|
|
||||||
memdelete( canvas_item );
|
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<Rasterizer::CanvasItem*>::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)) {
|
} else if (canvas_light_owner.owns(p_rid)) {
|
||||||
|
|
||||||
Rasterizer::CanvasLight *canvas_light = canvas_light_owner.get(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);
|
canvas->lights.erase(canvas_light);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (canvas_light->shadow_buffer.is_valid())
|
||||||
|
rasterizer->free(canvas_light->shadow_buffer);
|
||||||
|
|
||||||
canvas_light_owner.free( p_rid );
|
canvas_light_owner.free( p_rid );
|
||||||
memdelete( canvas_light );
|
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)) {
|
} else if (scenario_owner.owns(p_rid)) {
|
||||||
|
|
||||||
Scenario *scenario=scenario_owner.get(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;
|
CanvasItem *ci = p_canvas_item;
|
||||||
|
|
||||||
|
@ -6455,11 +6700,11 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
|
||||||
ci->vp_render=NULL;
|
ci->vp_render=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ci->use_parent_shader && p_shader_owner)
|
if (ci->use_parent_material && p_material_owner)
|
||||||
ci->shader_owner=p_shader_owner;
|
ci->material_owner=p_material_owner;
|
||||||
else {
|
else {
|
||||||
p_shader_owner=ci;
|
p_material_owner=ci;
|
||||||
ci->shader_owner=NULL;
|
ci->material_owner=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6493,7 +6738,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
|
||||||
|
|
||||||
if (child_items[i]->ontop)
|
if (child_items[i]->ontop)
|
||||||
continue;
|
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)
|
if (!child_items[i]->ontop)
|
||||||
continue;
|
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);
|
Rect2 clip_rect(0,0,viewport_rect.width,viewport_rect.height);
|
||||||
Rasterizer::CanvasLight *lights=NULL;
|
Rasterizer::CanvasLight *lights=NULL;
|
||||||
|
Rasterizer::CanvasLight *lights_with_shadow=NULL;
|
||||||
|
Rect2 shadow_rect;
|
||||||
|
|
||||||
for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
|
for (Map<RID,Viewport::CanvasData>::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->rect_cache=Rect2(-offset+cl->texture_offset,tsize);
|
||||||
cl->xform_cache=xf * cl->xform;
|
cl->xform_cache=xf * cl->xform;
|
||||||
|
|
||||||
|
|
||||||
if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) {
|
if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) {
|
||||||
cl->filter_next_ptr=lights;
|
cl->filter_next_ptr=lights;
|
||||||
lights=cl;
|
lights=cl;
|
||||||
|
@ -6685,11 +6933,18 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
|
||||||
scale.elements[2]=cl->rect_cache.pos;
|
scale.elements[2]=cl->rect_cache.pos;
|
||||||
cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse();
|
cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse();
|
||||||
cl->light_shader_pos=cl->xform_cache[2];
|
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();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6697,6 +6952,38 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lights_with_shadow) {
|
||||||
|
//update shadows if any
|
||||||
|
|
||||||
|
Rasterizer::CanvasLightOccluderInstance * occluders=NULL;
|
||||||
|
|
||||||
|
//make list of occluders
|
||||||
|
for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
Matrix32 xf = p_viewport->global_transform * E->get().transform;
|
||||||
|
|
||||||
|
for(Set<Rasterizer::CanvasLightOccluderInstance*>::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) {
|
||||||
|
|
||||||
|
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<Viewport::CanvasKey,Viewport::CanvasData*>::Element *E=canvas_map.front();E;E=E->next()) {
|
for (Map<Viewport::CanvasKey,Viewport::CanvasData*>::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++;
|
i++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
//capture
|
//capture
|
||||||
|
|
|
@ -371,7 +371,7 @@ class VisualServerRaster : public VisualServer {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mutable RID_Owner<Rasterizer::CanvasItemMaterial> canvas_item_material_owner;
|
||||||
|
|
||||||
struct CanvasItem : public Rasterizer::CanvasItem {
|
struct CanvasItem : public Rasterizer::CanvasItem {
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ class VisualServerRaster : public VisualServer {
|
||||||
bool sort_y;
|
bool sort_y;
|
||||||
float opacity;
|
float opacity;
|
||||||
float self_opacity;
|
float self_opacity;
|
||||||
bool use_parent_shader;
|
bool use_parent_material;
|
||||||
|
|
||||||
|
|
||||||
Vector<CanvasItem*> child_items;
|
Vector<CanvasItem*> child_items;
|
||||||
|
@ -396,7 +396,7 @@ class VisualServerRaster : public VisualServer {
|
||||||
opacity=1;
|
opacity=1;
|
||||||
self_opacity=1;
|
self_opacity=1;
|
||||||
sort_y=false;
|
sort_y=false;
|
||||||
use_parent_shader=false;
|
use_parent_material=false;
|
||||||
z_relative=true;
|
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<Rasterizer::CanvasLightOccluderInstance*> owners;
|
||||||
|
|
||||||
|
CanvasLightOccluderPolygon() { active=false; cull_mode=CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
RID_Owner<CanvasLightOccluderPolygon> canvas_light_occluder_polygon_owner;
|
||||||
|
|
||||||
|
RID_Owner<Rasterizer::CanvasLightOccluderInstance> canvas_light_occluder_owner;
|
||||||
|
|
||||||
struct CanvasLight;
|
struct CanvasLight;
|
||||||
|
|
||||||
struct Canvas {
|
struct Canvas {
|
||||||
|
@ -422,6 +440,7 @@ class VisualServerRaster : public VisualServer {
|
||||||
};
|
};
|
||||||
|
|
||||||
Set<Rasterizer::CanvasLight*> lights;
|
Set<Rasterizer::CanvasLight*> lights;
|
||||||
|
Set<Rasterizer::CanvasLightOccluderInstance*> occluders;
|
||||||
|
|
||||||
Vector<ChildItem> child_items;
|
Vector<ChildItem> child_items;
|
||||||
Color modulate;
|
Color modulate;
|
||||||
|
@ -610,7 +629,7 @@ class VisualServerRaster : public VisualServer {
|
||||||
void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
|
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);
|
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_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);
|
void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights);
|
||||||
Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
|
Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
|
||||||
Vector<Plane> _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
|
Vector<Plane> _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(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_z_as_relative_to_parent(RID p_item, bool p_enable);
|
||||||
|
|
||||||
virtual void canvas_item_set_shader(RID p_item, RID p_shader);
|
virtual void canvas_item_set_material(RID p_item, RID p_material);
|
||||||
virtual RID canvas_item_get_shader(RID p_item) const;
|
virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
|
||||||
|
|
||||||
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 RID canvas_light_create();
|
virtual RID canvas_light_create();
|
||||||
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas);
|
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_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_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_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 RID canvas_light_occluder_create();
|
||||||
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas);
|
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_enabled(RID p_occluder,bool p_enabled);
|
||||||
virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& 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<Vector2>& p_shape,bool p_close);
|
||||||
|
virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& 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_clear(RID p_item);
|
||||||
virtual void canvas_item_raise(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 */
|
/* CURSOR */
|
||||||
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians
|
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);
|
virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor=0);
|
||||||
|
|
|
@ -1139,14 +1139,9 @@ public:
|
||||||
FUNC2(canvas_item_set_z,RID,int);
|
FUNC2(canvas_item_set_z,RID,int);
|
||||||
FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool);
|
FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool);
|
||||||
|
|
||||||
FUNC2(canvas_item_set_shader,RID, RID );
|
FUNC2(canvas_item_set_material,RID, RID );
|
||||||
FUNC1RC(RID,canvas_item_get_shader,RID );
|
|
||||||
|
|
||||||
FUNC2(canvas_item_set_use_parent_shader,RID, bool );
|
FUNC2(canvas_item_set_use_parent_material,RID, bool );
|
||||||
|
|
||||||
|
|
||||||
FUNC3(canvas_item_set_shader_param,RID,const StringName&,const Variant&);
|
|
||||||
FUNC2RC(Variant,canvas_item_get_shader_param,RID,const StringName&);
|
|
||||||
|
|
||||||
FUNC1(canvas_item_clear,RID);
|
FUNC1(canvas_item_clear,RID);
|
||||||
FUNC1(canvas_item_raise,RID);
|
FUNC1(canvas_item_raise,RID);
|
||||||
|
@ -1167,14 +1162,31 @@ public:
|
||||||
FUNC2(canvas_light_set_subtract_mode,RID,bool);
|
FUNC2(canvas_light_set_subtract_mode,RID,bool);
|
||||||
FUNC2(canvas_light_set_shadow_enabled,RID,bool);
|
FUNC2(canvas_light_set_shadow_enabled,RID,bool);
|
||||||
FUNC2(canvas_light_set_shadow_buffer_size,RID,int);
|
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 */
|
/* CANVAS OCCLUDER */
|
||||||
|
|
||||||
FUNC0R(RID,canvas_light_occluder_create);
|
FUNC0R(RID,canvas_light_occluder_create);
|
||||||
FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID);
|
FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID);
|
||||||
FUNC2(canvas_light_occluder_set_enabled,RID,bool);
|
FUNC2(canvas_light_occluder_set_enabled,RID,bool);
|
||||||
FUNC2(canvas_light_occluder_set_shape,RID,const DVector<Vector2>&);
|
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<Vector2>&,bool);
|
||||||
|
FUNC2(canvas_occluder_polygon_set_shape_as_lines,RID,const DVector<Vector2>&);
|
||||||
|
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 */
|
/* CURSOR */
|
||||||
FUNC2(cursor_set_rotation,float , int ); // radians
|
FUNC2(cursor_set_rotation,float , int ); // radians
|
||||||
|
|
|
@ -998,13 +998,9 @@ public:
|
||||||
virtual void canvas_item_clear(RID p_item)=0;
|
virtual void canvas_item_clear(RID p_item)=0;
|
||||||
virtual void canvas_item_raise(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 void canvas_item_set_material(RID p_item, RID p_material)=0;
|
||||||
virtual RID canvas_item_get_shader(RID p_item) const=0;
|
|
||||||
|
|
||||||
virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable)=0;
|
virtual void canvas_item_set_use_parent_material(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 RID canvas_light_create()=0;
|
virtual RID canvas_light_create()=0;
|
||||||
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas)=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_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_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_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 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_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_enabled(RID p_occluder,bool p_enabled)=0;
|
||||||
virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& 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<Vector2>& p_shape,bool p_closed)=0;
|
||||||
|
virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& 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 */
|
/* CURSOR */
|
||||||
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians
|
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
#include "plugins/baked_light_editor_plugin.h"
|
#include "plugins/baked_light_editor_plugin.h"
|
||||||
#include "plugins/polygon_2d_editor_plugin.h"
|
#include "plugins/polygon_2d_editor_plugin.h"
|
||||||
#include "plugins/navigation_polygon_editor_plugin.h"
|
#include "plugins/navigation_polygon_editor_plugin.h"
|
||||||
|
#include "plugins/light_occluder_2d_editor_plugin.h"
|
||||||
// end
|
// end
|
||||||
#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
|
#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
|
||||||
#include "tools/editor/io_plugins/editor_scene_import_plugin.h"
|
#include "tools/editor/io_plugins/editor_scene_import_plugin.h"
|
||||||
|
@ -4115,6 +4116,7 @@ EditorNode::EditorNode() {
|
||||||
add_editor_plugin( memnew( PathEditorPlugin(this) ) );
|
add_editor_plugin( memnew( PathEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) );
|
add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) );
|
add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) );
|
||||||
|
add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) );
|
add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) );
|
||||||
|
|
||||||
for(int i=0;i<EditorPlugins::get_plugin_count();i++)
|
for(int i=0;i<EditorPlugins::get_plugin_count();i++)
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 835 B |
Binary file not shown.
After Width: | Height: | Size: 441 B |
Binary file not shown.
After Width: | Height: | Size: 516 B |
Binary file not shown.
After Width: | Height: | Size: 581 B |
|
@ -4,6 +4,7 @@
|
||||||
#include "os/file_access.h"
|
#include "os/file_access.h"
|
||||||
#include "tools/editor/editor_settings.h"
|
#include "tools/editor/editor_settings.h"
|
||||||
|
|
||||||
|
|
||||||
void CollisionPolygon2DEditor::_notification(int p_what) {
|
void CollisionPolygon2DEditor::_notification(int p_what) {
|
||||||
|
|
||||||
switch(p_what) {
|
switch(p_what) {
|
||||||
|
|
|
@ -0,0 +1,500 @@
|
||||||
|
#include "light_occluder_2d_editor_plugin.h"
|
||||||
|
|
||||||
|
#include "canvas_item_editor_plugin.h"
|
||||||
|
#include "os/file_access.h"
|
||||||
|
#include "tools/editor/editor_settings.h"
|
||||||
|
|
||||||
|
void LightOccluder2DEditor::_notification(int p_what) {
|
||||||
|
|
||||||
|
switch(p_what) {
|
||||||
|
|
||||||
|
case NOTIFICATION_READY: {
|
||||||
|
|
||||||
|
button_create->set_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<Vector2> 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)<grab_treshold) {
|
||||||
|
//wip closed
|
||||||
|
_wip_close(true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (wip.size()>1 && xform.xform(wip[wip.size()-1]).distance_to(gpoint)<grab_treshold) {
|
||||||
|
//wip closed
|
||||||
|
_wip_close(false);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
wip.push_back( cpoint );
|
||||||
|
edited_point=wip.size();
|
||||||
|
canvas_item_editor->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<poly.size();i++) {
|
||||||
|
|
||||||
|
Vector2 points[2] ={ xform.xform(poly[i]),
|
||||||
|
xform.xform(poly[(i+1)%poly.size()]) };
|
||||||
|
|
||||||
|
Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
|
||||||
|
if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
|
||||||
|
continue; //not valid to reuse point
|
||||||
|
|
||||||
|
real_t d = cp.distance_to(gpoint);
|
||||||
|
if (d<closest_dist && d<grab_treshold) {
|
||||||
|
closest_dist=d;
|
||||||
|
closest_pos=cp;
|
||||||
|
closest_idx=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest_idx>=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<poly.size();i++) {
|
||||||
|
|
||||||
|
Vector2 cp =xform.xform(poly[i]);
|
||||||
|
|
||||||
|
real_t d = cp.distance_to(gpoint);
|
||||||
|
if (d<closest_dist && d<grab_treshold) {
|
||||||
|
closest_dist=d;
|
||||||
|
closest_pos=cp;
|
||||||
|
closest_idx=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest_idx>=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<poly.size();i++) {
|
||||||
|
|
||||||
|
Vector2 cp =xform.xform(poly[i]);
|
||||||
|
|
||||||
|
real_t d = cp.distance_to(gpoint);
|
||||||
|
if (d<closest_dist && d<grab_treshold) {
|
||||||
|
closest_dist=d;
|
||||||
|
closest_pos=cp;
|
||||||
|
closest_idx=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest_idx>=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<Vector2> 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<Texture> handle= get_icon("EditorHandle","EditorIcons");
|
||||||
|
|
||||||
|
int len = poly.size();
|
||||||
|
|
||||||
|
for(int i=0;i<poly.size();i++) {
|
||||||
|
|
||||||
|
|
||||||
|
Vector2 p,p2;
|
||||||
|
p = i==edited_point ? edited_point_pos : poly[i];
|
||||||
|
if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
|
||||||
|
p2=edited_point_pos;
|
||||||
|
else
|
||||||
|
p2 = poly[(i+1)%poly.size()];
|
||||||
|
|
||||||
|
Vector2 point = xform.xform(p);
|
||||||
|
Vector2 next_point = xform.xform(p2);
|
||||||
|
|
||||||
|
Color col=Color(1,0.3,0.1,0.8);
|
||||||
|
|
||||||
|
if (i==poly.size()-1 && (!node->get_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<LightOccluder2D>();
|
||||||
|
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<OccluderPolygon2D>(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<Node>());
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -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 <reduzio@gmail.com>
|
||||||
|
*/
|
||||||
|
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<Vector2> pre_move_edit;
|
||||||
|
Vector<Vector2> 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
|
|
@ -1857,8 +1857,33 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p
|
||||||
} else {
|
} else {
|
||||||
p_item->set_text(1,"<"+res->get_type()+">");
|
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;
|
} break;
|
||||||
default: {};
|
default: {};
|
||||||
}
|
}
|
||||||
|
@ -2529,7 +2554,10 @@ void PropertyEditor::update_tree() {
|
||||||
item->set_editable( 1, !read_only );
|
item->set_editable( 1, !read_only );
|
||||||
item->add_button(1,get_icon("EditResource","EditorIcons"));
|
item->add_button(1,get_icon("EditResource","EditorIcons"));
|
||||||
String type;
|
String type;
|
||||||
|
if (p.hint==PROPERTY_HINT_RESOURCE_TYPE)
|
||||||
|
type=p.hint_string;
|
||||||
bool notnil=false;
|
bool notnil=false;
|
||||||
|
|
||||||
if (obj->get( p.name ).get_type() == Variant::NIL || obj->get( p.name ).operator RefPtr().is_null()) {
|
if (obj->get( p.name ).get_type() == Variant::NIL || obj->get( p.name ).operator RefPtr().is_null()) {
|
||||||
item->set_text(1,"<null>");
|
item->set_text(1,"<null>");
|
||||||
|
|
||||||
|
@ -2553,12 +2581,18 @@ void PropertyEditor::update_tree() {
|
||||||
};
|
};
|
||||||
notnil=true;
|
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());
|
//printf("prop %s , type %s\n",p.name.ascii().get_data(),p.hint_string.ascii().get_data());
|
||||||
if (has_icon(p.hint_string,"EditorIcons"))
|
if (has_icon(type,"EditorIcons"))
|
||||||
item->set_icon( 0, get_icon(p.hint_string,"EditorIcons") );
|
item->set_icon( 0, get_icon(type,"EditorIcons") );
|
||||||
else
|
else
|
||||||
item->set_icon( 0, get_icon("Object","EditorIcons") );
|
item->set_icon( 0, get_icon("Object","EditorIcons") );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue