You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-06 12:20:30 +00:00
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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user