Merged changes in the trunk up to revision 54110.
[blender.git] / source / blender / editors / space_view3d / drawobject.c
index 90da3824870df8f3fd0f9805b3590a321a83bb96..fc8d5d26455ed8d78e51cb986d3650f16256441a 100644 (file)
  *  \ingroup spview3d
  */
 
-
-#include <string.h>
-#include <math.h>
-
 #include "MEM_guardedalloc.h"
 
 #include "DNA_camera_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
 #include "DNA_meta_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_smoke_types.h"
-#include "DNA_speaker_types.h"
 #include "DNA_world_types.h"
-#include "DNA_armature_types.h"
 #include "DNA_object_types.h"
 
-#include "BLI_utildefines.h"
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
-#include "BLI_edgehash.h"
-#include "BLI_rand.h"
-#include "BLI_utildefines.h"
 
 #include "BKE_anim.h"  /* for the where_on_path function */
 #include "BKE_armature.h"
 #include "BKE_pointcache.h"
 #include "BKE_scene.h"
 #include "BKE_unit.h"
-#include "BKE_movieclip.h"
 #include "BKE_tracking.h"
 
 #include "BKE_tessmesh.h"
 
-#include "smoke_API.h"
-
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
 #include "ED_screen.h"
 #include "ED_sculpt.h"
 #include "ED_types.h"
-#include "ED_curve.h" /* for curve_editnurbs */
 
 #include "UI_resources.h"
+#include "UI_interface_icons.h"
 
 #include "WM_api.h"
-#include "wm_subwindow.h"
 #include "BLF_api.h"
 
-#include "view3d_intern.h"  /* own include */
+#include "view3d_intern.h"  /* bad level include */
 
 typedef enum eWireDrawMode {
        OBDRAW_WIRE_OFF = 0,
@@ -116,30 +101,8 @@ typedef enum eWireDrawMode {
        OBDRAW_WIRE_ON_DEPTH = 2
 } eWireDrawMode;
 
-/* user data structures for derived mesh callbacks */
-typedef struct foreachScreenVert_userData {
-       void (*func)(void *userData, BMVert *eve, int x, int y, int index);
-       void *userData;
-       ViewContext vc;
-       eV3DClipTest clipVerts;
-} foreachScreenVert_userData;
-
-typedef struct foreachScreenEdge_userData {
-       void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index);
-       void *userData;
-       ViewContext vc;
-       rcti win_rect; /* copy of: vc.ar->winx/winy, use for faster tests, minx/y will always be 0 */
-       eV3DClipTest clipVerts;
-} foreachScreenEdge_userData;
-
-typedef struct foreachScreenFace_userData {
-       void (*func)(void *userData, BMFace *efa, int x, int y, int index);
-       void *userData;
-       ViewContext vc;
-} foreachScreenFace_userData;
-
 typedef struct drawDMVerts_userData {
-       BMEditMesh *em; /* BMESH BRANCH ONLY */
+       BMEditMesh *em;
 
        int sel;
        BMVert *eve_act;
@@ -157,20 +120,25 @@ typedef struct drawDMVerts_userData {
 } drawDMVerts_userData;
 
 typedef struct drawDMEdgesSel_userData {
-       BMEditMesh *em; /* BMESH BRANCH ONLY */
+       BMEditMesh *em;
 
        unsigned char *baseCol, *selCol, *actCol;
        BMEdge *eed_act;
 } drawDMEdgesSel_userData;
 
 typedef struct drawDMFacesSel_userData {
+#ifdef WITH_FREESTYLE
+       unsigned char *cols[4];
+#else
        unsigned char *cols[3];
+#endif
 
-       DerivedMesh *dm; /* BMESH BRANCH ONLY */
-       BMEditMesh *em;  /* BMESH BRANCH ONLY */
+       DerivedMesh *dm;
+       BMEditMesh *em;
 
        BMFace *efa_act;
-       int *orig_index;
+       int *orig_index_mf_to_mpoly;
+       int *orig_index_mp_to_orig;
 } drawDMFacesSel_userData;
 
 typedef struct drawDMNormal_userData {
@@ -205,17 +173,26 @@ static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], con
 }
 
 /* this condition has been made more complex since editmode can draw textures */
-static int check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype)
+static bool check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype)
 {
        /* texture and material draw modes */
-       if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID)
-               return TRUE;
+       if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID) {
+               return true;
+       }
 
        /* textured solid */
-       if (v3d->drawtype == OB_SOLID && (v3d->flag2 & V3D_SOLID_TEX) && !BKE_scene_use_new_shading_nodes(scene))
-               return TRUE;
+       if ((v3d->drawtype == OB_SOLID) &&
+           (v3d->flag2 & V3D_SOLID_TEX) &&
+           (BKE_scene_use_new_shading_nodes(scene) == false))
+       {
+               return true;
+       }
        
-       return FALSE;
+       if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) {
+               return true;
+       }
+       
+       return false;
 }
 
 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
@@ -239,112 +216,11 @@ static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
        return 1;
 }
 
-/* ************* only use while object drawing **************
- * or after running ED_view3d_init_mats_rv3d
- * */
-static void view3d_project_short_clip(ARegion *ar, const float vec[3], short adr[2], int is_local)
-{
-       RegionView3D *rv3d = ar->regiondata;
-       float fx, fy, vec4[4];
-       
-       adr[0] = IS_CLIPPED;
-       
-       /* clipplanes in eye space */
-       if (rv3d->rflag & RV3D_CLIPPING) {
-               if (ED_view3d_clipping_test(rv3d, vec, is_local))
-                       return;
-       }
-       
-       copy_v3_v3(vec4, vec);
-       vec4[3] = 1.0;
-       
-       mul_m4_v4(rv3d->persmatob, vec4);
-       
-       /* clipplanes in window space */
-       if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
-               fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
-               
-               if (fx > 0 && fx < ar->winx) {
-                       
-                       fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
-                       
-                       if (fy > 0.0f && fy < (float)ar->winy) {
-                               adr[0] = (short)floorf(fx);
-                               adr[1] = (short)floorf(fy);
-                       }
-               }
-       }
-}
-
-/* BMESH NOTE: this function is unused in bmesh only */
-
-/* only use while object drawing */
-static void UNUSED_FUNCTION(view3d_project_short_noclip) (ARegion * ar, const float vec[3], short adr[2])
-{
-       RegionView3D *rv3d = ar->regiondata;
-       float fx, fy, vec4[4];
-       
-       adr[0] = IS_CLIPPED;
-       
-       copy_v3_v3(vec4, vec);
-       vec4[3] = 1.0;
-       
-       mul_m4_v4(rv3d->persmatob, vec4);
-       
-       if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
-               fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
-               
-               if (fx > -32700 && fx < 32700) {
-                       
-                       fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
-                       
-                       if (fy > -32700.0f && fy < 32700.0f) {
-                               adr[0] = (short)floorf(fx);
-                               adr[1] = (short)floorf(fy);
-                       }
-               }
-       }
-}
-
-/* same as view3d_project_short_clip but use persmat instead of persmatob for projection */
-static void view3d_project_short_clip_persmat(ARegion *ar, const float vec[3], short adr[2], int is_local)
-{
-       RegionView3D *rv3d = ar->regiondata;
-       float fx, fy, vec4[4];
-
-       adr[0] = IS_CLIPPED;
-
-       /* clipplanes in eye space */
-       if (rv3d->rflag & RV3D_CLIPPING) {
-               if (ED_view3d_clipping_test(rv3d, vec, is_local))
-                       return;
-       }
-
-       copy_v3_v3(vec4, vec);
-       vec4[3] = 1.0;
-
-       mul_m4_v4(rv3d->persmat, vec4);
-
-       /* clipplanes in window space */
-       if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
-               fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
-
-               if (fx > 0 && fx < ar->winx) {
-
-                       fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
-
-                       if (fy > 0.0f && fy < (float)ar->winy) {
-                               adr[0] = (short)floorf(fx);
-                               adr[1] = (short)floorf(fy);
-                       }
-               }
-       }
-}
 /* ************************ */
 
 /* check for glsl drawing */
 
-int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt)
+int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
 {
        if (!GPU_glsl_support())
                return 0;
@@ -354,6 +230,10 @@ int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt)
                return 0;
        if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
                return 0;
