Sculpt: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r24095...
[blender.git] / source / blender / editors / space_view3d / drawobject.c
index 60ae91e7a897f3f4051b132ce7a58173a88a8242..f7dba10200a0dbfe5bd463c13acbf06752179b0b 100644 (file)
 #include "GPU_draw.h"
 #include "GPU_material.h"
 #include "GPU_extensions.h"
+#include "gpu_buffers.h"
 
 #include "ED_mesh.h"
 #include "ED_particle.h"
 #include "ED_screen.h"
+#include "ED_sculpt.h"
 #include "ED_types.h"
 #include "ED_util.h"
 
 #include "UI_interface_icons.h"
 
 #include "WM_api.h"
+#include "wm_subwindow.h"
 #include "BLF_api.h"
 
 #include "view3d_intern.h"     // own include
@@ -137,7 +140,9 @@ static void draw_empty_sphere(float size);
 static void draw_empty_cone(float size);
 
 
-/* ************* only use while object drawing ************** */
+/* ************* only use while object drawing **************
+ * or after running ED_view3d_init_mats_rv3d
+ * */
 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr)
 {
        RegionView3D *rv3d= ar->regiondata;
@@ -208,7 +213,7 @@ static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
 
 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
 {
-       if(!GPU_extensions_minimum_support())
+       if(!GPU_glsl_support())
                return 0;
        if(G.f & G_PICKSEL)
                return 0;
@@ -918,11 +923,11 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
                /* draw the circle/square representing spotbl */
                if(la->type==LA_SPOT) {
                        float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
-                       /* make sure the line is always visible - prevent it from reaching the outer border (or 0) 
-                        * values are kinda arbitrary - just what seemed to work well */
-                       if (spotblcirc == 0) spotblcirc = 0.15;
-                       else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
-                       circ(0.0, 0.0, spotblcirc);
+                       /* hide line if it is zero size or overlaps with outer border,
+                          previously it adjusted to always to show it but that seems
+                          confusing because it doesn't show the actual blend size */
+                       if (spotblcirc != 0 && spotblcirc != fabs(z))
+                               circ(0.0, 0.0, spotblcirc);
                }
                
        }
@@ -1297,6 +1302,10 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
 
 /* ***************** ******************** */
 
+/* Note! - foreach funcs should be called while drawing or directly after
+ * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
+ * but would not give correct results with dupli's for eg. which dont
+ * use the object matrix in the useual way */
 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
 {
        struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
@@ -1550,15 +1559,83 @@ static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *
                }
        }
 }
+
+/* disabled because it crashes combined with e.g. subsurf modifier,
+ * the derivedmesh can't be assumed to be an EditMeshDerivedMesh,
+ * nor should this struct be copied around, it should be defined in
+ * a single place only to avoid them getting out of sync */
+#if 0
+/* originally defined in DerivedMesh.c */
+typedef struct {
+       DerivedMesh dm;
+
+       EditMesh *em;
+       float (*vertexCos)[3];
+       float (*vertexNos)[3];
+       float (*faceNos)[3];
+} EditMeshDerivedMesh;
+#endif
+
 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
 {
        struct { int sel; EditVert *eve_act; } data;
+       //GPUBuffer *buffer;
+       //float *varray;
        data.sel = sel;
        data.eve_act = eve_act;
-       
-       bglBegin(GL_POINTS);
-       dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
-       bglEnd();
+
+#if 0
+       /* first come the unselected vertices, then the selected */
+       buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( sizeof(float)*3*dm->getNumVerts(dm)*2, 0 );
+
+       if( (varray = GPU_buffer_lock_stream( buffer )) && bglPointHack() == 0 ) {
+               EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+               EditVert *eve;
+               int i;
+               int numverts = 0, numselected = 0;
+               int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_END };
+               GPU_buffer_unlock( buffer );
+               GPU_interleaved_setup( buffer, datatype );
+               varray = GPU_buffer_lock_stream( buffer );
+
+               glBegin(GL_POINTS);
+               for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
+                       if (eve->h==0 && (eve->f&SELECT)==data.sel) {
+                               if (eve==data.eve_act) {
+                                       if (emdm->vertexCos) {
+                                               VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],emdm->vertexCos[i]);
+                                       }
+                                       else {
+                                               VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],eve->co);
+                                       }
+                                       numselected++;
+                               } else {
+                                       if (emdm->vertexCos) {
+                                               VECCOPY(&varray[3*numverts],emdm->vertexCos[i]);
+                                       } else {
+                                               VECCOPY(&varray[3*numverts],eve->co);
+                                       }
+                                       numverts++;
+                               }
+                       }
+               }
+               glEnd();
+               GPU_buffer_unlock( buffer );
+               glDrawArrays(GL_POINTS,0,numverts);
+               UI_ThemeColor4(TH_EDITMESH_ACTIVE);
+               glDrawArrays(GL_POINTS,dm->getNumVerts(dm),numselected);
+               UI_ThemeColor4(data.sel?TH_VERTEX_SELECT:TH_VERTEX);
+               GPU_buffer_unbind();
+       }
+       {
+#endif
+               bglBegin(GL_POINTS);
+               dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
+               bglEnd();
+#if 0
+       }
+       GPU_buffer_free( buffer, 0 );
+#endif
 }
 
        /* Draw edges with color set based on selection */
@@ -1626,12 +1703,59 @@ static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int i
                                col0[2] + (col1[2]-col0[2])*t,
                                col0[3] + (col1[3]-col0[3])*t);
 }
