2D Rewrite Step [1]

-=-=-=-=-=-=-=-=-=-

-Moved drawing code to a single function that takes linked list (should make it easier to optimize in the future).
-Implemented Z ordering of 2D nodes. Node2D and those that inherit have a visibility/Z property that affects drawing order (besides the tree order)
-Removed OpenGL ES 1.x support. Good riddance!
This commit is contained in:
Juan Linietsky 2015-01-10 17:35:26 -03:00
parent 78f4b93703
commit 8997084831
35 changed files with 653 additions and 7694 deletions

View file

@ -3352,129 +3352,6 @@ void VisualServerRaster::canvas_item_set_clip(RID p_item, bool p_clip) {
canvas_item->clip=p_clip;
}
const Rect2& VisualServerRaster::CanvasItem::get_rect() const {
if (custom_rect || !rect_dirty)
return rect;
//must update rect
int s=commands.size();
if (s==0) {
rect=Rect2();
rect_dirty=false;
return rect;
}
Matrix32 xf;
bool found_xform=false;
bool first=true;
const CanvasItem::Command * const *cmd = &commands[0];
for (int i=0;i<s;i++) {
const CanvasItem::Command *c=cmd[i];
Rect2 r;
switch(c->type) {
case CanvasItem::Command::TYPE_LINE: {
const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c);
r.pos=line->from;
r.expand_to(line->to);
} break;
case CanvasItem::Command::TYPE_RECT: {
const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c);
r=crect->rect;
} break;
case CanvasItem::Command::TYPE_STYLE: {
const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c);
r=style->rect;
} break;
case CanvasItem::Command::TYPE_PRIMITIVE: {
const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c);
r.pos=primitive->points[0];
for(int i=1;i<primitive->points.size();i++) {
r.expand_to(primitive->points[i]);
}
} break;
case CanvasItem::Command::TYPE_POLYGON: {
const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::CommandPolygon*>(c);
int l = polygon->points.size();
const Point2*pp=&polygon->points[0];
r.pos=pp[0];
for(int i=1;i<l;i++) {
r.expand_to(pp[i]);
}
} break;
case CanvasItem::Command::TYPE_POLYGON_PTR: {
const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c);
int l = polygon->count;
if (polygon->indices != NULL) {
r.pos=polygon->points[polygon->indices[0]];
for (int i=1; i<polygon->count; i++) {
r.expand_to(polygon->points[polygon->indices[i]]);
};
} else {
r.pos=polygon->points[0];
for (int i=1; i<polygon->count; i++) {
r.expand_to(polygon->points[i]);
};
};
} break;
case CanvasItem::Command::TYPE_CIRCLE: {
const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::CommandCircle*>(c);
r.pos=Point2(-circle->radius,-circle->radius)+circle->pos;
r.size=Point2(circle->radius*2.0,circle->radius*2.0);
} break;
case CanvasItem::Command::TYPE_TRANSFORM: {
const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c);
xf=transform->xform;
found_xform=true;
continue;
} break;
case CanvasItem::Command::TYPE_BLEND_MODE: {
} break;
case CanvasItem::Command::TYPE_CLIP_IGNORE: {
} break;
}
if (found_xform) {
r = xf.xform(r);
found_xform=false;
}
if (first) {
rect=r;
first=false;
} else
rect=rect.merge(r);
}
rect_dirty=false;
return rect;
}
void VisualServerRaster::canvas_item_set_transform(RID p_item, const Matrix32& p_transform) {
@ -3812,6 +3689,17 @@ void VisualServerRaster::canvas_item_add_set_blend_mode(RID p_item, MaterialBlen
canvas_item->commands.push_back(bm);
};
void VisualServerRaster::canvas_item_set_z(RID p_item, int p_z) {
ERR_FAIL_COND(p_z<0 || p_z>=CANVAS_ITEM_Z_MAX);
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
canvas_item->z=p_z;
}
void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
VS_CHANGED;
@ -6200,7 +6088,38 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
rasterizer->end_scene();
}
void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity) {
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++) {
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);
for(int i=0;i<CANVAS_ITEM_Z_MAX;i++) {
if (!z_list[i])
continue;
rasterizer->canvas_render_items(z_list[i]);
}
}
void VisualServerRaster::_render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect) {
VisualServerRaster *self=(VisualServerRaster*)(p_self);
Viewport *vp=(Viewport*)p_vp;
self->_draw_viewport(vp,p_rect.pos.x,p_rect.pos.y,p_rect.size.x,p_rect.size.y);
self->rasterizer->canvas_begin();
}
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 *ci = p_canvas_item;
@ -6219,24 +6138,33 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
if (global_rect.intersects(p_clip_rect) && ci->viewport.is_valid() && viewport_owner.owns(ci->viewport)) {
Viewport *vp = viewport_owner.get(ci->viewport);
Viewport *vp = viewport_owner.get(ci->viewport);
Point2i from = xform.get_origin() + Point2(viewport_rect.x,viewport_rect.y);
Point2i size = rect.size;
size.x *= xform[0].length();
size.y *= xform[1].length();
ci->vp_render = memnew( Rasterizer::CanvasItem::ViewportRender );
ci->vp_render->owner=this;
ci->vp_render->udata=vp;
ci->vp_render->rect=Rect2(from.x,
from.y,
size.x,
size.y);
/*
_draw_viewport(vp,
from.x,
from.y,
size.x,
size.y);
rasterizer->canvas_begin();
*/
//rasterizer->canvas_begin();
} else {
ci->vp_render=NULL;
}
int s = ci->commands.size();
bool reclip=false;
float opacity = ci->opacity * p_opacity;
@ -6246,8 +6174,11 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(CanvasItem*));
if (ci->clip) {
rasterizer->canvas_set_clip(true,global_rect);
canvas_clip=global_rect;
ci->final_clip_rect=global_rect;
ci->final_clip_owner=ci;
} else {
ci->final_clip_owner=p_canvas_clip;
}
if (ci->sort_y) {
@ -6261,155 +6192,33 @@ 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);
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner);
}
if (s!=0) {
if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render) {
//something to draw?
ci->final_transform=xform;
ci->final_opacity=opacity * ci->self_opacity;
//Rect2 rect( ci->rect.pos + p_ofs, ci->rect.size);
if (z_last_list[ci->z]) {
z_last_list[ci->z]->next=ci;
z_last_list[ci->z]=ci;
if (p_clip_rect.intersects(global_rect)) {
rasterizer->canvas_begin_rect(xform);
rasterizer->canvas_set_opacity( opacity * ci->self_opacity );
rasterizer->canvas_set_blend_mode( ci->blend_mode );
CanvasItem::Command **commands = &ci->commands[0];
for (int i=0;i<s;i++) {
CanvasItem::Command *c=commands[i];
switch(c->type) {
case CanvasItem::Command::TYPE_LINE: {
CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c);
rasterizer->canvas_draw_line(line->from,line->to,line->color,line->width);
} break;
case CanvasItem::Command::TYPE_RECT: {
CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c);
// rasterizer->canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate);
#if 0
int flags=0;
if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) {
flags|=Rasterizer::CANVAS_RECT_REGION;
}
if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) {
flags|=Rasterizer::CANVAS_RECT_TILE;
}
if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) {
flags|=Rasterizer::CANVAS_RECT_FLIP_H;
}
if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) {
flags|=Rasterizer::CANVAS_RECT_FLIP_V;
}
#else
int flags=rect->flags;
#endif
rasterizer->canvas_draw_rect(rect->rect,flags,rect->source,rect->texture,rect->modulate);
} break;
case CanvasItem::Command::TYPE_STYLE: {
CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c);
rasterizer->canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color);
} break;
case CanvasItem::Command::TYPE_PRIMITIVE: {
CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c);
rasterizer->canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width);
} break;
case CanvasItem::Command::TYPE_POLYGON: {
CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c);
rasterizer->canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1);
} break;
case CanvasItem::Command::TYPE_POLYGON_PTR: {
CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c);
rasterizer->canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false);
} break;
case CanvasItem::Command::TYPE_CIRCLE: {
CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c);
static const int numpoints=32;
Vector2 points[numpoints+1];
points[numpoints]=circle->pos;
int indices[numpoints*3];
for(int i=0;i<numpoints;i++) {
points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius;
indices[i*3+0]=i;
indices[i*3+1]=(i+1)%numpoints;
indices[i*3+2]=numpoints;
}
rasterizer->canvas_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true);
//rasterizer->canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1);
} break;
case CanvasItem::Command::TYPE_TRANSFORM: {
CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c);
rasterizer->canvas_set_transform(transform->xform);
} break;
case CanvasItem::Command::TYPE_BLEND_MODE: {
CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c);
rasterizer->canvas_set_blend_mode(bm->blend_mode);
} break;
case CanvasItem::Command::TYPE_CLIP_IGNORE: {
CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(c);
if (canvas_clip!=Rect2()) {
if (ci->ignore!=reclip) {
if (ci->ignore) {
rasterizer->canvas_set_clip(false,Rect2());
reclip=true;
} else {
rasterizer->canvas_set_clip(true,canvas_clip);
reclip=false;
}
}
}
} break;
}
}
rasterizer->canvas_end_rect();
} else {
z_list[ci->z]=ci;
z_last_list[ci->z]=ci;
}
}
ci->next=NULL;
if (reclip) {
rasterizer->canvas_set_clip(true,canvas_clip);
}
for(int i=0;i<child_item_count;i++) {
if (!child_items[i]->ontop)
continue;
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
}
if (ci->clip) {
rasterizer->canvas_set_clip(false,Rect2());
canvas_clip=Rect2();
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner);
}
}
@ -6423,23 +6232,23 @@ void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_trans
for(int i=0;i<l;i++) {
Canvas::ChildItem& ci=p_canvas->child_items[i];
_render_canvas_item(ci.item,p_transform,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1);
_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(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1);
_render_canvas_item_tree(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height));
}
if (ci.mirror.y!=0) {
Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y));
_render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1);
_render_canvas_item_tree(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height));
}
if (ci.mirror.y!=0 && ci.mirror.x!=0) {
Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror);
_render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1);
_render_canvas_item_tree(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height));
}
}
@ -6859,6 +6668,7 @@ RID VisualServerRaster::get_test_cube() {
VisualServerRaster::VisualServerRaster(Rasterizer *p_rasterizer) {
rasterizer=p_rasterizer;
rasterizer->draw_viewport_func=_render_canvas_item_viewport;
instance_update_list=NULL;
render_pass=0;
clear_color=Color(0.3,0.3,0.3,1.0);