+       
+       if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)
+               return 1;
+       
        if (BKE_scene_use_new_shading_nodes(scene))
                return 0;
        
@@ -367,17 +247,21 @@ static int check_alpha_pass(Base *base)
 
        if (G.f & G_PICKSEL)
                return 0;
-       
+
+       if (base->object->mode & OB_MODE_ALL_PAINT)
+               return 0;
+
        return (base->object->dtx & OB_DRAWTRANSP);
 }
 
 /***/
-static unsigned int colortab[24] =
-{0x0,       0xFF88FF, 0xFFBBFF,
- 0x403000,  0xFFFF88, 0xFFFFBB,
- 0x104040,  0x66CCCC, 0x77CCCC,
- 0x104010,  0x55BB55, 0x66FF66,
- 0xFFFFFF};
+static unsigned int colortab[24] = {
+       0x0,      0xFF88FF, 0xFFBBFF,
+       0x403000, 0xFFFF88, 0xFFFFBB,
+       0x104040, 0x66CCCC, 0x77CCCC,
+       0x104010, 0x55BB55, 0x66FF66,
+       0xFFFFFF
+};
 
 
 static float cube[8][3] = {
@@ -667,7 +551,7 @@ void drawaxes(float size, char drawtype)
 static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
 {
        Image *ima = (Image *)ob->data;
-       ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
+       ImBuf *ibuf = ima ? BKE_image_acquire_ibuf(ima, NULL, NULL) : NULL;
 
        float scale, ofs_x, ofs_y, sca_x, sca_y;
        int ima_x, ima_y;
@@ -717,7 +601,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
        glTranslatef(0.0f,  0.0f,  0.0f);
 
        /* Calculate Image scale */
-       scale = (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
+       scale = (ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y));
 
        /* Set the object scale */
        glScalef(scale * sca_x, scale * sca_y, 1.0f);
@@ -752,9 +636,11 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
        /* Reset GL settings */
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
 }
 
-static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4])
+static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[4][4])
 {
        float vx[3], vy[3];
        float *viter = (float *)verts;
@@ -770,7 +656,7 @@ static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3
        }
 }
 
-void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
+void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4])
 {
        float verts[CIRCLE_RESOL][3];
 
@@ -871,7 +757,7 @@ void view3d_cached_text_draw_add(const float co[3],
        memcpy(++vos, str, alloc_len);
 }
 
-void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
+void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[4][4])
 {
        RegionView3D *rv3d = ar->regiondata;
        ListBase *strings = &CachedText[CachedTextLevel - 1];
@@ -883,13 +769,17 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa
                if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
                        mul_m4_v3(mat, vos->vec);
 
-               if (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE)
-                       view3d_project_short_clip_persmat(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
-               else
-                       view3d_project_short_clip(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
-
-               if (vos->sco[0] != IS_CLIPPED)
+               if (ED_view3d_project_short_ex(ar,
+                                              (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
+                                              (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0,
+                                              vos->vec, vos->sco,
+                                              V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+               {
                        tot++;
+               }
+               else {
+                       vos->sco[0] = IS_CLIPPED;
+               }
        }
 
        if (tot) {
@@ -954,7 +844,9 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa
                if (depth_write) {
                        if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
                }
-               else glDepthMask(1);
+               else {
+                       glDepthMask(1);
+               }
                
                glMatrixMode(GL_PROJECTION);
                glPopMatrix();
@@ -996,7 +888,7 @@ static void drawcube(void)
        glEnd();
 }
 
-/* draws a cube on given the scaling of the cube, assuming that 
+/* draws a cube on given the scaling of the cube, assuming that
  * all required matrices have been set (used for drawing empties)
  */
 static void drawcube_size(float size)
@@ -1055,7 +947,7 @@ static void drawcube_size(const float size[3])
 }
 #endif
 
-static void drawshadbuflimits(Lamp *la, float mat[][4])
+static void drawshadbuflimits(Lamp *la, float mat[4][4])
 {
        float sta[3], end[3], lavec[3];
 
@@ -1203,7 +1095,7 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z)
 }
 
 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
-                     const short dt, const short dflag, const unsigned char ob_wire_col[4])
+                     const char dt, const short dflag, const unsigned char ob_wire_col[4])
 {
        Object *ob = base->object;
        const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
@@ -1380,8 +1272,10 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
                        glVertex3fv(tvec);
                        glEnd();
                }
-               else circ(0.0, 0.0, fabsf(z));
-               
+               else {
+                       circ(0.0, 0.0, fabsf(z));
+               }
+
                /* draw the circle/square representing spotbl */
                if (la->type == LA_SPOT) {
                        float spotblcirc = fabs(z) * (1 - pow(la->spotblend, 2));
@@ -1410,6 +1304,13 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
                        glVertex3fv(vvec_clip);
                        glEnd();
                }
+               /* Else, draw spot direction (using distance as end limit, same as for Area lamp). */
+               else {
+                       glBegin(GL_LINE_STRIP);
+                       glVertex3f(0.0, 0.0, -circrad);
+                       glVertex3f(0.0, 0.0, -la->dist);
+                       glEnd();
+               }
        }
        else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
                
@@ -1525,7 +1426,7 @@ static void draw_limit_line(float sta, float end, unsigned int col)
        glVertex3f(0.0, 0.0, -end);
        glEnd();
        glPointSize(1.0);
-}              
+}
 
 
 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
@@ -1966,27 +1867,6 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
        bglEnd();
 }
 
-void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
-{
-       Object *obedit = vc->obedit;
-       Lattice *lt = obedit->data;
-       BPoint *bp = lt->editlatt->latt->def;
-       DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS);
-       float *co = dl ? dl->verts : NULL;
-       int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
-       short s[2] = {IS_CLIPPED, 0};
-
-       ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */
-
-       for (i = 0; i < N; i++, bp++, co += 3) {
-               if (bp->hide == 0) {
-                       view3d_project_short_clip(vc->ar, dl ? co : bp->vec, s, TRUE);
-                       if (s[0] != IS_CLIPPED)
-                               func(userData, bp, s[0], s[1]);
-               }
-       }
-}
-
 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
 {
        int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
@@ -2073,56 +1953,6 @@ 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 don't
- * use the object matrix in the usual way */
-static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
-                                            const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
-{
-       foreachScreenVert_userData *data = userData;
-       BMVert *eve = EDBM_vert_at_index(data->vc.em, index);
-
-       if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
-               short s[2] = {IS_CLIPPED, 0};
-
-               if (data->clipVerts != V3D_CLIP_TEST_OFF) {
-                       view3d_project_short_clip(data->vc.ar, co, s, TRUE);
-               }
-               else {
-                       float co2[2];
-                       mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
-                       project_short_noclip(data->vc.ar, co2, s);
-               }
-
-               if (s[0] != IS_CLIPPED)
-                       data->func(data->userData, eve, s[0], s[1], index);
-       }
-}
-
-void mesh_foreachScreenVert(
-        ViewContext *vc,
-        void (*func)(void *userData, BMVert *eve, int x, int y, int index),
-        void *userData, eV3DClipTest clipVerts)
-{
-       foreachScreenVert_userData data;
-       DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
-       
-       data.vc = *vc;
-       data.func = func;
-       data.userData = userData;
-       data.clipVerts = clipVerts;
-
-       if (clipVerts != V3D_CLIP_TEST_OFF)
-               ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat);  /* for local clipping lookups */
-
-       EDBM_index_arrays_init(vc->em, 1, 0, 0);
-       dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
-       EDBM_index_arrays_free(vc->em);
-
-       dm->release(dm);
-}
-
 /*  draw callback */
 static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
                                           const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
@@ -2151,166 +1981,9 @@ static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
        glEnd();
 }
 