+
 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
 {
-       unsigned char *cols[2];
-       cols[0] = baseCol;
-       cols[1] = selCol;
-       dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
+       unsigned char *cols[2] = {baseCol, selCol};
+#if 0
+       int elemsize = sizeof(float)*3+sizeof(unsigned char)*4;
+       EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
+       EditMesh *em= emdm->em;
+       unsigned char *varray;
+       int i;
+       GPUBuffer *buffer;
+
+       buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*em->totedge*2, 0 );
+       if( (varray = GPU_buffer_lock_stream( buffer )) ) {
+               EditEdge *eed;
+               int numedges = 0;
+               int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
+               GPU_buffer_unlock( buffer );
+               GPU_interleaved_setup( buffer, datatype );
+               varray = GPU_buffer_lock_stream( buffer );
+               for (i=0,eed= em->edges.first; eed; i++,eed= eed->next) {
+                       if(eed->h==0) {
+                               unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
+                               unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
+
+                               if( emdm->vertexCos ) {
+                                       VECCOPY(((float *)&varray[elemsize*numedges*2]),emdm->vertexCos[(int) eed->v1->tmp.l]);
+                               }
+                               else {
+                                       VECCOPY(((float *)&varray[elemsize*numedges*2]),eed->v1->co);
+                               }
+                               QUATCOPY(&varray[elemsize*numedges*2+sizeof(float)*3],col0);
+                               if( emdm->vertexCos ) {
+                                       VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),emdm->vertexCos[(int) eed->v2->tmp.l]);
+                               }
+                               else {
+                                       VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),eed->v2->co);
+                               }
+                               QUATCOPY(&varray[elemsize*numedges*2+elemsize+sizeof(float)*3],col1);
+                               numedges++;
+                       }
+               }
+               GPU_buffer_unlock( buffer );
+               glDrawArrays(GL_LINES,0,numedges*2);
+               GPU_buffer_unbind();
+       }
+       else {
+#endif
+               dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
+#if 0
+       }
+       GPU_buffer_free( buffer, 0 );
+#endif
 }
 
        /* Draw only seam edges */
@@ -1685,12 +1809,236 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *dra
 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
 {
        struct { unsigned char *cols[3]; EditFace *efa_act; } data;
+       //EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
+       EditFace *efa;
+       unsigned char *col;
+       GPUBuffer *buffer;
+       unsigned char *varray;
+       unsigned char black[] = { 0, 0, 0, 0 };
+       int i, draw=0;
+       int elemsize = (sizeof(float)*6+sizeof(unsigned char)*4);
        data.cols[0] = baseCol;
        data.cols[1] = selCol;
        data.cols[2] = actCol;
        data.efa_act = efa_act;
-       
-       dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
+
+
+       buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*dm->getNumFaces(dm)*3*2, 0 );
+       if( dm->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
+               int prevdraw = 0;
+               int numfaces = 0;
+               int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
+               GPU_buffer_unlock( buffer );
+               GPU_interleaved_setup( buffer, datatype );
+               glShadeModel(GL_SMOOTH);
+               varray = GPU_buffer_lock_stream( buffer );
+               for (i=0,efa= efa_act; efa; i++,efa= efa->next) {
+                       int drawSmooth = (efa->flag & ME_SMOOTH);
+                       if (efa->h==0) {
+                               if (efa == data.efa_act) {
+                                       draw = 2;
+                               } else {
+                                       col = data.cols[(efa->f&SELECT)?1:0];
+                                       if (col[3]==0) draw = 0;
+                                       else draw = 1;
+                               }
+                       }
+                       else {
+                               draw = 0;
+                       }
+                       if( prevdraw != draw && prevdraw != 0 && numfaces > 0) {
+                               if( prevdraw==2 ) {
+                                       glEnable(GL_POLYGON_STIPPLE);
+                                       glPolygonStipple(stipple_quarttone);
+                               }
+                               GPU_buffer_unlock( buffer );
+                               glDrawArrays(GL_TRIANGLES,0,numfaces*3);
+                               if( prevdraw==2 ) {
+                                       glDisable(GL_POLYGON_STIPPLE);
+                               }
+                               varray = GPU_buffer_lock_stream( buffer );
+                               numfaces = 0;
+                       }
+
+                       if( draw != 0 ) {
+                               if(!drawSmooth) {
+                                       /*if (emdm->vertexCos) {
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
+
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
+
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
+                                       }
+                                       else {*/
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
+
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
+
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
+                                       /*}*/
+                                       if( draw == 2 ) {
+                                               QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
+                                       }
+                                       else if( draw == 1 ) {
+                                               QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                       }
+                                       else {
+                                               QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
+                                       }
+
+                                       numfaces++;
+                                       if( efa->v4 ) {
+                                               /*if (emdm->vertexCos) {
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
+
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
+
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
+                                               }
+                                               else {*/
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
+
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
+
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
+                                               /*}*/
+
+                                               if( draw == 2 ) {
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
+                                               }
+                                               else if( draw == 1 ) {
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                               }
+                                               else {
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
+                                               }
+
+                                               numfaces++;
+                                       }
+                               }
+                               else {
+                                       /*if (emdm->vertexCos) {
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
+
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
+
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
+                                       }
+                                       else {*/
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v1->no);
+
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v2->no);
+
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
+                                               VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v3->no);
+                                       /*}*/
+
+                                       if( draw == 2 ) {
+                                               QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
+                                       }
+                                       else if( draw == 1 ) {
+                                               QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                       }
+                                       else {
+                                               QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
+                                               QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
+                                       }
+
+                                       numfaces++;
+                                       if( efa->v4 ) {
+                                               /*if (emdm->vertexCos) {
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
+
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
+
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
+                                               }
+                                               else {*/
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v3->no);
+
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v4->no);
+
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
+                                                       VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v1->no);
+                                               /*}*/
+
+                                               if( draw == 2 ) {
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
+                                               }
+                                               else if( draw == 1 ) {
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
+                                               }
+                                               else {
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
+                                                       QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
+                                               }
+
+                                               numfaces++;
+                                       }
+                               }
+                       }
+                       prevdraw = draw;
+               }
+               GPU_buffer_unlock( buffer );
+               if( prevdraw != 0 && numfaces > 0) {
+                       if( prevdraw==2 ) {
+                               glEnable(GL_POLYGON_STIPPLE);
+                               glPolygonStipple(stipple_quarttone);
+                       }
+                       glDrawArrays(GL_TRIANGLES,0,numfaces*3);
+                       if( prevdraw==2 ) {
+                               glDisable(GL_POLYGON_STIPPLE);
+                       }
+               }
+               GPU_buffer_unbind();
+       } else {
+               dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
+       }
+       GPU_buffer_free( buffer, 0 );
 }
 
 static int draw_dm_creases__setDrawOptions(void *userData, int index)
@@ -2103,12 +2451,115 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
                        }
                }
                else {
+                       /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
+                       GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->totface*3*2, 0 );
+                       float *varray;
+                       EditFace *efa;
+                       int i, curmat = 0, draw = 0;
+
                        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
 
                        glEnable(GL_LIGHTING);
                        glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
 
