From 2ef5a342e34df3863ac512bb3673eba28f15e9f4 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 13 Jan 2015 10:49:26 -0300 Subject: [PATCH] -begin work on unidirectional collision detection -fixed performance issue in new 2D engine -texscreen() working in shader 2D --- drivers/gles2/rasterizer_gles2.cpp | 23 ++++ drivers/gles2/shader_compiler_gles2.cpp | 2 +- drivers/gles2/shaders/canvas.glsl | 1 + drivers/gles2/shaders/material.glsl | 1 + scene/2d/node_2d.cpp | 28 ++++- scene/2d/node_2d.h | 3 + scene/2d/physics_body_2d.cpp | 15 +++ scene/2d/physics_body_2d.h | 4 + scene/3d/physics_body.cpp | 1 + scene/3d/physics_body.h | 2 + servers/physics_2d/body_2d_sw.h | 5 + servers/physics_2d/physics_2d_server_sw.cpp | 16 +++ servers/physics_2d/physics_2d_server_sw.h | 3 + servers/physics_2d_server.cpp | 4 + servers/physics_2d_server.h | 3 + servers/visual/visual_server_raster.cpp | 111 ++++++++++++++------ servers/visual/visual_server_raster.h | 5 +- servers/visual/visual_server_wrap_mt.h | 1 + servers/visual_server.h | 6 +- 19 files changed, 194 insertions(+), 40 deletions(-) diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 44fb210526a..9375532f072 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -5141,6 +5141,7 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material if (p_material->shader_cache->has_texscreen && framebuffer.active) { material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); + material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(0,0,float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_TEX,texcoord); glActiveTexture(GL_TEXTURE0+texcoord); glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); @@ -8387,11 +8388,32 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { if (shader->has_texscreen && framebuffer.active) { + + int x = viewport.x; + int y = window_size.height-(viewport.height+viewport.y); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(float(x)/framebuffer.width,float(y)/framebuffer.height,float(x+viewport.width)/framebuffer.width,float(y+viewport.height)/framebuffer.height)); canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_TEX,tex_id); glActiveTexture(GL_TEXTURE0+tex_id); glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); + if (framebuffer.scale==1 && !canvas_texscreen_used) { +#ifdef GLEW_ENABLED + glReadBuffer(GL_COLOR_ATTACHMENT0); +#endif + glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height); + if (current_clip) { + print_line(" a clip "); + } + canvas_texscreen_used=true; + } + tex_id++; + + } + + if (tex_id>1) { + glActiveTexture(GL_TEXTURE0); } if (shader->has_screen_uv) { canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height)); @@ -8412,6 +8434,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { } + canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform); canvas_last_shader=shader_owner->shader; } diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 93b0ecc61f4..4d9563a82b0 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -404,7 +404,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } else if (callfunc=="texscreen") { //create the call to sample the screen, and clamp it uses_texscreen=true; - code="(texture2D( texscreen_tex, min(("+dump_node_code(onode->arguments[1],p_level)+").xy*texscreen_screen_mult,texscreen_screen_mult))).rgb"; + code="(texture2D( texscreen_tex, clamp(("+dump_node_code(onode->arguments[1],p_level)+").xy*texscreen_screen_mult,texscreen_screen_clamp.xy,texscreen_screen_clamp.zw))).rgb"; //code="(texture2D( screen_texture, ("+dump_node_code(onode->arguments[1],p_level)+").xy).rgb"; break; } else if (callfunc=="texpos") { diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 4ec601f0fcb..464cb9e1885 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -100,6 +100,7 @@ uniform vec2 screen_uv_mult; #if defined(ENABLE_TEXSCREEN) uniform vec2 texscreen_screen_mult; +uniform vec4 texscreen_screen_clamp; uniform sampler2D texscreen_tex; #endif diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index 718dd56249e..38fb03ab5c8 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -779,6 +779,7 @@ uniform highp mat4 camera_inverse_transform; #if defined(ENABLE_TEXSCREEN) uniform vec2 texscreen_screen_mult; +uniform vec4 texscreen_screen_clamp; uniform sampler2D texscreen_tex; #endif diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index b9041e1224e..8b4196ee7f4 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -291,13 +291,27 @@ void Node2D::set_global_transform(const Matrix32& p_transform) { void Node2D::set_z(int p_z) { - ERR_FAIL_COND(p_z<-VS::CANVAS_ITEM_Z_DEFAULT); - ERR_FAIL_COND(p_z>=VS::CANVAS_ITEM_Z_DEFAULT); + ERR_FAIL_COND(p_zVS::CANVAS_ITEM_Z_MAX); z=p_z; - VS::get_singleton()->canvas_item_set_z(get_canvas_item(),z+VS::CANVAS_ITEM_Z_DEFAULT); + VS::get_singleton()->canvas_item_set_z(get_canvas_item(),z); } +void Node2D::set_z_as_relative(bool p_enabled) { + + if (z_relative==p_enabled) + return; + z_relative=p_enabled; + VS::get_singleton()->canvas_item_set_z_as_relative_to_parent(get_canvas_item(),p_enabled); +} + +bool Node2D::is_z_relative() const { + + return z_relative; +} + + int Node2D::get_z() const{ return z; @@ -332,13 +346,16 @@ void Node2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_z","z"),&Node2D::set_z); ObjectTypeDB::bind_method(_MD("get_z"),&Node2D::get_z); + ObjectTypeDB::bind_method(_MD("set_z_as_relative","enable"),&Node2D::set_z_as_relative); + ObjectTypeDB::bind_method(_MD("is_z_relative"),&Node2D::is_z_relative); + ObjectTypeDB::bind_method(_MD("edit_set_pivot"),&Node2D::edit_set_pivot); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/pos"),_SCS("set_pos"),_SCS("get_pos")); ADD_PROPERTY(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_rotd"),_SCS("_get_rotd")); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/scale"),_SCS("set_scale"),_SCS("get_scale")); - ADD_PROPERTY(PropertyInfo(Variant::INT,"visibility/z",PROPERTY_HINT_RANGE,"-512,511,1"),_SCS("set_z"),_SCS("get_z")); - + ADD_PROPERTY(PropertyInfo(Variant::INT,"z/z",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z"),_SCS("get_z")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"z/relative"),_SCS("set_z_as_relative"),_SCS("is_z_relative")); } @@ -351,6 +368,7 @@ Node2D::Node2D() { scale=Vector2(1,1); _xform_dirty=false; z=0; + z_relative=true; } diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 63ca2e3b95a..61b8c829d66 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -39,6 +39,7 @@ class Node2D : public CanvasItem { float angle; Size2 scale; int z; + bool z_relative; Matrix32 _mat; @@ -89,6 +90,8 @@ public: void set_z(int p_z); int get_z() const; + void set_z_as_relative(bool p_enabled); + bool is_z_relative() const; Matrix32 get_transform() const; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 2413fbded1f..37681e1b81d 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -43,13 +43,28 @@ void PhysicsBody2D::_notification(int p_what) { */ } +void PhysicsBody2D::set_one_way_collision_direction(const Vector2& p_dir) { + + one_way_collision_direction=p_dir; + Physics2DServer::get_singleton()->body_set_one_way_collision_direction(get_rid(),p_dir); +} + +Vector2 PhysicsBody2D::get_one_way_collision_direction() const{ + + return one_way_collision_direction; +} + + void PhysicsBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&PhysicsBody2D::set_layer_mask); ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsBody2D::get_layer_mask); + ObjectTypeDB::bind_method(_MD("set_one_way_collision_direction","dir"),&PhysicsBody2D::set_one_way_collision_direction); + ObjectTypeDB::bind_method(_MD("get_one_way_collision_direction"),&PhysicsBody2D::get_one_way_collision_direction); ObjectTypeDB::bind_method(_MD("add_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::add_collision_exception_with); ObjectTypeDB::bind_method(_MD("remove_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::remove_collision_exception_with); ADD_PROPERTY(PropertyInfo(Variant::INT,"layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"one_way_collision/direction"),_SCS("set_one_way_collision_direction"),_SCS("get_one_way_collision_direction")); } void PhysicsBody2D::set_layer_mask(uint32_t p_mask) { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 956999ce317..f88b89f34f4 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -39,6 +39,7 @@ class PhysicsBody2D : public CollisionObject2D { OBJ_TYPE(PhysicsBody2D,CollisionObject2D); uint32_t mask; + Vector2 one_way_collision_direction; protected: void _notification(int p_what); @@ -53,6 +54,9 @@ public: void add_collision_exception_with(Node* p_node); //must be physicsbody void remove_collision_exception_with(Node* p_node); + void set_one_way_collision_direction(const Vector2& p_dir); + Vector2 get_one_way_collision_direction() const; + PhysicsBody2D(); }; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index f2806f2af29..940a29b5d8a 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -92,6 +92,7 @@ void PhysicsBody::remove_collision_exception_with(Node* p_node) { PhysicsServer::get_singleton()->body_remove_collision_exception(get_rid(),physics_body->get_rid()); } + void PhysicsBody::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&PhysicsBody::set_layer_mask); ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsBody::get_layer_mask); diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 0d1de7f2366..beec01ff3aa 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -56,6 +56,8 @@ public: void add_collision_exception_with(Node* p_node); //must be physicsbody void remove_collision_exception_with(Node* p_node); + + PhysicsBody(); }; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 5bd68ba976c..8a1415da62b 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -67,6 +67,8 @@ class Body2DSW : public CollisionObject2DSW { Vector2 applied_force; real_t applied_torque; + Vector2 one_way_collision_direction; + SelfList active_list; SelfList inertia_update_list; @@ -216,6 +218,9 @@ public: _FORCE_INLINE_ void set_continuous_collision_detection_mode(Physics2DServer::CCDMode p_mode) { continuous_cd_mode=p_mode; } _FORCE_INLINE_ Physics2DServer::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } + void set_one_way_collision_direction(const Vector2& p_dir) { one_way_collision_direction=p_dir; } + Vector2 get_one_way_collision_direction() const { return one_way_collision_direction; } + void set_space(Space2DSW *p_space); void update_inertias(); diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index ab85f5e1d6e..f310ee0d9f6 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -860,6 +860,22 @@ int Physics2DServerSW::body_get_max_contacts_reported(RID p_body) const { return body->get_max_contacts_reported(); } +void Physics2DServerSW::body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_one_way_collision_direction(p_direction); +} + +Vector2 Physics2DServerSW::body_get_one_way_collision_direction(RID p_body) const{ + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,Vector2()); + return body->get_one_way_collision_direction(); + +} + + void Physics2DServerSW::body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata) { diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 9edd4eee115..b56c6da19aa 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -205,6 +205,9 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts); virtual int body_get_max_contacts_reported(RID p_body) const; + virtual void body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction); + virtual Vector2 body_get_one_way_collision_direction(RID p_body) const; + virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant()); virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count); diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 3633efc5eb0..6e6fae56b1f 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -500,6 +500,10 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported); ObjectTypeDB::bind_method(_MD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported); + ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_direction","normal"),&Physics2DServer::body_set_one_way_collision_direction); + ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_direction"),&Physics2DServer::body_get_one_way_collision_direction); + + ObjectTypeDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration); ObjectTypeDB::bind_method(_MD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 6e53cde55cb..008b25e7d7f 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -442,6 +442,9 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts)=0; virtual int body_get_max_contacts_reported(RID p_body) const=0; + virtual void body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction)=0; + virtual Vector2 body_get_one_way_collision_direction(RID p_body) const=0; + //missing remove virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold)=0; virtual float body_get_contacts_reported_depth_treshold(RID p_body) const=0; diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index dfa1e849b7d..dc0bff4cf4c 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -3691,7 +3691,7 @@ void VisualServerRaster::canvas_item_add_set_blend_mode(RID p_item, MaterialBlen void VisualServerRaster::canvas_item_set_z(RID p_item, int p_z) { - ERR_FAIL_COND(p_z<0 || p_z>=CANVAS_ITEM_Z_MAX); + ERR_FAIL_COND(p_zCANVAS_ITEM_Z_MAX); VS_CHANGED; CanvasItem *canvas_item = canvas_item_owner.get( p_item ); ERR_FAIL_COND(!canvas_item); @@ -3699,6 +3699,15 @@ void VisualServerRaster::canvas_item_set_z(RID p_item, int p_z) { } +void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->z_relative=p_enable; + +} + void VisualServerRaster::canvas_item_set_use_parent_shader(RID p_item, bool p_enable) { VS_CHANGED; @@ -6139,18 +6148,20 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S void VisualServerRaster::_render_canvas_item_tree(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect) { - Rasterizer::CanvasItem *z_list[CANVAS_ITEM_Z_MAX]; - Rasterizer::CanvasItem *z_last_list[CANVAS_ITEM_Z_MAX]; - for(int i=0;icanvas_render_items(z_list[i]); @@ -6168,7 +6179,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,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_shader_owner) { CanvasItem *ci = p_canvas_item; @@ -6247,7 +6258,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat if (child_items[i]->ontop) continue; - _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,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_shader_owner); } @@ -6256,13 +6267,20 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat ci->final_transform=xform; ci->final_opacity=opacity * ci->self_opacity; - if (z_last_list[ci->z]) { - z_last_list[ci->z]->next=ci; - z_last_list[ci->z]=ci; + if (ci->z_relative) + p_z=CLAMP(p_z+ci->z,CANVAS_ITEM_Z_MIN,CANVAS_ITEM_Z_MAX); + else + p_z=ci->z; + + int zidx = p_z-CANVAS_ITEM_Z_MIN; + + if (z_last_list[zidx]) { + z_last_list[zidx]->next=ci; + z_last_list[zidx]=ci; } else { - z_list[ci->z]=ci; - z_last_list[ci->z]=ci; + z_list[zidx]=ci; + z_last_list[zidx]=ci; } ci->next=NULL; @@ -6273,7 +6291,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat if (!child_items[i]->ontop) continue; - _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,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_shader_owner); } } @@ -6282,31 +6300,62 @@ void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_trans rasterizer->canvas_begin(); - int l = p_canvas->child_items.size(); + Canvas::ChildItem *ci=p_canvas->child_items.ptr(); + bool has_mirror=false; for(int i=0;ichild_items[i]; - _render_canvas_item_tree(ci.item,p_transform,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height)); - - //mirroring (useful for scrolling backgrounds) - if (ci.mirror.x!=0) { - - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); - _render_canvas_item_tree(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height)); + if (ci[i].mirror.x || ci[i].mirror.y) { + has_mirror=true; + break; } - if (ci.mirror.y!=0) { + } - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); - _render_canvas_item_tree(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height)); + Rect2 clip_rect(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height); + if (!has_mirror) { + + static const int z_range = CANVAS_ITEM_Z_MAX-CANVAS_ITEM_Z_MIN+1; + Rasterizer::CanvasItem *z_list[z_range]; + Rasterizer::CanvasItem *z_last_list[z_range]; + + for(int i=0;icanvas_render_items(z_list[i]); + } + } else { + + for(int i=0;ichild_items[i]; + _render_canvas_item_tree(ci.item,p_transform,clip_rect); + + //mirroring (useful for scrolling backgrounds) + if (ci.mirror.x!=0) { + + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); + _render_canvas_item_tree(ci.item,xform2,clip_rect); + } + if (ci.mirror.y!=0) { + + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); + _render_canvas_item_tree(ci.item,xform2,clip_rect); + } + if (ci.mirror.y!=0 && ci.mirror.x!=0) { + + Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror); + _render_canvas_item_tree(ci.item,xform2,clip_rect); + } + + } } } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index d30ac17400a..3fd8d7355be 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -380,6 +380,7 @@ class VisualServerRaster : public VisualServer { List::Element *E; RID viewport; int z; + bool z_relative; bool sort_y; float opacity; float self_opacity; @@ -396,6 +397,7 @@ class VisualServerRaster : public VisualServer { self_opacity=1; sort_y=false; use_parent_shader=false; + z_relative=true; } }; @@ -600,7 +602,7 @@ class VisualServerRaster : public VisualServer { void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect); void _render_canvas_item_tree(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect); - void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect,float p_opacity,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_shader_owner); void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform); Vector _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); Vector _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); @@ -1112,6 +1114,7 @@ public: virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); virtual void canvas_item_set_z(RID p_item, int p_z); + virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); virtual void canvas_item_set_shader(RID p_item, RID p_shader); virtual RID canvas_item_get_shader(RID p_item) const; diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index c3441614452..b59fdbc66a3 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -1132,6 +1132,7 @@ public: FUNC2(canvas_item_set_sort_children_by_y,RID,bool); FUNC2(canvas_item_set_z,RID,int); + FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool); FUNC2(canvas_item_set_shader,RID, RID ); FUNC1RC(RID,canvas_item_get_shader,RID ); diff --git a/servers/visual_server.h b/servers/visual_server.h index 5edf333e657..5721e7acf0d 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -86,8 +86,9 @@ public: ARRAY_WEIGHTS_SIZE=4, MAX_PARTICLE_COLOR_PHASES=4, MAX_PARTICLE_ATTRACTORS=4, - CANVAS_ITEM_Z_MAX=1024, - CANVAS_ITEM_Z_DEFAULT=512, + CANVAS_ITEM_Z_MIN=-4096, + CANVAS_ITEM_Z_MAX=4096, + MAX_CURSORS = 8, @@ -985,6 +986,7 @@ public: virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore)=0; virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0; virtual void canvas_item_set_z(RID p_item, int p_z)=0; + virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable)=0; virtual void canvas_item_clear(RID p_item)=0; virtual void canvas_item_raise(RID p_item)=0;