-static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3])
-{
-       foreachScreenEdge_userData *data = userData;
-       BMEdge *eed = EDBM_edge_at_index(data->vc.em, index);
-
-       if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
-               short s[2][2];
-
-               if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
-                       view3d_project_short_clip(data->vc.ar, v0co, s[0], TRUE);
-                       view3d_project_short_clip(data->vc.ar, v1co, s[1], TRUE);
-               }
-               else {
-                       float v1_co[3], v2_co[3];
-
-                       mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
-                       mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
-
-                       project_short_noclip(data->vc.ar, v1_co, s[0]);
-                       project_short_noclip(data->vc.ar, v2_co, s[1]);
-
-                       if (data->clipVerts == V3D_CLIP_TEST_REGION) {
-                               /* make an int copy */
-                               int s_int[2][2] = {{s[0][0], s[0][1]},
-                                                  {s[1][0], s[1][1]}};
-                               if (!BLI_rcti_isect_segment(&data->win_rect, s_int[0], s_int[1])) {
-                                       return;
-                               }
-                       }
-               }
-
-               data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
-       }
-}
-
-void mesh_foreachScreenEdge(
-        ViewContext *vc,
-        void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index),
-        void *userData, eV3DClipTest clipVerts)
-{
-       foreachScreenEdge_userData data;
-       DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
-
-       data.vc = *vc;
-
-       data.win_rect.xmin = 0;
-       data.win_rect.ymin = 0;
-       data.win_rect.xmax = vc->ar->winx;
-       data.win_rect.ymax = vc->ar->winy;
-
-       data.func = func;
-       data.userData = userData;
-       data.clipVerts = clipVerts;
-
-       if (clipVerts != V3D_CLIP_TEST_OFF)
-               ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat);  /* for local clipping lookups */
-
-       EDBM_index_arrays_init(vc->em, 0, 1, 0);
-       dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
-       EDBM_index_arrays_free(vc->em);
-
-       dm->release(dm);
-}
-
-static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
-{
-       foreachScreenFace_userData *data = userData;
-       BMFace *efa = EDBM_face_at_index(data->vc.em, index);
-
-       if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
-               float cent2[3];
-               short s[2];
-
-               mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
-               project_short(data->vc.ar, cent2, s);
-
-               if (s[0] != IS_CLIPPED) {
-                       data->func(data->userData, efa, s[0], s[1], index);
-               }
-       }
-}
-
-void mesh_foreachScreenFace(
-        ViewContext *vc,
-        void (*func)(void *userData, BMFace *efa, int x, int y, int index),
-        void *userData)
-{
-       foreachScreenFace_userData data;
-       DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
-
-       data.vc = *vc;
-       data.func = func;
-       data.userData = userData;
-
-       //if (clipVerts)
-       ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
-
-       EDBM_index_arrays_init(vc->em, 0, 0, 1);
-       dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
-       EDBM_index_arrays_free(vc->em);
-
-       dm->release(dm);
-}
-
-void nurbs_foreachScreenVert(
-        ViewContext *vc,
-        void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y),
-        void *userData)
-{
-       Curve *cu = vc->obedit->data;
-       short s[2] = {IS_CLIPPED, 0};
-       Nurb *nu;
-       int i;
-       ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
-       ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
-
-       for (nu = nurbs->first; nu; nu = nu->next) {
-               if (nu->type == CU_BEZIER) {
-                       for (i = 0; i < nu->pntsu; i++) {
-                               BezTriple *bezt = &nu->bezt[i];
-
-                               if (bezt->hide == 0) {
-                                       
-                                       if (cu->drawflag & CU_HIDE_HANDLES) {
-                                               view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
-                                               if (s[0] != IS_CLIPPED)
-                                                       func(userData, nu, NULL, bezt, 1, s[0], s[1]);
-                                       }
-                                       else {
-                                               view3d_project_short_clip(vc->ar, bezt->vec[0], s, TRUE);
-                                               if (s[0] != IS_CLIPPED)
-                                                       func(userData, nu, NULL, bezt, 0, s[0], s[1]);
-                                               view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
-                                               if (s[0] != IS_CLIPPED)
-                                                       func(userData, nu, NULL, bezt, 1, s[0], s[1]);
-                                               view3d_project_short_clip(vc->ar, bezt->vec[2], s, TRUE);
-                                               if (s[0] != IS_CLIPPED)
-                                                       func(userData, nu, NULL, bezt, 2, s[0], s[1]);
-                                       }
-                               }
-                       }
-               }
-               else {
-                       for (i = 0; i < nu->pntsu * nu->pntsv; i++) {
-                               BPoint *bp = &nu->bp[i];
-
-                               if (bp->hide == 0) {
-                                       view3d_project_short_clip(vc->ar, bp->vec, s, TRUE);
-                                       if (s[0] != IS_CLIPPED)
-                                               func(userData, nu, bp, NULL, -1, s[0], s[1]);
-                               }
-                       }
-               }
-       }
-}
-
 /* ************** DRAW MESH ****************** */
 
-/* First section is all the "simple" draw routines, 
+/* First section is all the "simple" draw routines,
  * ones that just pass some sort of primitive to GL,
  * with perhaps various options to control lighting,
  * color, etc.
@@ -2545,7 +2218,7 @@ static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
                return DM_DRAW_OPTION_SKIP;
        }
 }
-static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
+static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
 {
        drawDMEdgesSel_userData data;
@@ -2567,7 +2240,7 @@ static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
                return DM_DRAW_OPTION_NORMAL;
 }
 
-static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) 
+static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
 {
        dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
 }
@@ -2632,6 +2305,23 @@ static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
        dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
 }
 
+#ifdef WITH_FREESTYLE
+/* Draw only Freestyle feature edges */
+static DMDrawOption draw_dm_edges_freestyle__setDrawOptions(void *userData, int index)
+{
+       BMEdge *eed = EDBM_edge_at_index(userData, index);
+
+       if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_FREESTYLE))
+               return DM_DRAW_OPTION_NORMAL;
+       else
+               return DM_DRAW_OPTION_SKIP;
+}
+
+static void draw_dm_edges_freestyle(BMEditMesh *em, DerivedMesh *dm)
+{
+       dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, em);
+}
+#endif
 
 /* Draw faces with color set based on selection
  * return 2 for the active face so it renders with stipple enabled */
@@ -2650,7 +2340,11 @@ static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
                        return DM_DRAW_OPTION_STIPPLE;
                }
                else {
+#ifdef WITH_FREESTYLE
+                       col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : BM_elem_flag_test(efa, BM_ELEM_FREESTYLE) ? 3 : 0];
+#else
                        col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
+#endif
                        if (col[3] == 0)
                                return DM_DRAW_OPTION_SKIP;
                        glColor4ubv(col);
@@ -2669,11 +2363,11 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
 
        unsigned char *col, *next_col;
 
-       if (!data->orig_index)
+       if (!data->orig_index_mf_to_mpoly)
                return 0;
 
-       efa = EDBM_face_at_index(data->em, data->orig_index[index]);
-       next_efa = EDBM_face_at_index(data->em, data->orig_index[next_index]);
+       efa = EDBM_face_at_index(data->em, DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, index));
+       next_efa = EDBM_face_at_index(data->em, DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, next_index));
 
        if (efa == next_efa)
                return 1;
@@ -2681,8 +2375,13 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
        if (efa == data->efa_act || next_efa == data->efa_act)
                return 0;
 
+#ifdef WITH_FREESTYLE
+       col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : BM_elem_flag_test(efa, BM_ELEM_FREESTYLE) ? 3 : 0];
+       next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : BM_elem_flag_test(next_efa, BM_ELEM_FREESTYLE) ? 3 : 0];
+#else
        col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
        next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
+#endif
 
        if (col[3] == 0 || next_col[3] == 0)
                return 0;
@@ -2691,8 +2390,13 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
 }
 
 /* also draws the active face */
-static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
+#ifdef WITH_FREESTYLE
+static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
+                              unsigned char *selCol, unsigned char *actCol, unsigned char *markCol, BMFace *efa_act)
+#else
+static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
+#endif
 {
        drawDMFacesSel_userData data;
        data.dm = dm;
@@ -2700,8 +2404,16 @@ static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *ba
        data.em = em;
        data.cols[1] = selCol;
        data.cols[2] = actCol;
+#ifdef WITH_FREESTYLE
+       data.cols[3] = markCol;
+#endif
        data.efa_act = efa_act;
-       data.orig_index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
+       /* double lookup */
+       data.orig_index_mf_to_mpoly = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
+       data.orig_index_mp_to_orig  = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
+       if ((data.orig_index_mf_to_mpoly && data.orig_index_mp_to_orig) == FALSE) {
+               data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL;
+       }
 
        dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
 }