-                       finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
+                       if( finalDM->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
+                               int prevdraw = 0, prevmat = 0;
+                               int numfaces = 0;
+                               int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_END };
+                               GPU_buffer_unlock( buffer );
+                               GPU_interleaved_setup( buffer, datatype );
+                               glShadeModel(GL_SMOOTH);
+                               varray = GPU_buffer_lock_stream( buffer );
+                               for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
+                                       int drawSmooth = (efa->flag & ME_SMOOTH);
+                                       if( efa->h == 0 ) {
+                                               curmat = efa->mat_nr+1;
+                                               draw = 1;
+                                       } 
+                                       else {
+                                               draw = 0;
+                                       }
+                                       if( ((prevdraw != draw) || (curmat != prevmat)) && prevdraw != 0 && numfaces > 0) {
+                                               if( prevdraw==2 ) {
+                                                       glEnable(GL_POLYGON_STIPPLE);
+                                                       glPolygonStipple(stipple_quarttone);
+                                               }
+                                               GPU_buffer_unlock( buffer );
+                                               GPU_enable_material(prevmat, NULL);
+                                               glDrawArrays(GL_TRIANGLES,0,numfaces*3);
+                                               if( prevdraw==2 ) {
+                                                       glDisable(GL_POLYGON_STIPPLE);
+                                               }
+                                               varray = GPU_buffer_lock_stream( buffer );
+                                               numfaces = 0;
+                                       }
+                                       if( draw != 0 ) {
+                                               if(!drawSmooth) {
+                                                       VECCOPY(&varray[numfaces*18],efa->v1->co);
+                                                       VECCOPY(&varray[numfaces*18+3],efa->n);
+
+                                                       VECCOPY(&varray[numfaces*18+6],efa->v2->co);
+                                                       VECCOPY(&varray[numfaces*18+9],efa->n);
+
+                                                       VECCOPY(&varray[numfaces*18+12],efa->v3->co);
+                                                       VECCOPY(&varray[numfaces*18+15],efa->n);
+                                                       numfaces++;
+                                                       if( efa->v4 ) {
+                                                               VECCOPY(&varray[numfaces*18],efa->v3->co);
+                                                               VECCOPY(&varray[numfaces*18+3],efa->n);
+
+                                                               VECCOPY(&varray[numfaces*18+6],efa->v4->co);
+                                                               VECCOPY(&varray[numfaces*18+9],efa->n);
+
+                                                               VECCOPY(&varray[numfaces*18+12],efa->v1->co);
+                                                               VECCOPY(&varray[numfaces*18+15],efa->n);
+                                                               numfaces++;
+                                                       }
+                                               }
+                                               else {
+                                                       VECCOPY(&varray[numfaces*18],efa->v1->co);
+                                                       VECCOPY(&varray[numfaces*18+3],efa->v1->no);
+
+                                                       VECCOPY(&varray[numfaces*18+6],efa->v2->co);
+                                                       VECCOPY(&varray[numfaces*18+9],efa->v2->no);
+
+                                                       VECCOPY(&varray[numfaces*18+12],efa->v3->co);
+                                                       VECCOPY(&varray[numfaces*18+15],efa->v3->no);
+                                                       numfaces++;
+                                                       if( efa->v4 ) {
+                                                               VECCOPY(&varray[numfaces*18],efa->v3->co);
+                                                               VECCOPY(&varray[numfaces*18+3],efa->v3->no);
+
+                                                               VECCOPY(&varray[numfaces*18+6],efa->v4->co);
+                                                               VECCOPY(&varray[numfaces*18+9],efa->v4->no);
+
+                                                               VECCOPY(&varray[numfaces*18+12],efa->v1->co);
+                                                               VECCOPY(&varray[numfaces*18+15],efa->v1->no);
+                                                               numfaces++;
+                                                       }
+                                               }
+                                       }
+                                       prevdraw = draw;
+                                       prevmat = curmat;
+                               }
+                               GPU_buffer_unlock( buffer );
+                               if( prevdraw != 0 && numfaces > 0) {
+                                       if( prevdraw==2 ) {
+                                               glEnable(GL_POLYGON_STIPPLE);
+                                               glPolygonStipple(stipple_quarttone);
+                                       }
+                                       GPU_enable_material(prevmat, NULL);
+                                       glDrawArrays(GL_TRIANGLES,0,numfaces*3);
+                                       if( prevdraw==2 ) {
+                                               glDisable(GL_POLYGON_STIPPLE);
+                                       }
+                               }
+                               GPU_buffer_unbind();
+                       }
+                       else {
+                               finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
+                       }
+                       GPU_buffer_free(buffer,0);
 
                        glFrontFace(GL_CCW);
                        glDisable(GL_LIGHTING);
@@ -2241,7 +2692,7 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
                   drawFacesSolid() doesn't draw the transparent faces */
                if(ob->dtx & OB_DRAWTRANSP) {
                        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
-                       dm->drawFacesSolid(dm, GPU_enable_material);
+                       dm->drawFacesSolid(dm, NULL, GPU_enable_material);
                        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
                        GPU_disable_material();
                }
@@ -2260,7 +2711,7 @@ static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmoot
        return 1;
 }
 
-static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
+static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
 {
        Object *ob= base->object;
        Mesh *me = ob->data;
@@ -2333,7 +2784,7 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
                }
        }
        else if(dt==OB_SOLID) {
-               if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
+               if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
                        draw_mesh_object_outline(v3d, ob, dm);
 
                glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
@@ -2341,7 +2792,21 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
                glEnable(GL_LIGHTING);
                glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
 
-               dm->drawFacesSolid(dm, GPU_enable_material);
+               if(ob->sculpt) {
+                       float planes[4][4];
+                       float (*fpl)[4] = NULL;
+
+                       if(ob->sculpt->partial_redraw) {
+                               sculpt_get_redraw_planes(planes, ar, rv3d, ob);
+                               fpl = planes;
+                               ob->sculpt->partial_redraw = 0;
+                       }
+
+                       dm->drawFacesSolid(dm, fpl, GPU_enable_material);
+               }
+               else
+                       dm->drawFacesSolid(dm, NULL, GPU_enable_material);
+
                GPU_disable_material();
 
                glFrontFace(GL_CCW);
@@ -2352,7 +2817,8 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
                } else {
                        UI_ThemeColor(TH_WIRE);
                }
-               dm->drawLooseEdges(dm);
+               if(!ob->sculpt)
+                       dm->drawLooseEdges(dm);
        }
        else if(dt==OB_SHADED) {
                int do_draw= 1; /* to resolve all G.f settings below... */
@@ -2470,7 +2936,7 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
 }
 
 /* returns 1 if nothing was drawn, for detecting to draw an object center */
-static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
+static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
 {
        Object *ob= base->object;
        Object *obedit= scene->obedit;
@@ -2520,7 +2986,7 @@ static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
                                        (check_alpha)? &do_alpha_pass: NULL);
                        }
 
