summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/physics_2d/body_2d_sw.cpp1
-rw-r--r--servers/physics_2d/body_2d_sw.h9
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp46
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h9
-rw-r--r--servers/physics_2d/space_2d_sw.cpp81
-rw-r--r--servers/physics_2d_server.cpp7
-rw-r--r--servers/physics_2d_server.h6
-rw-r--r--servers/visual/shader_language.cpp1
-rw-r--r--servers/visual/visual_server_raster.cpp105
-rw-r--r--servers/visual/visual_server_raster.h7
-rw-r--r--servers/visual/visual_server_wrap_mt.h1
-rw-r--r--servers/visual_server.h6
12 files changed, 244 insertions, 35 deletions
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index d93d4d5c35..1cfe9a6ab9 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -647,6 +647,7 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti
area_linear_damp=0;
contact_count=0;
gravity_scale=1.0;
+ one_way_collision_max_depth=0.1;
still_time=0;
continuous_cd_mode=Physics2DServer::CCD_MODE_DISABLED;
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index 5bd68ba976..3b87be2737 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -67,6 +67,9 @@ class Body2DSW : public CollisionObject2DSW {
Vector2 applied_force;
real_t applied_torque;
+ Vector2 one_way_collision_direction;
+ float one_way_collision_max_depth;
+
SelfList<Body2DSW> active_list;
SelfList<Body2DSW> inertia_update_list;
@@ -216,6 +219,12 @@ 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_one_way_collision_max_depth(float p_depth) { one_way_collision_max_depth=p_depth; }
+ float get_one_way_collision_max_depth() const { return one_way_collision_max_depth; }
+
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 ab85f5e1d6..be49955055 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -138,6 +138,21 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p
if (cbk->max==0)
return;
+ if (cbk->valid_dir!=Vector2()) {
+ if (p_point_A.distance_squared_to(p_point_B)>cbk->valid_depth*cbk->valid_depth) {
+ return;
+ }
+ if (cbk->valid_dir.dot((p_point_A-p_point_B).normalized())<0.7071) {
+/* print_line("A: "+p_point_A);
+ print_line("B: "+p_point_B);
+ print_line("discard too angled "+rtos(cbk->valid_dir.dot((p_point_A-p_point_B))));
+ print_line("resnorm: "+(p_point_A-p_point_B).normalized());
+ print_line("distance: "+rtos(p_point_A.distance_to(p_point_B)));
+*/
+ return;
+ }
+ }
+
if (cbk->amount == cbk->max) {
//find least deep
float min_depth=1e20;
@@ -860,6 +875,37 @@ 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_one_way_collision_max_depth(RID p_body,float p_max_depth) {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_one_way_collision_max_depth(p_max_depth);
+
+}
+
+float Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body,0);
+ return body->get_one_way_collision_max_depth();
+
+}
+
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 9edd4eee11..e9c499aaff 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -71,6 +71,8 @@ public:
struct CollCbkData {
+ Vector2 valid_dir;
+ float valid_depth;
int max;
int amount;
Vector2 *ptr;
@@ -205,6 +207,13 @@ 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_one_way_collision_max_depth(RID p_body,float p_max_depth);
+ virtual float body_get_one_way_collision_max_depth(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/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 76069de9a0..f2ed74ffbf 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -98,7 +98,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec
if (shape->intersect_segment(local_from,local_to,shape_point,shape_normal)) {
- //print_line("inters sgment!");
+
Matrix32 xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point=xform.xform(shape_point);
@@ -217,6 +217,16 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
int shape_idx=space->intersection_query_subindex_results[i];
+ /*if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ if (body->get_one_way_collision_direction()!=Vector2() && p_motion.dot(body->get_one_way_collision_direction())<=CMP_EPSILON) {
+ print_line("failed in motion dir");
+ continue;
+ }
+ }*/
+
+
Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) {
@@ -227,6 +237,14 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
//test initial overlap
if (CollisionSolver2DSW::solve(shape,p_xform,Vector2(),col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) {
+ if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+ //if one way collision direction ignore initial overlap
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ if (body->get_one_way_collision_direction()!=Vector2()) {
+ continue;
+ }
+ }
+
return false;
}
@@ -253,6 +271,29 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
}
}
+ if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ if (body->get_one_way_collision_direction()!=Vector2()) {
+
+ Vector2 cd[2];
+ Physics2DServerSW::CollCbkData cbk;
+ cbk.max=1;
+ cbk.amount=0;
+ cbk.ptr=cd;
+ cbk.valid_dir=body->get_one_way_collision_direction();
+ cbk.valid_depth=body->get_one_way_collision_max_depth();
+
+ Vector2 sep=mnormal; //important optimization for this to work fast enough
+ bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*(hi+space->contact_max_allowed_penetration),col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),Physics2DServerSW::_shape_col_cbk,&cbk,&sep,p_margin);
+ if (!collided || cbk.amount==0) {
+ continue;
+ }
+
+ }
+ }
+
+
if (low<best_safe) {
best_safe=low;
best_unsafe=hi;
@@ -311,14 +352,23 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_s
if (p_exclude.has( col_obj->get_self() ))
continue;
-
+ if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ cbk.valid_dir=body->get_one_way_collision_direction();
+ cbk.valid_depth=body->get_one_way_collision_max_depth();
+ } else {
+ cbk.valid_dir=Vector2();
+ cbk.valid_depth=0;
+ }
if (CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2(),cbkres,cbkptr,NULL,p_margin)) {
- collided=true;
+ collided=p_result_max==0 || cbk.amount>0;
}
}
+
r_result_count=cbk.amount;
return collided;
@@ -334,6 +384,8 @@ struct _RestCallbackData2D {
Vector2 best_contact;
Vector2 best_normal;
float best_len;
+ Vector2 valid_dir;
+ float valid_depth;
};
static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata) {
@@ -341,11 +393,23 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v
_RestCallbackData2D *rd=(_RestCallbackData2D*)p_userdata;
+ if (rd->valid_dir!=Vector2()) {
+
+ if (rd->valid_dir!=Vector2()) {
+ if (p_point_A.distance_squared_to(p_point_B)>rd->valid_depth*rd->valid_depth)
+ return;
+ if (rd->valid_dir.dot((p_point_A-p_point_B).normalized())<Math_PI*0.25)
+ return;
+ }
+
+ }
+
Vector2 contact_rel = p_point_B - p_point_A;
float len = contact_rel.length();
if (len <= rd->best_len)
return;
+
rd->best_len=len;
rd->best_contact=p_point_B;
rd->best_normal=contact_rel/len;
@@ -385,6 +449,17 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape
if (p_exclude.has( col_obj->get_self() ))
continue;
+ if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ rcd.valid_dir=body->get_one_way_collision_direction();
+ rcd.valid_depth=body->get_one_way_collision_max_depth();
+ } else {
+ rcd.valid_dir=Vector2();
+ rcd.valid_depth=0;
+ }
+
+
rcd.object=col_obj;
rcd.shape=shape_idx;
bool sc = CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2() ,_rest_cbk_result,&rcd,NULL,p_margin);
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index 3633efc5eb..07389bc912 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -500,6 +500,13 @@ 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_one_way_collision_max_depth","normal"),&Physics2DServer::body_set_one_way_collision_max_depth);
+ ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_max_depth"),&Physics2DServer::body_get_one_way_collision_max_depth);
+
+
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 6e53cde55c..765cebf45f 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -442,6 +442,12 @@ 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;
+
+ virtual void body_set_one_way_collision_max_depth(RID p_body,float p_max_depth)=0;
+ virtual float body_get_one_way_collision_max_depth(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/shader_language.cpp b/servers/visual/shader_language.cpp
index f5bff29f47..9a76a009a9 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -900,6 +900,7 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
{"normalize",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
{"normalize",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
{"reflect",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"refract",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
//intrinsics - texture
{"tex",TYPE_VEC4,{TYPE_TEXTURE,TYPE_VEC2,TYPE_VOID}},
{"texcube",TYPE_VEC4,{TYPE_CUBEMAP,TYPE_VEC3,TYPE_VOID}},
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index dfa1e849b7..dc0bff4cf4 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_z<CANVAS_ITEM_Z_MIN || p_z>CANVAS_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;i<CANVAS_ITEM_Z_MAX;i++) {
+ 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;i<z_range;i++) {
z_list[i]=NULL;
z_last_list[i]=NULL;
}
- _render_canvas_item(p_canvas_item,p_transform,p_clip_rect,1.0,z_list,z_last_list,NULL,NULL);
+ _render_canvas_item(p_canvas_item,p_transform,p_clip_rect,1.0,0,z_list,z_last_list,NULL,NULL);
- for(int i=0;i<CANVAS_ITEM_Z_MAX;i++) {
+ for(int i=0;i<z_range;i++) {
if (!z_list[i])
continue;
rasterizer->canvas_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;i<l;i++) {
+ if (ci[i].mirror.x || ci[i].mirror.y) {
+ has_mirror=true;
+ break;
+ }
+ }
- Canvas::ChildItem& ci=p_canvas->child_items[i];
- _render_canvas_item_tree(ci.item,p_transform,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) {
- //mirroring (useful for scrolling backgrounds)
- if (ci.mirror.x!=0) {
+ 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];
- 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));
+ for(int i=0;i<z_range;i++) {
+ z_list[i]=NULL;
+ z_last_list[i]=NULL;
}
- 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));
+ for(int i=0;i<l;i++) {
+ _render_canvas_item(ci[i].item,p_transform,clip_rect,1.0,0,z_list,z_last_list,NULL,NULL);
}
- if (ci.mirror.y!=0 && ci.mirror.x!=0) {
- Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror);
- _render_canvas_item_tree(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height));
+ for(int i=0;i<z_range;i++) {
+ if (!z_list[i])
+ continue;
+ rasterizer->canvas_render_items(z_list[i]);
}
+ } else {
+
+ for(int i=0;i<l;i++) {
+
+ Canvas::ChildItem& ci=p_canvas->child_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 d30ac17400..6c4e15827a 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -380,6 +380,7 @@ class VisualServerRaster : public VisualServer {
List<CanvasItem*>::Element *E;
RID viewport;
int z;
+ bool z_relative;
bool sort_y;
float opacity;
float self_opacity;
@@ -391,11 +392,12 @@ class VisualServerRaster : public VisualServer {
CanvasItem() {
E=NULL;
- z=CANVAS_ITEM_Z_MAX/2;
+ z=0;
opacity=1;
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<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);
@@ -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 c344161445..b59fdbc66a 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 5edf333e65..5721e7acf0 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;