@@ -2788,9 +2500,9 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
 
 /* EditMesh drawing routines*/
 
-static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, 
+static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
-                                                               RegionView3D *rv3d)
+                                RegionView3D *rv3d)
 {
        ToolSettings *ts = scene->toolsettings;
        int sel;
@@ -2910,7 +2622,7 @@ static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
                        glEnable(GL_DEPTH_TEST);
                }
        }
-}      
+}
 
 static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
 {
@@ -2929,12 +2641,12 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS
        BMIter iter;
        int i;
 
-       /* make the precision of the pronted value proportionate to the gridsize */
+       /* make the precision of the display value proportionate to the gridsize */
 
-       if (grid < 0.01f) conv_float = "%.6g";
-       else if (grid < 0.1f) conv_float = "%.5g";
-       else if (grid < 1.0f) conv_float = "%.4g";
-       else if (grid < 10.0f) conv_float = "%.3g";
+       if (grid <= 0.01f) conv_float = "%.6g";
+       else if (grid <= 0.1f) conv_float = "%.5g";
+       else if (grid <= 1.0f) conv_float = "%.4g";
+       else if (grid <= 10.0f) conv_float = "%.3g";
        else conv_float = "%.2g";
        
        if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
@@ -2979,16 +2691,21 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS
                BMFace *f;
                int n;
 
-#define DRAW_EM_MEASURE_STATS_FACEAREA()                                      \
-       if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                               \
-               mul_v3_fl(vmid, 1.0f / (float)n);                                     \
-               if (unit->system)                                                     \
-                       bUnit_AsString(numstr, sizeof(numstr),                            \
-                                      (double)(area * unit->scale_length),               \
-                                      3, unit->system, B_UNIT_LENGTH, do_split, FALSE);  \
-               else                                                                  \
-                       BLI_snprintf(numstr, sizeof(numstr), conv_float, area);           \
-               view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);          \
+#define DRAW_EM_MEASURE_STATS_FACEAREA()                                                 \
+       if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                                          \
+               mul_v3_fl(vmid, 1.0f / (float)n);                                                \
+               if (unit->system) {                                                              \
+                       bUnit_AsString(numstr, sizeof(numstr),                                       \
+                                      (double)(area * unit->scale_length * unit->scale_length),     \
+                                      3, unit->system, B_UNIT_AREA, do_split, FALSE);               \
+                       view3d_cached_text_draw_add(vmid, numstr, 0,                                 \
+                                                   /* Metric system uses unicode "squared" sign! */ \
+                                                   txt_flag ^ V3D_CACHE_TEXT_ASCII, col);           \
+               }                                                                                \
+               else {                                                                           \
+                       BLI_snprintf(numstr, sizeof(numstr), conv_float, area);                      \
+                       view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);                 \
+               }                                                                                \
        } (void)0
 
                UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
@@ -3160,7 +2877,7 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
 }
 
 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
-                          Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const short dt)
+                          Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt)
 
 {
        Mesh *me = ob->data;
@@ -3175,7 +2892,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
                if (ese->type == BM_FACE) {
                        efa_act = (BMFace *)ese->data;
                }
-               else 
+               else
 #endif
                if (ese->htype == BM_EDGE) {
                        eed_act = (BMEdge *)ese->ele;
@@ -3185,7 +2902,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
                }
        }
        
-       EDBM_index_arrays_init(em, 1, 1, 1);
+       EDBM_index_arrays_ensure(em, BM_VERT | BM_EDGE | BM_FACE);
 
        if (dt > OB_WIRE) {
                if (check_object_draw_texture(scene, v3d, dt)) {
@@ -3232,10 +2949,16 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
        
        if (me->drawflag & ME_DRAWFACES) {  /* transp faces */
                unsigned char col1[4], col2[4], col3[4];
+#ifdef WITH_FREESTYLE
+               unsigned char col4[4];
+#endif
 
                UI_GetThemeColor4ubv(TH_FACE, col1);
                UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
                UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
+#ifdef WITH_FREESTYLE
+               UI_GetThemeColor4ubv(TH_FREESTYLE_FACE_MARK, col4);
+#endif
 
                glEnable(GL_BLEND);
                glDepthMask(0);  /* disable write in zbuffer, needed for nice transp */
@@ -3244,7 +2967,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
                if (check_object_draw_texture(scene, v3d, dt))
                        col1[3] = 0;
 
+#ifdef WITH_FREESTYLE
+               if (!(me->drawflag & ME_DRAW_FREESTYLE_FACE))
+                       col4[3] = 0;
+
+               draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
+#else
                draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
+#endif
 
                glDisable(GL_BLEND);
                glDepthMask(1);  /* restore write in zbuffer */
@@ -3253,14 +2983,19 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
                /* even if draw faces is off it would be nice to draw the stipple face
                 * Make all other faces zero alpha except for the active
                 * */
-               unsigned char col1[4], col2[4], col3[4];
-               col1[3] = col2[3] = 0; /* don't draw */
+               /* col4 is only used by WITH_FREESTYLE, but keeping it here spares some #ifdef's... */
+               unsigned char col1[4], col2[4], col3[4], col4[4];
+               col1[3] = col2[3] = col4[3] = 0; /* don't draw */
                UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
 
                glEnable(GL_BLEND);
                glDepthMask(0);  /* disable write in zbuffer, needed for nice transp */
 
+#ifdef WITH_FREESTYLE
+               draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
+#else
                draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
+#endif
 
                glDisable(GL_BLEND);
                glDepthMask(1);  /* restore write in zbuffer */
@@ -3296,6 +3031,18 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
                        glLineWidth(1);
                }
 
+#ifdef WITH_FREESTYLE
+               if(me->drawflag & ME_DRAW_FREESTYLE_EDGE) {
+                       UI_ThemeColor(TH_FREESTYLE_EDGE_MARK);
+                       glLineWidth(2);
+       
+                       draw_dm_edges_freestyle(em, cageDM);
+       
+                       glColor3ub(0,0,0);
+                       glLineWidth(1);
+               }
+#endif
+       
                if (me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
                        draw_dm_creases(em, cageDM);
                }
@@ -3305,7 +3052,8 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
 
                draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
        }
-       if (em) {
+
+       {
                draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d);
 
                if (me->drawflag & ME_DRAWNORMALS) {
@@ -3335,21 +3083,18 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
                bglPolygonOffset(rv3d->dist, 0.0);
                GPU_disable_material();
        }
-
-       EDBM_index_arrays_free(em);
 }
 
 /* Mesh drawing routines */
 
 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
 {
-       
        if ((v3d->transp == FALSE) &&  /* not when we draw the transparent pass */
            (ob->mode & OB_MODE_ALL_PAINT) == FALSE) /* not when painting (its distracting) - campbell */
        {
                glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
                glDepthMask(0);
-               
+
                /* if transparent, we cannot draw the edges for solid select... edges have no material info.
                 * drawFacesSolid() doesn't draw the transparent faces */
                if (ob->dtx & OB_DRAWTRANSP) {
@@ -3368,7 +3113,7 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
 }
 
 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
-                            const short dt, const unsigned char ob_wire_col[4], const short dflag)
+                            const char dt, const unsigned char ob_wire_col[4], const short dflag)
 {
        Object *ob = base->object;
        Mesh *me = ob->data;
@@ -3431,7 +3176,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
                        glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
 
                        dm->drawFacesGLSL(dm, GPU_enable_material);
-//                     if (get_ob_property(ob, "Text"))
+//                     if (BKE_bproperty_object_get(ob, "Text"))
 // XXX                         draw_mesh_text(ob, 1);
                        GPU_disable_material();
 
@@ -3577,7 +3322,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
                        glDepthMask(0);  /* disable write in zbuffer, selected edge wires show better */
                }
                
-               dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), me->drawflag & ME_ALLEDGES);
+               dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), (ob->dtx & OB_DRAW_ALL_EDGES));
 
                if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) {
                        glDepthMask(1);
@@ -3586,11 +3331,15 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
        }
        
        if (is_obact && paint_vertsel_test(ob)) {
-               
+               const int use_depth = (v3d->flag & V3D_ZBUF_SELECT);
                glColor3f(0.0f, 0.0f, 0.0f);
                glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-               
+
+               if (!use_depth) glDisable(GL_DEPTH_TEST);
+               else            bglPolygonOffset(rv3d->dist, 1.0);
                drawSelectedVertices(dm, ob->data);
+               if (!use_depth) glEnable(GL_DEPTH_TEST);
+               else            bglPolygonOffset(rv3d->dist, 0.0);
                
                glPointSize(1.0f);
        }