-                       draw_mesh_fancy(scene, v3d, rv3d, base, dt, flag);
+                       draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
 
                        GPU_end_object_materials();
                        
@@ -2926,7 +3392,30 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
 }
 
 /* *********** drawing for particles ************* */
+static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select)
+{
+       /* draw created data arrays */
+       switch(draw_as){
+               case PART_DRAW_AXIS:
+               case PART_DRAW_CROSS:
+                       glDrawArrays(GL_LINES, 0, 6*totpoint);
+                       break;
+               case PART_DRAW_LINE:
+                       glDrawArrays(GL_LINES, 0, 2*totpoint);
+                       break;
+               case PART_DRAW_BB:
+                       if(ob_dt<=OB_WIRE || select)
+                               glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+                       else
+                               glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
 
+                       glDrawArrays(GL_QUADS, 0, 4*totpoint);
+                       break;
+               default:
+                       glDrawArrays(GL_POINTS, 0, totpoint);
+                       break;
+       }
+}
 static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd)
 {
        float vec[3], vec2[3];
@@ -2969,7 +3458,7 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
                                cd[7]=cd[10]=1.0;
                                cd[13]=cd[12]=cd[15]=cd[16]=0.0;
                                cd[14]=cd[17]=1.0;
-                               cd+=18;
+                               pdd->cd+=18;
 
                                VECCOPY(vec2,state->co);
                        }
@@ -3120,7 +3609,13 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
        if(psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART)==0)
                return;
                
-       if(part->draw_as==PART_DRAW_NOT) return;
+       if(part->draw_as == PART_DRAW_REND)
+               draw_as = part->ren_as;
+       else
+               draw_as = part->draw_as;
+
+       if(draw_as == PART_DRAW_NOT)
+               return;
 
 /* 2. */
        sim.psmd = psmd = psys_get_modifier(ob,psys);
@@ -3150,23 +3645,21 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 
        if(v3d->zbuf) glDepthMask(1);
 
-       if(select)
-               cpack(0xFFFFFF);
-       else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
+       if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
                glColor3f(ma->r,ma->g,ma->b);
 
                ma_r = ma->r;
                ma_g = ma->g;
                ma_b = ma->b;
+       }
+       else
+               cpack(0);
 
+       if(pdd) {
                pdd->ma_r = &ma_r;
                pdd->ma_g = &ma_g;
                pdd->ma_b = &ma_b;
-
-               create_cdata = 1;
        }
-       else
-               cpack(0);
 
        timestep= psys_get_timestep(&sim);
 
@@ -3178,15 +3671,10 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 
        totpart=psys->totpart;
 
-       if(part->draw_as==PART_DRAW_REND)
-               draw_as = part->ren_as;
-       else
-               draw_as = part->draw_as;
-
        //if(part->flag&PART_GLOB_TIME)
        cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f);
 
-       if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL)
+       if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL && psys->childcache==NULL)
                draw_as=PART_DRAW_DOT;
 
 /* 3. */
@@ -3212,6 +3700,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                                pixsize*=2.0;
                        else
                                pixsize*=part->draw_size;
+
+                       if(draw_as==PART_DRAW_AXIS)
+                               create_cdata = 1;
                        break;
                case PART_DRAW_OB:
                        if(part->dup_ob==0)
@@ -3259,9 +3750,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                Normalize(imat[1]);
        }
 
+       if(!create_cdata && pdd && pdd->cdata) {
+               MEM_freeN(pdd->cdata);
+               pdd->cdata = pdd->cd = NULL;
+       }
+
 /* 4. */
-       if(draw_as && draw_as!=PART_DRAW_PATH) {
+       if(draw_as && ELEM(draw_as, PART_DRAW_PATH, PART_DRAW_CIRC)==0) {
                int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
+               int create_ndata = 0;
 
                if(!pdd)
                        pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData");
@@ -3271,37 +3768,36 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                        psys_make_temp_pointcache(ob, psys);
                }
 
+               switch(draw_as) {
+                       case PART_DRAW_AXIS:
+                       case PART_DRAW_CROSS:
+                               tot_vec_size *= 6;
+                               if(draw_as != PART_DRAW_CROSS)
+                                       create_cdata = 1;
+                               break;
+                       case PART_DRAW_LINE:
+                               tot_vec_size *= 2;
+                               break;
+                       case PART_DRAW_BB:
+                               tot_vec_size *= 4;
+                               create_ndata = 1;
+                               break;
+               }
+
                if(pdd->tot_vec_size != tot_vec_size)
                        psys_free_pdd(psys);
 
-               if(draw_as!=PART_DRAW_CIRC) {
-                       switch(draw_as) {
-                               case PART_DRAW_AXIS:
-                               case PART_DRAW_CROSS:
-                                       if(draw_as != PART_DRAW_CROSS || create_cdata)
-                                               if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata");
-                                       if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata");
-                                       break;
-                               case PART_DRAW_LINE:
-                                       if(create_cdata)
-                                               if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata");
-                                       if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata");
-                                       break;
-                               case PART_DRAW_BB:
-                                       if(create_cdata)
-                                               if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata");
-                                       if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
-                                       if(!pdd->ndata) pdd->ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
-                                       break;
-                               default:
-                                       if(create_cdata)
-                                               if(!pdd->cdata) pdd->cdata=MEM_callocN(tot_vec_size, "particle_cdata");
-                                       if(!pdd->vdata) pdd->vdata=MEM_callocN(tot_vec_size, "particle_vdata");
-                       }
-               }
+               if(!pdd->vdata)
+                       pdd->vdata = MEM_callocN(tot_vec_size, "particle_vdata");
+               if(create_cdata && !pdd->cdata)
+                       pdd->cdata = MEM_callocN(tot_vec_size, "particle_cdata");
+               if(create_ndata && !pdd->ndata)
+                       pdd->ndata = MEM_callocN(tot_vec_size, "particle_vdata");
 
                if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) {
-                       if(!pdd->vedata) pdd->vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata");
+                       if(!pdd->vedata)
+                               pdd->vedata = MEM_callocN(2 * (totpart + totchild) * 3 * sizeof(float), "particle_vedata");
+
                        need_v = 1;
                }
 
@@ -3310,11 +3806,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                pdd->cd= pdd->cdata;
                pdd->nd= pdd->ndata;
                pdd->tot_vec_size= tot_vec_size;
-
-               psys->lattice= psys_get_lattice(&sim);
        }
 
-       if(draw_as){
+       psys->lattice= psys_get_lattice(&sim);
+
+       if(pdd && draw_as!=PART_DRAW_PATH){
 /* 5. */
                if((pdd->flag & PARTICLE_DRAW_DATA_UPDATED)
                        && (pdd->vedata || part->draw & (PART_DRAW_SIZE|PART_DRAW_NUM|PART_DRAW_HEALTH))==0) {
@@ -3402,156 +3898,141 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                                r_length = PSYS_FRAND(a + 22);
                        }
 
-                       if(draw_as!=PART_DRAW_PATH){
-                               drawn = 0;
-                               if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
-                                       float length = part->path_end * (1.0 - part->randlength * r_length);
-                                       int trail_count = part->trail_count * (1.0 - part->randlength * r_length);
-                                       float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
-                                       float dt = length / (trail_count ? (float)trail_count : 1.0f);
-                                       int i=0;
-
-                                       ct+=dt;
-                                       for(i=0; i < trail_count; i++, ct += dt) {
-                                               if(part->draw & PART_ABS_PATH_TIME) {
-                                                       if(ct < pa_birthtime || ct > pa_dietime)
-                                                               continue;
-                                               }
-                                               else if(ct < 0.0f || ct > 1.0f)
+                       drawn = 0;
+                       if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
+                               float length = part->path_end * (1.0 - part->randlength * r_length);
+                               int trail_count = part->trail_count * (1.0 - part->randlength * r_length);
+                               float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
+                               float dt = length / (trail_count ? (float)trail_count : 1.0f);
+                               int i=0;
+
+                               ct+=dt;
+                               for(i=0; i < trail_count; i++, ct += dt) {
+                                       if(part->draw & PART_ABS_PATH_TIME) {
+                                               if(ct < pa_birthtime || ct > pa_dietime)
                                                        continue;
+                                       }
+                                       else if(ct < 0.0f || ct > 1.0f)
+                                               continue;
 
-                                               state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
-                                               psys_get_particle_on_path(&sim,a,&state,need_v);
-                                               
-                                               if(psys->parent)
-                                                       Mat4MulVecfl(psys->parent->obmat, state.co);
-
-                                               /* create actiual particle data */
-                                               if(draw_as == PART_DRAW_BB) {
-                                                       bb.size = pa_size;
-                                                       bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
-                                                       bb.time = ct;
-                                               }
+                                       state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
+                                       psys_get_particle_on_path(&sim,a,&state,need_v);
+                                       
+                                       if(psys->parent)
+                                               Mat4MulVecfl(psys->parent->obmat, state.co);
+
+                                       /* create actiual particle data */
+                                       if(draw_as == PART_DRAW_BB) {
+                                               bb.size = pa_size;
+                                               bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+                                               bb.time = ct;
+                                       }
 
-                                               draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd);
+                                       draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd);
 
-                                               totpoint++;
-                                               drawn = 1;
-                                       }
+                                       totpoint++;
+                                       drawn = 1;
                                }
-                               else
-                               {
-                                       state.time=cfra;
-                                       if(psys_get_particle_state(&sim,a,&state,0)){
-                                               if(psys->parent)
-                                                       Mat4MulVecfl(psys->parent->obmat, state.co);
-
-                                               /* create actiual particle data */
-                                               if(draw_as == PART_DRAW_BB) {
-                                                       bb.size = pa_size;
-                                                       bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
-                                                       bb.time = pa_time;
-                                               }
+                       }
+                       else
+                       {
+                               state.time=cfra;
+                               if(psys_get_particle_state(&sim,a,&state,0)){
+                                       if(psys->parent)
+                                               Mat4MulVecfl(psys->parent->obmat, state.co);
+
+                                       /* create actiual particle data */
+                                       if(draw_as == PART_DRAW_BB) {
+                                               bb.size = pa_size;
+                                               bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+                                               bb.time = pa_time;
+                                       }
 
-                                               draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd);
+                                       draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd);
 
-                                               totpoint++;
-                                               drawn = 1;
-                                       }
+                                       totpoint++;
+                                       drawn = 1;
                                }
+                       }
 
-                               if(drawn) {
-                                       /* additional things to draw for each particle  */
-                                       /* (velocity, size and number)                                  */
-                                       if(pdd->vedata){
-                                               VECCOPY(pdd->ved,state.co);
-                                               pdd->ved+=3;
-                                               VECCOPY(vel,state.vel);
-                                               VecMulf(vel,timestep);
-                                               VECADD(pdd->ved,state.co,vel);
-                                               pdd->ved+=3;
-
-                                               totve++;
-                                       }
+                       if(drawn) {
+                               /* additional things to draw for each particle  */
+                               /* (velocity, size and number)                                  */
+                               if(pdd->vedata){
+                                       VECCOPY(pdd->ved,state.co);
+                                       pdd->ved+=3;
+                                       VECCOPY(vel,state.vel);
+                                       VecMulf(vel,timestep);
+                                       VECADD(pdd->ved,state.co,vel);
+                                       pdd->ved+=3;
+
+                                       totve++;
+                               }
 
-                                       if(part->draw & PART_DRAW_SIZE){
-                                               setlinestyle(3);
-                                               drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
-                                               setlinestyle(0);
-                                       }
+                               if(part->draw & PART_DRAW_SIZE){
+                                       setlinestyle(3);
+                                       drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
+                                       setlinestyle(0);
+                               }
 
-                                       if((part->draw&PART_DRAW_NUM || part->draw&PART_DRAW_HEALTH) && !(G.f & G_RENDER_SHADOW)){
-                                               val[0]= '\0';
-                                               
-                                               if(part->draw&PART_DRAW_NUM)
-                                                       sprintf(val, " %i", a);
+                               if((part->draw&PART_DRAW_NUM || part->draw&PART_DRAW_HEALTH) && !(G.f & G_RENDER_SHADOW)){
+                                       val[0]= '\0';
+                                       
+                                       if(part->draw&PART_DRAW_NUM)
+                                               sprintf(val, " %i", a);
 
-                                               if(part->draw&PART_DRAW_NUM && part->draw&PART_DRAW_HEALTH)
-                                                       sprintf(val, "%s:", val);
+                                       if(part->draw&PART_DRAW_NUM && part->draw&PART_DRAW_HEALTH)
+                                               sprintf(val, "%s:", val);
 
-                                               if(part->draw&PART_DRAW_HEALTH && a < totpart && part->phystype==PART_PHYS_BOIDS)
-                                                       sprintf(val, "%s %.2f", val, pa_health);
+                                       if(part->draw&PART_DRAW_HEALTH && a < totpart && part->phystype==PART_PHYS_BOIDS)
+                                               sprintf(val, "%s %.2f", val, pa_health);
 
-                                               /* in path drawing state.co is the end point */
-                                               view3d_cached_text_draw_add(state.co[0],  state.co[1],  state.co[2], val, 0);
-                                       }
+                                       /* in path drawing state.co is the end point */
+                                       view3d_cached_text_draw_add(state.co[0],  state.co[1],  state.co[2], val, 0);
                                }
                        }
                }