@@ -3599,7 +3348,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
 
 /* returns 1 if nothing was drawn, for detecting to draw an object center */
 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
-                            const short dt, const unsigned char ob_wire_col[4], const short dflag)
+                            const char dt, const unsigned char ob_wire_col[4], const short dflag)
 {
        Object *ob = base->object;
        Object *obedit = scene->obedit;
@@ -3619,7 +3368,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
        }
        
        if (obedit && ob != obedit && ob->data == obedit->data) {
-               if (ob_get_key(ob) || ob_get_key(obedit)) {}
+               if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {}
                else if (ob->modifiers.first || obedit->modifiers.first) {}
                else drawlinked = 1;
        }
@@ -3671,7 +3420,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
                }
        }
        
-       if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0) {
+       if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
                /* GPU_begin_object_materials checked if this is needed */
                if (do_alpha_after) {
                        if (ob->dtx & OB_DRAWXRAY) {
@@ -3763,7 +3512,7 @@ static int drawDispListwire(ListBase *dlbase)
 
 #if 0
                                /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
-                               glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3*nr);
+                               glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3 * nr);
                                if (dl->flag & DL_CYCL_V)
                                        glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
                                else
@@ -3794,7 +3543,7 @@ static int drawDispListwire(ListBase *dlbase)
        return 0;
 }
 
-static void drawDispListsolid(ListBase *lb, Object *ob,
+static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
                               const unsigned char ob_wire_col[4], int use_glsl)
 {
        DispList *dl;
@@ -3825,7 +3574,9 @@ static void drawDispListsolid(ListBase *lb, Object *ob,
                                        int nr;
 
                                        glDisable(GL_LIGHTING);
-                                       glColor3ubv(ob_wire_col);
+
+                                       if ((dflag & DRAW_CONSTCOLOR) == 0)
+                                               glColor3ubv(ob_wire_col);
 
                                        // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
                                        // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
@@ -3919,7 +3670,7 @@ static void drawCurveDMWired(Object *ob)
 }
 
 /* return 1 when nothing was drawn */
-static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const short dt)
+static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt)
 {
        Object *ob = base->object;
        DerivedMesh *dm = ob->derivedFinal;
@@ -3950,9 +3701,12 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B
        return 0;
 }
 
-/* returns 1 when nothing was drawn */
-static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
-                        const short dt, const unsigned char ob_wire_col[4])
+/**
+ * Only called by #drawDispList
+ * \return 1 when nothing was drawn
+ */
+static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+                                   const char dt, const short dflag, const unsigned char ob_wire_col[4])
 {
        Object *ob = base->object;
        ListBase *lb = NULL;
@@ -3960,20 +3714,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
        Curve *cu;
        const short render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE);
        const short solid = (dt > OB_WIRE);
-       int retval = 0;
-
-       /* backface culling */
-       if (v3d->flag2 & V3D_BACKFACE_CULLING) {
-               /* not all displists use same in/out normal direction convention */
-               glEnable(GL_CULL_FACE);
-               glCullFace((ob->type == OB_MBALL) ? GL_BACK : GL_FRONT);
-       }
 
        if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == 0) {
-               if (v3d->flag2 & V3D_BACKFACE_CULLING)
-                       glDisable(GL_CULL_FACE);
-
-               return 0;
+               return FALSE;
        }
 
        switch (ob->type) {
@@ -3985,7 +3728,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
 
                        if (solid) {
                                dl = lb->first;
-                               if (dl == NULL) return 1;
+                               if (dl == NULL) {
+                                       return TRUE;
+                               }
 
                                if (dl->nors == NULL) BKE_displist_normals_add(lb);
                                index3_nors_incr = 0;
@@ -4000,12 +3745,12 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
                                else {
                                        if (draw_glsl_material(scene, ob, v3d, dt)) {
                                                GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
-                                               drawDispListsolid(lb, ob, ob_wire_col, TRUE);
+                                               drawDispListsolid(lb, ob, dflag, ob_wire_col, TRUE);
                                                GPU_end_object_materials();
                                        }
                                        else {
                                                GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
-                                               drawDispListsolid(lb, ob, ob_wire_col, FALSE);
+                                               drawDispListsolid(lb, ob, dflag, ob_wire_col, FALSE);
                                                GPU_end_object_materials();
                                        }
                                        if (cu->editnurb && cu->bevobj == NULL && cu->taperobj == NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) {
@@ -4019,9 +3764,11 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
                        }
                        else {
                                if (!render_only || (render_only && BKE_displist_has_faces(lb))) {
+                                       int retval;
                                        draw_index_wire = 0;
                                        retval = drawDispListwire(lb);
                                        draw_index_wire = 1;
+                                       return retval;
                                }
                        }
                        break;
@@ -4031,23 +3778,25 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
 
                        if (solid) {
                                dl = lb->first;
-                               if (dl == NULL) return 1;
+                               if (dl == NULL) {
+                                       return TRUE;
+                               }
 
                                if (dl->nors == NULL) BKE_displist_normals_add(lb);
 
                                if (draw_glsl_material(scene, ob, v3d, dt)) {
                                        GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
-                                       drawDispListsolid(lb, ob, ob_wire_col, TRUE);
+                                       drawDispListsolid(lb, ob, dflag, ob_wire_col, TRUE);
                                        GPU_end_object_materials();
                                }
                                else {
                                        GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
-                                       drawDispListsolid(lb, ob, ob_wire_col, FALSE);
+                                       drawDispListsolid(lb, ob, dflag, ob_wire_col, FALSE);
                                        GPU_end_object_materials();
                                }
                        }
                        else {
-                               retval = drawDispListwire(lb);
+                               return drawDispListwire(lb);
                        }
                        break;
                case OB_MBALL:
@@ -4055,31 +3804,50 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
                        if (BKE_mball_is_basis(ob)) {
                                lb = &ob->disp;
                                if (lb->first == NULL) BKE_displist_make_mball(scene, ob);
-                               if (lb->first == NULL) return 1;
+                               if (lb->first == NULL) {
+                                       return TRUE;
+                               }
 
                                if (solid) {
 
                                        if (draw_glsl_material(scene, ob, v3d, dt)) {
                                                GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
-                                               drawDispListsolid(lb, ob, ob_wire_col, TRUE);
+                                               drawDispListsolid(lb, ob, dflag, ob_wire_col, TRUE);
                                                GPU_end_object_materials();
                                        }
                                        else {
                                                GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
-                                               drawDispListsolid(lb, ob, ob_wire_col, FALSE);
+                                               drawDispListsolid(lb, ob, dflag, ob_wire_col, FALSE);
                                                GPU_end_object_materials();
                                        }
                                }
                                else {
                                        /* MetaBalls use DL_INDEX4 type of DispList */
-                                       retval = drawDispListwire(lb);
+                                       return drawDispListwire(lb);
                                }
                        }
                        break;
        }
-       
-       if (v3d->flag2 & V3D_BACKFACE_CULLING)
+
+       return FALSE;
+}
+static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+                        const char dt, const short dflag, const unsigned char ob_wire_col[4])
+{
+       int retval;
+
+       /* backface culling */
+       if (v3d->flag2 & V3D_BACKFACE_CULLING) {
+               /* not all displists use same in/out normal direction convention */
+               glEnable(GL_CULL_FACE);
+               glCullFace((base->object->type == OB_MBALL) ? GL_BACK : GL_FRONT);
+       }
+
+       retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+
+       if (v3d->flag2 & V3D_BACKFACE_CULLING) {
                glDisable(GL_CULL_FACE);
+       }
 
        return retval;
 }
@@ -4784,7 +4552,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 
                if (cdata2)
                        MEM_freeN(cdata2);
-               /* cd2= */ /* UNUSED */ cdata2 = NULL;
+               /* cd2 = */ /* UNUSED */ cdata2 = NULL;
 
                glLineWidth(1.0f);
 