+       }
 /* 6. */
 
-               glGetIntegerv(GL_POLYGON_MODE, polygonmode);
-               glDisableClientState(GL_NORMAL_ARRAY);
+       glGetIntegerv(GL_POLYGON_MODE, polygonmode);
+       glDisableClientState(GL_NORMAL_ARRAY);
 
-               if(draw_as==PART_DRAW_PATH){
-                       ParticleCacheKey **cache, *path;
-                       float *cd2=0,*cdata2=0;
+       if(draw_as==PART_DRAW_PATH){
+               ParticleCacheKey **cache, *path;
+               float *cd2=0,*cdata2=0;
 
-                       glEnableClientState(GL_VERTEX_ARRAY);
+               glEnableClientState(GL_VERTEX_ARRAY);
 
-                       /* setup gl flags */
-                       if(ob_dt > OB_WIRE) {
-                               glEnableClientState(GL_NORMAL_ARRAY);
+               /* setup gl flags */
+               if(ob_dt > OB_WIRE) {
+                       glEnableClientState(GL_NORMAL_ARRAY);
 
-                               if(part->draw&PART_DRAW_MAT_COL)
-                                       glEnableClientState(GL_COLOR_ARRAY);
-
-                               glEnable(GL_LIGHTING);
-                               glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-                               glEnable(GL_COLOR_MATERIAL);
-                       }
-                       else {
-                               glDisableClientState(GL_NORMAL_ARRAY);
-
-                               glDisable(GL_COLOR_MATERIAL);
-                               glDisable(GL_LIGHTING);
-                               UI_ThemeColor(TH_WIRE);
-                       }
+                       if(part->draw&PART_DRAW_MAT_COL)
+                               glEnableClientState(GL_COLOR_ARRAY);
 
-                       if(totchild && (part->draw&PART_DRAW_PARENT)==0)
-                               totpart=0;
+                       glEnable(GL_LIGHTING);
+                       glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+                       glEnable(GL_COLOR_MATERIAL);
+               }
+               else {
+                       glDisableClientState(GL_NORMAL_ARRAY);
 
-                       /* draw actual/parent particles */
-                       cache=psys->pathcache;
-                       for(a=0, pa=psys->particles; a<totpart; a++, pa++){
-                               path=cache[a];
-                               if(path->steps > 0) {
-                                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+                       glDisable(GL_COLOR_MATERIAL);
+                       glDisable(GL_LIGHTING);
+                       UI_ThemeColor(TH_WIRE);
+               }
 
-                                       if(ob_dt > OB_WIRE) {
-                                               glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
-                                               if(part->draw&PART_DRAW_MAT_COL)
-                                                       glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
-                                       }
+               if(totchild && (part->draw&PART_DRAW_PARENT)==0)
+                       totpart=0;
+               else if(psys->pathcache==NULL)
+                       totpart=0;
 
-                                       glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
-                               }
-                       }
-                       
-                       /* draw child particles */
-                       cache=psys->childcache;
-                       for(a=0; a<totchild; a++){
-                               path=cache[a];
+               /* draw actual/parent particles */
+               cache=psys->pathcache;
+               for(a=0, pa=psys->particles; a<totpart; a++, pa++){
+                       path=cache[a];
+                       if(path->steps > 0) {
                                glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
 
                                if(ob_dt > OB_WIRE) {
@@ -3562,86 +4043,103 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 
                                glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
                        }
+               }
+               
+               /* draw child particles */
+               cache=psys->childcache;
+               for(a=0; a<totchild; a++){
+                       path=cache[a];
+                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
 
-
-                       /* restore & clean up */
                        if(ob_dt > OB_WIRE) {
+                               glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
                                if(part->draw&PART_DRAW_MAT_COL)
-                                       glDisable(GL_COLOR_ARRAY);
-                               glDisable(GL_COLOR_MATERIAL);
+                                       glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
                        }
 
-                       if(cdata2)
-                               MEM_freeN(cdata2);
-                       cd2=cdata2=0;
+                       glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+               }
 
-                       glLineWidth(1.0f);
+
+               /* restore & clean up */
+               if(ob_dt > OB_WIRE) {
+                       if(part->draw&PART_DRAW_MAT_COL)
+                               glDisable(GL_COLOR_ARRAY);
+                       glDisable(GL_COLOR_MATERIAL);
                }
-               else if(draw_as!=PART_DRAW_CIRC){
-                       glDisableClientState(GL_COLOR_ARRAY);
 
-                       /* setup created data arrays */
-                       if(pdd->vdata){
-                               glEnableClientState(GL_VERTEX_ARRAY);
-                               glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
-                       }
+               if(cdata2)
+                       MEM_freeN(cdata2);
+               cd2=cdata2=0;
+
+               glLineWidth(1.0f);
+       }
+       else if(pdd && ELEM(draw_as, 0, PART_DRAW_CIRC)==0){
+               glDisableClientState(GL_COLOR_ARRAY);
+
+               /* enable point data array */
+               if(pdd->vdata){
+                       glEnableClientState(GL_VERTEX_ARRAY);
+                       glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
+               }
+               else
+                       glDisableClientState(GL_VERTEX_ARRAY);
+
+               if(select) {
+                       UI_ThemeColor(TH_ACTIVE);
+                       
+                       if(part->draw_size)
+                               glPointSize(part->draw_size + 2);
                        else
-                               glDisableClientState(GL_VERTEX_ARRAY);
+                               glPointSize(4.0);
 
-                       /* billboards are drawn this way */
-                       if(pdd->ndata && ob_dt>OB_WIRE){
-                               glEnableClientState(GL_NORMAL_ARRAY);
-                               glNormalPointer(GL_FLOAT, 0, pdd->ndata);
-                               glEnable(GL_LIGHTING);
-                       }
-                       else{
-                               glDisableClientState(GL_NORMAL_ARRAY);
-                               glDisable(GL_LIGHTING);
-                       }
+                       glLineWidth(3.0);
 
-                       if(pdd->cdata){
-                               glEnableClientState(GL_COLOR_ARRAY);
-                               glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
-                       }
+                       draw_particle_arrays(draw_as, totpoint, ob_dt, 1);
+               }
 
-                       /* draw created data arrays */
-                       switch(draw_as){
-                               case PART_DRAW_AXIS:
-                               case PART_DRAW_CROSS:
-                                       glDrawArrays(GL_LINES, 0, 6*totpoint);
-                                       break;
-                               case PART_DRAW_LINE:
-                                       glDrawArrays(GL_LINES, 0, 2*totpoint);
-                                       break;
-                               case PART_DRAW_BB:
-                                       if(ob_dt<=OB_WIRE)
-                                               glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
-
-                                       glDrawArrays(GL_QUADS, 0, 4*totpoint);
-                                       break;
-                               default:
-                                       glDrawArrays(GL_POINTS, 0, totpoint);
-                                       break;
-                       }
+               /* restore from select */
+               glColor3f(ma_r,ma_g,ma_b);
+               glPointSize(part->draw_size ? part->draw_size : 2.0);
+               glLineWidth(1.0);
+
+               /* enable other data arrays */
 
-                       pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
-                       pdd->totpoint = totpoint;
+               /* billboards are drawn this way */
+               if(pdd->ndata && ob_dt>OB_WIRE){
+                       glEnableClientState(GL_NORMAL_ARRAY);
+                       glNormalPointer(GL_FLOAT, 0, pdd->ndata);
+                       glEnable(GL_LIGHTING);
+               }
+               else{
+                       glDisableClientState(GL_NORMAL_ARRAY);
+                       glDisable(GL_LIGHTING);
                }
 
-               if(pdd->vedata){
-                       glDisableClientState(GL_COLOR_ARRAY);
-                       cpack(0xC0C0C0);
-                       
-                       glEnableClientState(GL_VERTEX_ARRAY);
-                       glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
-                       
-                       glDrawArrays(GL_LINES, 0, 2*totve);
+               if(pdd->cdata){
+                       glEnableClientState(GL_COLOR_ARRAY);
+                       glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
                }
 
-               glPolygonMode(GL_FRONT, polygonmode[0]);
-               glPolygonMode(GL_BACK, polygonmode[1]);
+               draw_particle_arrays(draw_as, totpoint, ob_dt, 0);
+
+               pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
+               pdd->totpoint = totpoint;
        }
 
+       if(pdd && pdd->vedata){
+               glDisableClientState(GL_COLOR_ARRAY);
+               cpack(0xC0C0C0);
+               
+               glEnableClientState(GL_VERTEX_ARRAY);
+               glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
+               
+               glDrawArrays(GL_LINES, 0, 2*totve);
+       }
+
+       glPolygonMode(GL_FRONT, polygonmode[0]);
+       glPolygonMode(GL_BACK, polygonmode[1]);
+
 /* 7. */
        
        glDisable(GL_LIGHTING);
@@ -3653,6 +4151,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 
        psys->flag &= ~PSYS_DRAWING;
 
+       /* draw data can't be saved for billboards as they must update to target changes */
+       if(draw_as == PART_DRAW_BB) {
+               psys_free_pdd(psys);
+               pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
+       }
+
        if(psys->lattice){
                end_latt_deform(psys->lattice);
                psys->lattice= NULL;
@@ -3669,7 +4173,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj
        PTCacheEditKey *key;
        ParticleEditSettings *pset = PE_settings(scene);
        int i, k, totpoint = edit->totpoint, timed = pset->flag & PE_FADE_TIME ? pset->fade_frames : 0;
-       int steps;
+       int steps=1;
        char nosel[4], sel[4];
        float sel_col[3];
        float nosel_col[3];
@@ -3751,7 +4255,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj
                                if(!(point->flag & PEP_HIDE))
                                        totkeys += point->totkey;
 
-                       if(!(edit->points->keys->flag & PEK_USE_WCO))
+                       if(edit->points && !(edit->points->keys->flag & PEK_USE_WCO))
                                pd=pdata=MEM_callocN(totkeys*3*sizeof(float), "particle edit point data");
                        cd=cdata=MEM_callocN(totkeys*(timed?4:3)*sizeof(float), "particle edit color data");
 
@@ -4971,11 +5475,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
        /* draw paths... */
        // TODO...
 
-       /* multiply view with object matrix */
-       wmMultMatrix(ob->obmat);
-       /* local viewmat and persmat, to calculate projections */
-       wmGetMatrix(rv3d->viewmatob);
-       wmGetSingleMatrix(rv3d->persmatob);
+       /* multiply view with object matrix.
+        * local viewmat and persmat, to calculate projections */
+       ED_view3d_init_mats_rv3d(ob, rv3d);
 
        /* which wire color */
        if((flag & DRAW_CONSTCOLOR) == 0) {
@@ -5032,7 +5534,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
        if(ob==OBACT && (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT))) {
                if(ob->type==OB_MESH) {
 
-                       if(ob==scene->obedit);
+                       if(ob->mode & OB_MODE_EDIT);
                        else {
                                if(dt<OB_SOLID)
                                        zbufoff= 1;
@@ -5054,7 +5556,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
        if(dt>=OB_BOUNDBOX ) {
 
                dtx= ob->dtx;
-               if(scene->obedit==ob) {
+               if(ob->mode & OB_MODE_EDIT) {
                        // the only 2 extra drawtypes alowed in editmode
                        dtx= dtx & (OB_DRAWWIRE|OB_TEXSPACE);
                }
@@ -5070,7 +5572,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
        
        /* draw outline for selected solid objects, mesh does itself */
        if((v3d->flag & V3D_SELECT_OUTLINE) && ob->type!=OB_MESH) {
-               if(dt>OB_WIRE && dt<OB_TEXTURE && ob!=scene->obedit && (flag && DRAW_SCENESET)==0) {
+               if(dt>OB_WIRE && dt<OB_TEXTURE && (ob->mode & OB_MODE_EDIT)==0 && (flag & DRAW_SCENESET)==0) {
                        if (!(ob->dtx&OB_DRAWWIRE) && (ob->flag&SELECT) && !(flag&DRAW_PICKING)) {
                                
                                drawSolidSelect(scene, v3d, ar, base);
@@ -5080,10 +5582,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
 
        switch( ob->type) {
                case OB_MESH:
-                       if (!(base->flag&OB_RADIO)) {
-                               empty_object= draw_mesh_object(scene, v3d, rv3d, base, dt, flag);
-                               if(flag!=DRAW_CONSTCOLOR) dtx &= ~OB_DRAWWIRE; // mesh draws wire itself
-                       }
+                       empty_object= draw_mesh_object(scene, ar, v3d, rv3d, base, dt, flag);
+                       if(flag!=DRAW_CONSTCOLOR) dtx &= ~OB_DRAWWIRE; // mesh draws wire itself
 
                        break;
                case OB_FONT:
@@ -5227,6 +5727,22 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
        }
        if(ob->pd && ob->pd->forcefield) draw_forcefield(scene, ob);
 
+       /* particle mode has to be drawn first so that possible child particles get cached in edit mode */
+       if(             (warning_recursive==0) &&
+                       (flag & DRAW_PICKING)==0 &&
+                       (!scene->obedit)        
+         ) {
+
+               if(ob->mode & OB_MODE_PARTICLE_EDIT && ob==OBACT) {
+                       PTCacheEdit *edit = PE_get_current(scene, ob);
+                       if(edit) {
+                               wmLoadMatrix(rv3d->viewmat);
+                               draw_ptcache_edit(scene, v3d, rv3d, ob, edit, dt);
+                               wmMultMatrix(ob->obmat);
+                       }
+               }
+       }
+
        /* code for new particle system */
        if(             (warning_recursive==0) &&
                        (ob->particlesystem.first) &&
@@ -5251,21 +5767,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
                //glDepthMask(GL_TRUE);
                if(col) cpack(col);
        }
-       
-       if(             (warning_recursive==0) &&
-                       (flag & DRAW_PICKING)==0 &&
-                       (!scene->obedit)        
-         ) {
-
-               if(ob->mode & OB_MODE_PARTICLE_EDIT && ob==OBACT) {
-                       PTCacheEdit *edit = PE_get_current(scene, ob);
-                       if(edit) {
-                               wmLoadMatrix(rv3d->viewmat);
-                               draw_ptcache_edit(scene, v3d, rv3d, ob, edit, dt);
-                               wmMultMatrix(ob->obmat);
-                       }
-               }
-       }
 
        /* draw code for smoke */
        if((md = modifiers_findByType(ob, eModifierType_Smoke)))
@@ -5426,7 +5927,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
        if(zbufoff) glDisable(GL_DEPTH_TEST);
 
        if(warning_recursive) return;
-       if(base->flag & (OB_FROMDUPLI|OB_RADIO)) return;
+       if(base->flag & OB_FROMDUPLI) return;
        if(G.f & G_RENDER_SHADOW) return;
 
        /* object centers, need to be drawn in viewmat space for speed, but OK for picking select */
@@ -5601,7 +6102,24 @@ static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh
        }
 }
 
-static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmooth_r)
+static int bbs_mesh_solid_hide__setDrawOpts(void *userData, int index, int *drawSmooth_r)
+{
+       Mesh *me = userData;
+
+       if (!(me->mface[index].flag&ME_HIDE)) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+static int bbs_mesh_solid__setDrawOpts_legacy(void *userData, int index, int *drawSmooth_r)
+{
+       WM_set_framebuffer_index_color(index+1);
+       return 1;
+}
+
+static int bbs_mesh_solid_hide__setDrawOpts_legacy(void *userData, int index, int *drawSmooth_r)
 {
        Mesh *me = userData;
 
@@ -5613,14 +6131,49 @@ static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmoot
        }
 }
 
-/* TODO remove this - since face select mode now only works with painting */
 static void bbs_mesh_solid(Scene *scene, View3D *v3d, Object *ob)
 {
        DerivedMesh *dm = mesh_get_derived_final(scene, ob, v3d->customdata_mask);
        Mesh *me = (Mesh*)ob->data;
+       MCol *colors;
+       int i,j;
+       int face_sel_mode = (me->flag & ME_EDIT_PAINT_MASK) ? 1:0;
        
        glColor3ub(0, 0, 0);
-       dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0);
+               
+       if( !GPU_buffer_legacy(dm) ) {
+               int *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+               int ind;
+               colors = MEM_mallocN(dm->getNumFaces(dm)*sizeof(MCol)*4,"bbs_mesh_solid");
+               for(i=0;i<dm->getNumFaces(dm);i++) {
+                       if( index != 0 )
+                               ind = index[i];
+                       else
+                               ind = i;
+                       if (face_sel_mode==0 || !(me->mface[ind].flag&ME_HIDE)) {
+                               unsigned int fbindex = index_to_framebuffer(ind+1);
+                               for(j=0;j<4;j++) {
+                                       colors[i*4+j].b = ((fbindex)&0xFF);
+                                       colors[i*4+j].g = (((fbindex)>>8)&0xFF);
+                                       colors[i*4+j].r = (((fbindex)>>16)&0xFF);
+                               }
+                       }
+                       else {
+                               memset(&colors[i*4],0,sizeof(MCol)*4);
+                       }
+               }
+
+               CustomData_add_layer( &dm->faceData, CD_ID_MCOL, CD_ASSIGN, colors, dm->numFaceData );
+               GPU_buffer_free(dm->drawObject->colors,0);
+               dm->drawObject->colors = 0;
+
+               if(face_sel_mode)       dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, me, 1);
+               else                            dm->drawMappedFaces(dm, NULL, me, 1);
+       }
+       else {
+               if(face_sel_mode)       dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts_legacy, me, 0);
+               else                            dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts_legacy, me, 0);
+       }
 
        dm->release(dm);
 }
@@ -5637,7 +6190,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
        switch( ob->type) {
        case OB_MESH:
        {
-               if(ob == scene->obedit) {
+               if(ob->mode & OB_MODE_EDIT) {
                        Mesh *me= ob->data;
                        EditMesh *em= me->edit_mesh;
 
@@ -5693,7 +6246,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
        DerivedMesh *dm=NULL, *edm=NULL;
        int glsl;
        
-       if(ob == scene->obedit)
+       if(ob->mode & OB_MODE_EDIT)
                edm= editmesh_get_derived_base(ob, me->edit_mesh);
        else 
                dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
@@ -5723,7 +6276,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
                glEnable(GL_LIGHTING);
                
                if(dm) {
-                       dm->drawFacesSolid(dm, GPU_enable_material);
+                       dm->drawFacesSolid(dm, NULL, GPU_enable_material);
                        GPU_end_object_materials();
                }
                else if(edm)