@@ -4987,9 +4755,11 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
                                if (!(point->flag & PEP_HIDE))
                                        totkeys += point->totkey;
 
-                       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");
+                       if (totkeys) {
+                               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");
+                       }
 
                        for (i = 0, point = edit->points; i < totpoint; i++, point++) {
                                if (point->flag & PEP_HIDE)
@@ -5226,9 +4996,9 @@ static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, flo
        glEnd();
 }
 
-/*place to add drawers */
+/* place to add drawers */
 
-static void tekenhandlesN(Nurb *nu, short sel, short hide_handles)
+static void drawhandlesN(Nurb *nu, short sel, short hide_handles)
 {
        BezTriple *bezt;
        float *fp;
@@ -5288,7 +5058,7 @@ static void tekenhandlesN(Nurb *nu, short sel, short hide_handles)
        glEnd();
 }
 
-static void tekenhandlesN_active(Nurb *nu)
+static void drawhandlesN_active(Nurb *nu)
 {
        BezTriple *bezt;
        float *fp;
@@ -5323,7 +5093,7 @@ static void tekenhandlesN_active(Nurb *nu)
        glLineWidth(1);
 }
 
-static void tekenvertsN(Nurb *nu, short sel, short hide_handles, void *lastsel)
+static void drawvertsN(Nurb *nu, short sel, short hide_handles, void *lastsel)
 {
        BezTriple *bezt;
        BPoint *bp;
@@ -5579,7 +5349,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
 }
 
 static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb,
-                     const short dt, const unsigned char ob_wire_col[4])
+                     const char dt, const short dflag, const unsigned char ob_wire_col[4])
 {
        ToolSettings *ts = scene->toolsettings;
        Object *ob = base->object;
@@ -5594,7 +5364,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
        UI_GetThemeColor3ubv(TH_WIRE, wire_col);
        glColor3ubv(wire_col);
 
-       drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col);
+       drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
 
        if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
        
@@ -5603,8 +5373,8 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
        for (nu = nurb; nu; nu = nu->next) {
                if (nu->type == CU_BEZIER) {
                        if (index == cu->actnu && !hide_handles)
-                               tekenhandlesN_active(nu);
-                       tekenhandlesN(nu, 0, hide_handles);
+                               drawhandlesN_active(nu);
+                       drawhandlesN(nu, 0, hide_handles);
                }
                index++;
        }
@@ -5613,8 +5383,8 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
        /* selected handles */
        for (nu = nurb; nu; nu = nu->next) {
                if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0)
-                       tekenhandlesN(nu, 1, hide_handles);
-               tekenvertsN(nu, 0, hide_handles, NULL);
+                       drawhandlesN(nu, 1, hide_handles);
+               drawvertsN(nu, 0, hide_handles, NULL);
        }
        
        if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -5665,7 +5435,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
        if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
        
        for (nu = nurb; nu; nu = nu->next) {
-               tekenvertsN(nu, 1, hide_handles, cu->lastsel);
+               drawvertsN(nu, 1, hide_handles, cu->lastsel);
        }
        
        if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -5727,43 +5497,10 @@ static void draw_empty_cone(float size)
        gluDeleteQuadric(qobj);
 }
 
-/* draw points on curve speed handles */
-#if 0  /* XXX old animation system stuff */
-static void curve_draw_speed(Scene *scene, Object *ob)
-{
-       Curve *cu = ob->data;
-       IpoCurve *icu;
-       BezTriple *bezt;
-       float loc[4], dir[3];
-       int a;
-       
-       if (cu->ipo == NULL)
-               return;
-       
-       icu = cu->ipo->curve.first;
-       if (icu == NULL || icu->totvert < 2)
-               return;
-       
-       glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-       bglBegin(GL_POINTS);
-
-       for (a = 0, bezt = icu->bezt; a < icu->totvert; a++, bezt++) {
-               if (where_on_path(ob, bezt->vec[1][1], loc, dir)) {
-                       UI_ThemeColor((bezt->f2 & SELECT) && ob == OBACT ? TH_VERTEX_SELECT : TH_VERTEX);
-                       bglVertex3fv(loc);
-               }
-       }
-
-       glPointSize(1.0);
-       bglEnd();
-}
-#endif  /* XXX old animation system stuff */
-
-
-static void draw_textcurs(float textcurs[4][2])
+static void draw_textcurs(RegionView3D *rv3d, float textcurs[4][2])
 {
        cpack(0);
-       
+       bglPolygonOffset(rv3d->dist, -1.0);
        set_inverted_drawing(1);
        glBegin(GL_QUADS);
        glVertex2fv(textcurs[0]);
@@ -5772,9 +5509,10 @@ static void draw_textcurs(float textcurs[4][2])
        glVertex2fv(textcurs[3]);
        glEnd();
        set_inverted_drawing(0);
+       bglPolygonOffset(rv3d->dist, 0.0);
 }
 
-static void drawspiral(const float cent[3], float rad, float tmat[][4], int start)
+static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start)
 {
        float vec[3], vx[3], vy[3];
        const float tot_inv = (1.0f / (float)CIRCLE_RESOL);
@@ -5840,7 +5578,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[][4], int star
        glEnd();
 }
 
-/* draws a circle on x-z plane given the scaling of the circle, assuming that 
+/* draws a circle on x-z plane given the scaling of the circle, assuming that
  * all required matrices have been set (used for drawing empties)
  */
 static void drawcircle_size(float size)
@@ -5850,7 +5588,7 @@ static void drawcircle_size(float size)
 
        glBegin(GL_LINE_LOOP);
 
-       /* coordinates are: cos(degrees*11.25)=x, sin(degrees*11.25)=y, 0.0f=z */
+       /* coordinates are: cos(degrees * 11.25) = x, sin(degrees*11.25) = y, 0.0f = z */
        for (degrees = 0; degrees < CIRCLE_RESOL; degrees++) {
                x = cosval[degrees];
                y = sinval[degrees];
@@ -5862,8 +5600,8 @@ static void drawcircle_size(float size)
 
 }
 
-/* needs fixing if non-identity matrice used */
-static void drawtube(const float vec[3], float radius, float height, float tmat[][4])
+/* needs fixing if non-identity matrix used */
+static void drawtube(const float vec[3], float radius, float height, float tmat[4][4])
 {
        float cur[3];
        drawcircball(GL_LINE_LOOP, vec, radius, tmat);
@@ -5884,8 +5622,9 @@ static void drawtube(const float vec[3], float radius, float height, float tmat[
        glVertex3f(cur[0], cur[1] - radius, cur[2]);
        glEnd();
 }
-/* needs fixing if non-identity matrice used */
-static void drawcone(const float vec[3], float radius, float height, float tmat[][4])
+
+/* needs fixing if non-identity matrix used */
+static void drawcone(const float vec[3], float radius, float height, float tmat[4][4])
 {
        float cur[3];
 
@@ -5905,9 +5644,10 @@ static void drawcone(const float vec[3], float radius, float height, float tmat[
        glVertex3f(cur[0], cur[1] - radius, cur[2]);
        glEnd();
 }
+
 /* return TRUE if nothing was drawn */
 static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
-                     const short dt, const short dflag, const unsigned char ob_wire_col[4])
+                     const char dt, const short dflag, const unsigned char ob_wire_col[4])
 {
        Object *ob = base->object;
        MetaBall *mb;
@@ -5919,17 +5659,17 @@ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
 
        if (mb->editelems) {
                if ((G.f & G_PICKSEL) == 0) {
-                       unsigned char wire_col[3];
-                       UI_GetThemeColor3ubv(TH_WIRE, wire_col);
+                       unsigned char wire_col[4];
+                       UI_GetThemeColor4ubv(TH_WIRE, wire_col);
                        glColor3ubv(wire_col);
 
-                       drawDispList(scene, v3d, rv3d, base, dt, wire_col);
+                       drawDispList(scene, v3d, rv3d, base, dt, dflag, wire_col);
                }
                ml = mb->editelems->first;
        }
        else {
                if ((base->flag & OB_FROMDUPLI) == 0) {
-                       drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col);
+                       drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
                }
                ml = mb->elems.first;
        }
@@ -5953,7 +5693,6 @@ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
        }
        
        while (ml) {
-
                /* draw radius */
                if (mb->editelems) {
                        if ((dflag & DRAW_CONSTCOLOR) == 0) {
@@ -6540,6 +6279,34 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_
        r_ob_wire_col[3] = 255;
 }
 
+static void draw_object_matcap_check(Scene *scene, View3D *v3d, Object *ob)
+{
+       /* fixed rule, active object draws as matcap */
+       if (ob == OBACT) {
+               if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))
+                       return;
+                       
+               if (v3d->defmaterial == NULL) {
+                       extern Material defmaterial;
+                       
+                       v3d->defmaterial = MEM_mallocN(sizeof(Material), "matcap material");
+                       *(v3d->defmaterial) = defmaterial;
+                       v3d->defmaterial->gpumaterial.first = v3d->defmaterial->gpumaterial.last = NULL;
+                       v3d->defmaterial->preview = NULL;
+               }
+               /* first time users */
+               if (v3d->matcap_icon == 0)
+                       v3d->matcap_icon = ICON_MATCAP_01;
+               
+               if (v3d->defmaterial->preview == NULL)
+                       v3d->defmaterial->preview = UI_icon_to_preview(v3d->matcap_icon);
+               
+               /* signal to all material checks, gets cleared below */
+               v3d->flag2 |= V3D_SHOW_SOLID_MATCAP;
+       }
+
+}
+
 /**
  * main object drawing function, draws in selection
  * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET
@@ -6556,7 +6323,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
        unsigned char _ob_wire_col[4];      /* dont initialize this */
        unsigned char *ob_wire_col = NULL;  /* dont initialize this, use NULL crashes as a way to find invalid use */
        int i, selstart, selend, empty_object = 0;
-       short dt, dtx, zbufoff = 0;
+       short dtx;
+       char  dt;
+       short zbufoff = 0;
        const short is_obact = (ob == OBACT);
 
        /* only once set now, will be removed too, should become a global standard */
@@ -6578,7 +6347,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                return;
 
        /* xray delay? */
-       if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0) {
+       if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
                /* don't do xray in particle mode, need the z-buffer */
                if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
                        /* xray and transp are set when it is drawing the 2nd/3rd pass */
@@ -6613,7 +6382,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
        /* which wire color */
        if ((dflag & DRAW_CONSTCOLOR) == 0) {
 
-               project_short(ar, ob->obmat[3], &base->sx);
+               ED_view3d_project_base(ar, base);
 
                draw_object_wire_color(scene, base, _ob_wire_col, warning_recursive);
                ob_wire_col = _ob_wire_col;
@@ -6627,6 +6396,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
        dt = MIN2(dt, ob->dt);
        if (v3d->zbuf == 0 && dt > OB_WIRE) dt = OB_WIRE;
        dtx = 0;
+       
+       /* matcap check */
+       if (dt == OB_SOLID && (v3d->flag2 & V3D_SOLID_MATCAP))
+               draw_object_matcap_check(scene, v3d, ob);
 
        /* faceselect exception: also draw solid when (dt == wire), except in editmode */
        if (is_obact && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
@@ -6692,16 +6465,16 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                case OB_FONT:
                        cu = ob->data;
                        if (cu->editfont) {
-                               draw_textcurs(cu->editfont->textcurs);
+                               draw_textcurs(rv3d, cu->editfont->textcurs);
 
                                if (cu->flag & CU_FAST) {
                                        cpack(0xFFFFFF);
                                        set_inverted_drawing(1);
-                                       drawDispList(scene, v3d, rv3d, base, OB_WIRE, ob_wire_col);
+                                       drawDispList(scene, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col);
                                        set_inverted_drawing(0);
                                }
                                else {
-                                       drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col);
+                                       drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
                                }
 
                                if (cu->linewidth != 0.0f) {
@@ -6776,7 +6549,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                                }
                        }
                        else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
-                               empty_object = drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col);
+                               empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
                        }
 
                        break;
@@ -6786,7 +6559,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
 
                        if (cu->editnurb) {
                                ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-                               drawnurb(scene, v3d, rv3d, base, nurbs->first, dt, ob_wire_col);
+                               drawnurb(scene, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col);
                        }
                        else if (dt == OB_BOUNDBOX) {
                                if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && (v3d->drawtype >= OB_WIRE)) == 0) {
@@ -6794,7 +6567,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                                }
                        }
                        else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
-                               empty_object = drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col);
+                               empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
 
 //XXX old animsys                              if (cu->path)
 //                                  curve_draw_speed(scene, ob);
@@ -6897,7 +6670,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
        /* code for new particle system */
        if ((warning_recursive == 0) &&
            (ob->particlesystem.first) &&
-           (dflag & DRAW_PICKING) == 0 &&
            (ob != scene->obedit)
            )
        {
@@ -6985,72 +6757,76 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                }
 
                /* only draw domains */
-               if (smd->domain && smd->domain->fluid) {
-                       if (CFRA < smd->domain->point_cache[0]->startframe) {
-                               /* don't show smoke before simulation starts, this could be made an option in the future */
-                       }
-                       else if (!smd->domain->wt || !(smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
-// #if 0
-                               smd->domain->tex = NULL;
-                               GPU_create_smoke(smd, 0);
-                               draw_volume(ar, smd->domain->tex,
-                                           smd->domain->p0, smd->domain->p1,
-                                           smd->domain->res, smd->domain->dx,
-                                           smd->domain->tex_shadow);
-                               GPU_free_smoke(smd);
-// #endif
-#if 0
-                               int x, y, z;
-                               float *density = smoke_get_density(smd->domain->fluid);
+               if (smd->domain) {
+                       SmokeDomainSettings *sds = smd->domain;
+                       float p0[3], p1[3], viewnormal[3];
+                       BoundBox bb;
 
-                               glLoadMatrixf(rv3d->viewmat);
-                               // glMultMatrixf(ob->obmat);
+                       glLoadMatrixf(rv3d->viewmat);
+                       glMultMatrixf(ob->obmat);
 
-                               if (col || (ob->flag & SELECT)) cpack(0xFFFFFF);
-                               glDepthMask(GL_FALSE);
-                               glEnable(GL_BLEND);
-                               
+                       /* draw adaptive domain bounds */
+                       if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
+                               /* draw domain max bounds */
+                               VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res);
+                               VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res);
+                               BKE_boundbox_init_from_minmax(&bb, p0, p1);
+                               draw_box(bb.vec);
 
-                               // glPointSize(3.0);
-                               bglBegin(GL_POINTS);
+                               /* draw base resolution bounds */
+#if 0
+                               BKE_boundbox_init_from_minmax(&bb, sds->p0, sds->p1);
+                               draw_box(bb.vec);
+#endif
+                       }
 
-                               for (x = 0; x < smd->domain->res[0]; x++) {
-                                       for (y = 0; y < smd->domain->res[1]; y++) {
-                                               for (z = 0; z < smd->domain->res[2]; z++) {
-                                                       float tmp[3];
-                                                       int index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z);
-
-                                                       if (density[index] > FLT_EPSILON) {
-                                                               float color[3];
-                                                               copy_v3_v3(tmp, smd->domain->p0);
-                                                               tmp[0] += smd->domain->dx * x + smd->domain->dx * 0.5;
-                                                               tmp[1] += smd->domain->dx * y + smd->domain->dx * 0.5;
-                                                               tmp[2] += smd->domain->dx * z + smd->domain->dx * 0.5;
-                                                               color[0] = color[1] = color[2] = density[index];
-                                                               glColor3fv(color);
-                                                               bglVertex3fv(tmp);
-                                                       }
-                                               }
-                                       }
+                       /* don't show smoke before simulation starts, this could be made an option in the future */
+                       if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) {
+
+                               // get view vector
+                               copy_v3_v3(viewnormal, rv3d->viewinv[2]);
+                               mul_mat3_m4_v3(ob->imat, viewnormal);
+                               normalize_v3(viewnormal);
+
+                               /* set dynamic boundaries to draw the volume */
+                               p0[0] = sds->p0[0] + sds->cell_size[0] * sds->res_min[0] + sds->obj_shift_f[0];
+                               p0[1] = sds->p0[1] + sds->cell_size[1] * sds->res_min[1] + sds->obj_shift_f[1];
+                               p0[2] = sds->p0[2] + sds->cell_size[2] * sds->res_min[2] + sds->obj_shift_f[2];
+                               p1[0] = sds->p0[0] + sds->cell_size[0] * sds->res_max[0] + sds->obj_shift_f[0];
+                               p1[1] = sds->p0[1] + sds->cell_size[1] * sds->res_max[1] + sds->obj_shift_f[1];
+                               p1[2] = sds->p0[2] + sds->cell_size[2] * sds->res_max[2] + sds->obj_shift_f[2];
+
+                               /* scale cube to global space to equalize volume slicing on all axises
+                                *  (its scaled back before drawing) */
+                               mul_v3_v3(p0, ob->size);
+                               mul_v3_v3(p1, ob->size);
+
+                               if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
+                                       smd->domain->tex = NULL;
+                                       GPU_create_smoke(smd, 0);
+                                       draw_smoke_volume(sds, ob, sds->tex,
+                                                         p0, p1,
+                                                         sds->res, sds->dx, sds->scale * sds->maxres,
+                                                         viewnormal, sds->tex_shadow, sds->tex_flame);
+                                       GPU_free_smoke(smd);
+                               }
+                               else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
+                                       sds->tex = NULL;
+                                       GPU_create_smoke(smd, 1);
+                                       draw_smoke_volume(sds, ob, sds->tex,
+                                                         p0, p1,
+                                                         sds->res_wt, sds->dx, sds->scale * sds->maxres,
+                                                         viewnormal, sds->tex_shadow, sds->tex_flame);
+                                       GPU_free_smoke(smd);
                                }
 
-                               bglEnd();
-                               glPointSize(1.0);
-
-                               glMultMatrixf(ob->obmat);
-                               glDisable(GL_BLEND);
-                               glDepthMask(GL_TRUE);
-                               if (col) cpack(col);
+                               /* smoke debug render */
+#ifdef SMOKE_DEBUG_VELOCITY
+                               draw_smoke_velocity(smd->domain, ob);
+#endif
+#ifdef SMOKE_DEBUG_HEAT
+                               draw_smoke_heat(smd->domain, ob);
 #endif
-                       }
-                       else if (smd->domain->wt && (smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
-                               smd->domain->tex = NULL;
-                               GPU_create_smoke(smd, 1);
-                               draw_volume(ar, smd->domain->tex,
-                                           smd->domain->p0, smd->domain->p1,
-                                           smd->domain->res_wt, smd->domain->dx_wt,
-                                           smd->domain->tex_shadow);
-                               GPU_free_smoke(smd);
                        }
                }
        }
@@ -7067,7 +6843,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                }
 
                if (ob->gameflag & OB_BOUNDS) {
-                       if (ob->boundtype != ob->collision_boundtype || (dtx & OB_BOUNDBOX) == 0) {
+                       if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) {
 
                                setlinestyle(2);
                                draw_bounding_volume(scene, ob, ob->collision_boundtype);
@@ -7081,7 +6857,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                        if (dtx & OB_AXIS) {
                                drawaxes(1.0f, OB_ARROWS);
                        }
-                       if (dtx & OB_BOUNDBOX) {
+                       if (dtx & OB_DRAWBOUNDOX) {
                                draw_bounding_volume(scene, ob, ob->boundtype);
                        }
                        if (dtx & OB_TEXSPACE) {
@@ -7124,7 +6900,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
        /* return warning, this is cached text draw */
        invert_m4_m4(ob->imat, ob->obmat);
        view3d_cached_text_draw_end(v3d, ar, 1, NULL);
-
+       /* return warning, clear temp flag */
+       v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP;
+       
        glLoadMatrixf(rv3d->viewmat);
 
        if (zbufoff) {
@@ -7139,7 +6917,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
        }
 
        /* object centers, need to be drawn in viewmat space for speed, but OK for picking select */
-       if (!is_obact || !(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
+       if (!is_obact || !(ob->mode & OB_MODE_ALL_PAINT)) {
                int do_draw_center = -1; /* defines below are zero or positive... */
 
                if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
@@ -7198,10 +6976,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                        UI_make_axis_color(col1, col2, 'Z');
                        glColor3ubv(col2);
                        
-                       cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+                       cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
                        
                        for (curcon = list->first; curcon; curcon = curcon->next) {
-                               bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
+                               bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
                                ListBase targets = {NULL, NULL};
                                bConstraintTarget *ct;
                                
@@ -7232,7 +7010,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                                                setlinestyle(0);
                                        }
                                }
-                               else if ((curcon->flag & CONSTRAINT_EXPAND) && (cti) && (cti->get_constraint_targets)) {
+                               else if ((curcon->flag & CONSTRAINT_EXPAND) && (cti->get_constraint_targets)) {
                                        cti->get_constraint_targets(curcon, &targets);
                                        
                                        for (ct = targets.first; ct; ct = ct->next) {
@@ -7255,7 +7033,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                                }
                        }
                        
-                       constraints_clear_evalob(cob);
+                       BKE_constraints_clear_evalob(cob);
                }
        }
 
@@ -7312,7 +7090,7 @@ static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
        dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, ptrs);
        bglEnd();
        glPointSize(1.0);
-}              
+}
 
 static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index)
 {
@@ -7332,7 +7110,7 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
 {
        void *ptrs[2] = {(void *)(intptr_t) offset, em};
        dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, ptrs);
-}              
+}
 
 static DMDrawOption bbs_mesh_solid__setSolidDrawOptions(void *userData, int index)
 {
@@ -7416,14 +7194,28 @@ static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index)
                return DM_DRAW_OPTION_SKIP;
        }
 }
-static void bbs_mesh_solid(Scene *scene, Object *ob)
+
+static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
+{
+       Mesh *me = ob->data;
+       DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
+       glColor3ub(0, 0, 0);
+
+       dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, 0);
+
+       bbs_obmode_mesh_verts(ob, dm, 1);
+       bm_vertoffs = me->totvert + 1;
+       dm->release(dm);
+}
+
+static void bbs_mesh_solid_faces(Scene *scene, Object *ob)
 {
        DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
        Mesh *me = (Mesh *)ob->data;
        
        glColor3ub(0, 0, 0);
 
-       if ((me->editflag & ME_EDIT_PAINT_MASK))
+       if ((me->editflag & ME_EDIT_PAINT_FACE_SEL))
                dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, GPU_enable_material, NULL, me, 0);
        else
                dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, GPU_enable_material, NULL, me, 0);
@@ -7448,7 +7240,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
 
                                DerivedMesh *dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
 
-                               EDBM_index_arrays_init(em, 1, 1, 1);
+                               EDBM_index_arrays_ensure(em, BM_VERT | BM_EDGE | BM_FACE);
 
                                bbs_mesh_solid_EM(em, scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
                                if (ts->selectmode & SCE_SELECT_FACE)
@@ -7474,27 +7266,17 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
                                bglPolygonOffset(rv3d->dist, 0.0);
 
                                dm->release(dm);
-
-                               EDBM_index_arrays_free(em);
                        }
                        else {
                                Mesh *me = ob->data;
-                               if ((me->editflag & ME_EDIT_VERT_SEL) &&
+                               if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) &&
                                    /* currently vertex select only supports weight paint */
                                    (ob->mode & OB_MODE_WEIGHT_PAINT))
                                {
-                                       DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
-                                       glColor3ub(0, 0, 0);
-
-                                       dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, 0);
-
-
-                                       bbs_obmode_mesh_verts(ob, dm, 1);
-                                       bm_vertoffs = me->totvert + 1;
-                                       dm->release(dm);
+                                       bbs_mesh_solid_verts(scene, ob);
                                }
                                else {
-                                       bbs_mesh_solid(scene, ob);
+                                       bbs_mesh_solid_faces(scene, ob);
                                }
                        }
                        break;
@@ -7511,7 +7293,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
 /*               assumes all matrices/etc set OK */
 
 /* helper function for drawing object instances - meshes */
-static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, 
+static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d,
                                       Object *ob, const short dt, int outline)
 {
        Mesh *me = ob->data;
@@ -7560,7 +7342,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
        if (dm) dm->release(dm);
 }
 
-void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const short dt, int outline)
+void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline)
 {
        if (ob == NULL)
                return;