svn merge ^/trunk/blender -r43381:43392
authorCampbell Barton <ideasman42@gmail.com>
Sun, 15 Jan 2012 10:33:41 +0000 (10:33 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 15 Jan 2012 10:33:41 +0000 (10:33 +0000)
1  2 
release/scripts/startup/bl_ui/space_view3d.py
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/object/object_ops.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/makesrna/intern/rna_scene.c

index c05bc3cb72670cf8285a644b61557aa66dd6ea00,715a90bd7ecc341eb0e5f36a4d8333a329436964..8fd54c9d49ac70d0f57a1730b48661cd4596a83b
@@@ -523,10 -523,11 +523,10 @@@ class VIEW3D_MT_select_edit_mesh(Menu)
  
          layout.separator()
  
 -        layout.operator("mesh.select_by_number_vertices", text="Triangles").type = 'TRIANGLES'
 -        layout.operator("mesh.select_by_number_vertices", text="Quads").type = 'QUADS'
 +        layout.operator("mesh.select_by_number_vertices", text = "By Number of Verts")
          if context.scene.tool_settings.mesh_select_mode[2] == False:
              layout.operator("mesh.select_non_manifold", text="Non Manifold")
 -        layout.operator("mesh.select_by_number_vertices", text="Loose Verts/Edges").type = 'OTHER'
 +        layout.operator("mesh.select_loose_verts", text = "Loose Verts/Edges")
          layout.operator("mesh.select_similar", text="Similar")
  
          layout.separator()
@@@ -645,8 -646,8 +645,8 @@@ class VIEW3D_MT_select_edit_armature(Me
  
          layout.separator()
  
-         layout.operator("armature.select_all", text="Select/Deselect All")
-         layout.operator("armature.select_inverse", text="Inverse")
+         layout.operator("armature.select_all", text="Select/Deselect All").action = 'TOGGLE'
+         layout.operator("armature.select_all", text="Inverse").action = 'INVERT'
  
          layout.separator()
  
@@@ -1502,9 -1503,7 +1502,9 @@@ class VIEW3D_MT_edit_mesh_specials(Menu
          layout.operator_context = 'INVOKE_REGION_WIN'
  
          layout.operator("mesh.subdivide", text="Subdivide").smoothness = 0.0
 +        """
          layout.operator("mesh.subdivide", text="Subdivide Smooth").smoothness = 1.0
 +        """
          layout.operator("mesh.merge", text="Merge...")
          layout.operator("mesh.remove_doubles")
          layout.operator("mesh.hide", text="Hide")
          layout.operator("mesh.select_all").action = 'INVERT'
          layout.operator("mesh.flip_normals")
          layout.operator("mesh.vertices_smooth", text="Smooth")
 -        layout.operator("mesh.bevel", text="Bevel")
 +        layout.operator("mesh.bevel", text="Bevel")
          layout.operator("mesh.faces_shade_smooth")
          layout.operator("mesh.faces_shade_flat")
          layout.operator("mesh.blend_from_shape")
@@@ -1586,7 -1585,6 +1586,7 @@@ class VIEW3D_MT_edit_mesh_vertices(Menu
          layout.operator("mesh.rip_move")
          layout.operator("mesh.split")
          layout.operator("mesh.separate")
 +        layout.operator("mesh.vert_connect")
  
          layout.separator()
  
@@@ -1635,10 -1633,6 +1635,10 @@@ class VIEW3D_MT_edit_mesh_edges(Menu)
  
          layout.separator()
  
 +        layout.operator("mesh.bridge_edge_loops", text="Bridge Two Edge Loops")
 +
 +        layout.separator()
 +
          layout.operator("TRANSFORM_OT_edge_slide")
          layout.operator("TRANSFORM_OT_edge_crease")
          layout.operator("mesh.loop_multi_select", text="Edge Loop").ring = False
@@@ -1671,6 -1665,11 +1671,6 @@@ class VIEW3D_MT_edit_mesh_faces(Menu)
  
          layout.separator()
  
 -        layout.operator("mesh.fgon_make")
 -        layout.operator("mesh.fgon_clear")
 -
 -        layout.separator()
 -
          layout.operator("mesh.quads_convert_to_tris")
          layout.operator("mesh.tris_convert_to_quads")
          layout.operator("mesh.edge_flip")
          layout.separator()
  
          layout.operator_menu_enum("mesh.uvs_rotate", "direction")
 -        layout.operator_menu_enum("mesh.uvs_mirror", "axis")
 +        layout.operator("mesh.uvs_reverse")
          layout.operator_menu_enum("mesh.colors_rotate", "direction")
 -        layout.operator_menu_enum("mesh.colors_mirror", "axis")
 +        layout.operator("mesh.colors_reverse")
  
  
  class VIEW3D_MT_edit_mesh_normals(Menu):
index 872cfbec9a2a7412dc1f2c3741509a62d841e62f,4f01998872580dd801835f1afeb419d7ae285d4a..ffceaf1c6989e5cf4529cccbdeeff9b840b96c7b
@@@ -57,7 -57,6 +57,7 @@@
  
  /**************************** registration **********************************/
  
 +void EXPORT_MESH_OT_wavefront(wmOperatorType *ot);
  void ED_operatortypes_mesh(void)
  {
        WM_operatortype_append(MESH_OT_select_all);
@@@ -70,7 -69,6 +70,7 @@@
        WM_operatortype_append(MESH_OT_hide);
        WM_operatortype_append(MESH_OT_reveal);
        WM_operatortype_append(MESH_OT_select_by_number_vertices);
 +      WM_operatortype_append(MESH_OT_select_loose_verts);
        WM_operatortype_append(MESH_OT_select_mirror);
        WM_operatortype_append(MESH_OT_normals_make_consistent);
        WM_operatortype_append(MESH_OT_merge);
        WM_operatortype_append(MESH_OT_primitive_monkey_add);
        WM_operatortype_append(MESH_OT_primitive_uv_sphere_add);
        WM_operatortype_append(MESH_OT_primitive_ico_sphere_add);
 -      WM_operatortype_append(MESH_OT_fgon_clear);
 -      WM_operatortype_append(MESH_OT_fgon_make);
        WM_operatortype_append(MESH_OT_duplicate);
        WM_operatortype_append(MESH_OT_remove_doubles);
        WM_operatortype_append(MESH_OT_vertices_sort);
        WM_operatortype_append(MESH_OT_vertices_randomize);
 -      WM_operatortype_append(MESH_OT_extrude);
        WM_operatortype_append(MESH_OT_spin);
        WM_operatortype_append(MESH_OT_screw);
 -      
 +
 +      WM_operatortype_append(MESH_OT_extrude_region);
 +      WM_operatortype_append(MESH_OT_extrude_faces_indiv);
 +      WM_operatortype_append(MESH_OT_extrude_edges_indiv);
 +      WM_operatortype_append(MESH_OT_extrude_verts_indiv);
 +
        WM_operatortype_append(MESH_OT_split);
        WM_operatortype_append(MESH_OT_extrude_repeat);
        WM_operatortype_append(MESH_OT_edge_rotate);
        WM_operatortype_append(MESH_OT_select_axis);
        
        WM_operatortype_append(MESH_OT_uvs_rotate);
 -      WM_operatortype_append(MESH_OT_uvs_mirror);
 +      WM_operatortype_append(MESH_OT_uvs_reverse);
        WM_operatortype_append(MESH_OT_colors_rotate);
 -      WM_operatortype_append(MESH_OT_colors_mirror);
 +      WM_operatortype_append(MESH_OT_colors_reverse);
        
        WM_operatortype_append(MESH_OT_fill);
        WM_operatortype_append(MESH_OT_beautify_fill);
        WM_operatortype_append(MESH_OT_vertices_smooth);
        WM_operatortype_append(MESH_OT_noise);
        WM_operatortype_append(MESH_OT_flip_normals);
 -      WM_operatortype_append(MESH_OT_knife_cut);
 +      //WM_operatortype_append(MESH_OT_knife_cut);
        WM_operatortype_append(MESH_OT_rip);
        WM_operatortype_append(MESH_OT_blend_from_shape);
        WM_operatortype_append(MESH_OT_shape_propagate_to_all);
  
        WM_operatortype_append(MESH_OT_solidify);
        WM_operatortype_append(MESH_OT_select_nth);
 +      WM_operatortype_append(MESH_OT_vert_connect);
 +      WM_operatortype_append(MESH_OT_knifetool);
 +
 +      WM_operatortype_append(MESH_OT_bevel);
 +
 +      WM_operatortype_append(MESH_OT_select_next_loop);
 +      
 +      WM_operatortype_append(EXPORT_MESH_OT_wavefront);
 +      WM_operatortype_append(MESH_OT_bridge_edge_loops);
  
  #ifdef WITH_GAMEENGINE
        WM_operatortype_append(MESH_OT_navmesh_make);
@@@ -176,7 -163,7 +176,7 @@@ static int ED_operator_editmesh_face_se
  {
        Object *obedit= CTX_data_edit_object(C);
        if(obedit && obedit->type==OB_MESH) {
 -              EditMesh *em = ((Mesh *)obedit->data)->edit_mesh;
 +              BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
                if (em && em->selectmode & SCE_SELECT_FACE) {
                        return 1;
                }
@@@ -212,28 -199,31 +212,28 @@@ void ED_operatormacros_mesh(void
  
        ot= WM_operatortype_append_macro("MESH_OT_extrude_region_move", "Extrude Region and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
        ot->description = "Extrude region and move result";
 -      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
 -      RNA_enum_set(otmacro->ptr, "type", 1);
 +      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
        RNA_boolean_set(otmacro->ptr, "mirror", 0);
  
        ot= WM_operatortype_append_macro("MESH_OT_extrude_faces_move", "Extrude Individual Faces and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
        ot->description = "Extrude faces and move result";
 -      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
 -      RNA_enum_set(otmacro->ptr, "type", 2);
 +      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_faces_indiv");
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
        RNA_boolean_set(otmacro->ptr, "mirror", 0);
  
        ot= WM_operatortype_append_macro("MESH_OT_extrude_edges_move", "Extrude Only Edges and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
        ot->description = "Extrude edges and move result";
 -      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
 -      RNA_enum_set(otmacro->ptr, "type", 3);
 +      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv");
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
        RNA_boolean_set(otmacro->ptr, "mirror", 0);
  
        ot= WM_operatortype_append_macro("MESH_OT_extrude_vertices_move", "Extrude Only Vertices and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
        ot->description = "Extrude vertices and move result";
 -      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
 +      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_verts_indiv");
        RNA_enum_set(otmacro->ptr, "type", 4);
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
@@@ -266,8 -256,10 +266,10 @@@ void ED_keymap_mesh(wmKeyConfig *keycon
  
        WM_keymap_add_item(keymap, "MESH_OT_select_shortest_path", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
  
-       WM_keymap_add_item(keymap, "MESH_OT_select_all", AKEY, KM_PRESS, 0, 0);
-       RNA_enum_set(WM_keymap_add_item(keymap, "MESH_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "action", SEL_INVERT);
+       kmi = WM_keymap_add_item(keymap, "MESH_OT_select_all", AKEY, KM_PRESS, 0, 0);
+       RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
+       kmi = WM_keymap_add_item(keymap, "MESH_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
+       RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
  
        WM_keymap_add_item(keymap, "MESH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "MESH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
        
        WM_keymap_add_item(keymap, "MESH_OT_fill", FKEY, KM_PRESS, KM_ALT, 0);
        WM_keymap_add_item(keymap, "MESH_OT_beautify_fill", FKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
 +
        WM_keymap_add_item(keymap, "MESH_OT_quads_convert_to_tris", TKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "MESH_OT_tris_convert_to_quads", JKEY, KM_PRESS, KM_ALT, 0);
        WM_keymap_add_item(keymap, "MESH_OT_edge_flip", FKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
        WM_keymap_add_menu(keymap, "INFO_MT_mesh_add", AKEY, KM_PRESS, KM_SHIFT, 0);
        
        WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, 0, 0);
 -      WM_keymap_add_item(keymap, "MESH_OT_split", YKEY, KM_PRESS, 0, 0);
 +      WM_keymap_add_item(keymap, "MESH_OT_vert_connect", YKEY, KM_PRESS, 0, 0);
  
        /* use KM_CLICK because same key is used for tweaks */
        kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "MESH_OT_delete", XKEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "MESH_OT_delete", DELKEY, KM_PRESS, 0, 0);
        
 -      WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, 0, KKEY);
 -      RNA_enum_set(WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_SHIFT, KKEY)->ptr, "type", 2/*KNIFE_MIDPOINT*/);
 +      WM_keymap_add_item(keymap, "MESH_OT_knifetool", KKEY, KM_PRESS, 0, 0);
 +      //RNA_enum_set(WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_SHIFT, KKEY)->ptr, "type", 2/*KNIFE_MIDPOINT*/);
        
        WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
  
        }
        
        ED_object_generic_keymap(keyconf, keymap, 3);
 +      knifetool_modal_keymap(keyconf);
  }
  
index a86e5f343c17d368e395a1ac4fdc0b38337a36f8,99eeaf334a8410b572bdee84108fabe5324cf3b9..68d11837d0d8d7dc62667befe97b0082741bd9c3
@@@ -214,9 -214,8 +214,9 @@@ void ED_operatortypes_object(void
  
        WM_operatortype_append(OBJECT_OT_bake_image);
        WM_operatortype_append(OBJECT_OT_drop_named_material);
 -}
  
 +      WM_operatortype_append(OBJECT_OT_test_multires);
 +}
  
  void ED_operatormacros_object(void)
  {
@@@ -296,8 -295,10 +296,10 @@@ void ED_keymap_object(wmKeyConfig *keyc
  
        WM_keymap_add_item(keymap, "VIEW3D_OT_game_start", PKEY, KM_PRESS, 0, 0);
  
-       WM_keymap_add_item(keymap, "OBJECT_OT_select_all", AKEY, KM_PRESS, 0, 0);
-       RNA_enum_set(WM_keymap_add_item(keymap, "OBJECT_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "action", SEL_INVERT);
+       kmi = WM_keymap_add_item(keymap, "OBJECT_OT_select_all", AKEY, KM_PRESS, 0, 0);
+               RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
+       kmi = WM_keymap_add_item(keymap, "OBJECT_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
+               RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
  
        WM_keymap_add_item(keymap, "OBJECT_OT_select_linked", LKEY, KM_PRESS, KM_SHIFT, 0);
        WM_keymap_add_item(keymap, "OBJECT_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
        
        kmi= WM_keymap_add_item(keymap, "OBJECT_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0);
                RNA_enum_set_identifier(kmi->ptr, "direction", "PARENT");
+               RNA_boolean_set(kmi->ptr, "extend", FALSE);
        kmi= WM_keymap_add_item(keymap, "OBJECT_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
                RNA_enum_set_identifier(kmi->ptr, "direction", "PARENT");
-               RNA_boolean_set(kmi->ptr, "extend", 1);
+               RNA_boolean_set(kmi->ptr, "extend", TRUE);
  
        kmi= WM_keymap_add_item(keymap, "OBJECT_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
                RNA_enum_set_identifier(kmi->ptr, "direction", "CHILD");
+               RNA_boolean_set(kmi->ptr, "extend", FALSE);
        kmi= WM_keymap_add_item(keymap, "OBJECT_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
                RNA_enum_set_identifier(kmi->ptr, "direction", "CHILD");
-               RNA_boolean_set(kmi->ptr, "extend", 1);
+               RNA_boolean_set(kmi->ptr, "extend", TRUE);
  
        WM_keymap_verify_item(keymap, "OBJECT_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_verify_item(keymap, "OBJECT_OT_parent_no_inverse_set", PKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
index b7c4404c143e7b1398555057f069187ddc505f59,8eeca2e4e15d43531c915e0e3b6fbb47241b5a21..5f4777331c3bc47802e26a86f81cf219e99faf58
@@@ -2937,7 -2937,7 +2937,7 @@@ static void project_paint_begin(ProjPai
        
        MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
  
-       const int diameter= 2*brush_size(ps->brush);
+       const int diameter= 2*brush_size(ps->scene, ps->brush);
        
        /* ---- end defines ---- */
        
        }
        
        ps->dm_mvert = ps->dm->getVertArray(ps->dm);
 -      ps->dm_mface = ps->dm->getFaceArray(ps->dm);
 -      ps->dm_mtface= ps->dm->getFaceDataArray(ps->dm, CD_MTFACE);
 +      ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
 +      ps->dm_mtface= ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE);
        
        ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
 -      ps->dm_totface = ps->dm->getNumFaces(ps->dm);
 +      ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
        
        /* use clone mtface? */
        
@@@ -3580,7 -3580,7 +3580,7 @@@ static int project_bucket_iter_init(Pro
  {
        if(ps->source==PROJ_SRC_VIEW) {
                float min_brush[2], max_brush[2];
-               const float radius = (float)brush_size(ps->brush);
+               const float radius = (float)brush_size(ps->scene, ps->brush);
  
                /* so we dont have a bucket bounds that is way too small to paint into */
                // if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/
  
  static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
  {
-       const int diameter= 2*brush_size(ps->brush);
+       const int diameter= 2*brush_size(ps->scene, ps->brush);
  
        if (ps->thread_tot > 1)
                BLI_lock_thread(LOCK_CUSTOM1);
@@@ -3844,7 -3844,7 +3844,7 @@@ static void *do_projectpaint_thread(voi
        float co[2];
        float mask = 1.0f; /* airbrush wont use mask */
        unsigned short mask_short;
-       const float radius= (float)brush_size(ps->brush);
+       const float radius= (float)brush_size(ps->scene, ps->brush);
        const float radius_squared= radius*radius; /* avoid a square root with every dist comparison */
        
        short lock_alpha= ELEM(ps->brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : ps->brush->flag & BRUSH_LOCK_ALPHA;
                                        if (falloff > 0.0f) {
                                                if (ps->is_texbrush) {
                                                        /* note, for clone and smear, we only use the alpha, could be a special function */
-                                                       brush_sample_tex(ps->brush, projPixel->projCoSS, rgba, thread_index);
+                                                       brush_sample_tex(ps->scene, ps->brush, projPixel->projCoSS, rgba, thread_index);
                                                        alpha = rgba[3];
                                                } else {
                                                        alpha = 1.0f;
                                                
                                                if (ps->is_airbrush) {
                                                        /* for an aurbrush there is no real mask, so just multiply the alpha by it */
-                                                       alpha *= falloff * brush_alpha(ps->brush);
+                                                       alpha *= falloff * brush_alpha(ps->scene, ps->brush);
                                                        mask = ((float)projPixel->mask)/65535.0f;
                                                }
                                                else {
                                                        falloff = 1.0f - falloff;
                                                        falloff = 1.0f - (falloff * falloff);
                                                        
-                                                       mask_short = (unsigned short)(projPixel->mask * (brush_alpha(ps->brush) * falloff));
+                                                       mask_short = (unsigned short)(projPixel->mask * (brush_alpha(ps->scene, ps->brush) * falloff));
                                                        if (mask_short > projPixel->mask_max) {
                                                                mask = ((float)mask_short)/65535.0f;
                                                                projPixel->mask_max = mask_short;
@@@ -4801,7 -4801,7 +4801,7 @@@ static int texture_paint_init(bContext 
        if(pop->mode == PAINT_MODE_3D && (pop->s.tool == PAINT_TOOL_CLONE))
                pop->s.tool = PAINT_TOOL_DRAW;
        pop->s.blend = brush->blend;
-       pop->orig_brush_size= brush_size(brush);
+       pop->orig_brush_size= brush_size(scene, brush);
  
        if(pop->mode != PAINT_MODE_2D) {
                pop->s.ob = OBACT;
                        return 0;
  
                /* Dont allow brush size below 2 */
-               if (brush_size(brush) < 2)
-                       brush_set_size(brush, 2);
+               if (brush_size(scene, brush) < 2)
+                       brush_set_size(scene, brush, 2);
  
                /* allocate and initialize spacial data structures */
                project_paint_begin(&pop->ps);
@@@ -4922,7 -4922,7 +4922,7 @@@ static void paint_exit(bContext *C, wmO
        brush_painter_free(pop->painter);
  
        if(pop->mode == PAINT_MODE_3D_PROJECT) {
-               brush_set_size(pop->ps.brush, pop->orig_brush_size);
+               brush_set_size(scene, pop->ps.brush, pop->orig_brush_size);
                paint_brush_exit_tex(pop->ps.brush);
                
                project_paint_end(&pop->ps);
@@@ -5111,12 -5111,13 +5111,13 @@@ static void brush_drawcursor(bContext *
  #define PX_SIZE_FADE_MAX 12.0f
  #define PX_SIZE_FADE_MIN 4.0f
  
+       Scene *scene= CTX_data_scene(C);
        Brush *brush= image_paint_brush(C);
-       Paint *paint= paint_get_active(CTX_data_scene(C));
+       Paint *paint= paint_get_active(scene);
  
        if(paint && brush && paint->flags & PAINT_SHOW_BRUSH) {
                float zoomx, zoomy;
-               const float size= (float)brush_size(brush);
+               const float size= (float)brush_size(scene, brush);
                const short use_zoom= get_imapaint_zoom(C, &zoomx, &zoomy);
                const float pixel_size= MAX2(size * zoomx, size * zoomy);
                float alpha= 0.5f;
@@@ -5570,8 -5571,8 +5571,8 @@@ static int texture_paint_camera_project
        /* override */
        ps.is_texbrush= 0;
        ps.is_airbrush= 1;
-       orig_brush_size= brush_size(ps.brush);
-       brush_set_size(ps.brush, 32); /* cover the whole image */
+       orig_brush_size= brush_size(scene, ps.brush);
+       brush_set_size(scene, ps.brush, 32); /* cover the whole image */
  
        ps.tool= PAINT_TOOL_DRAW; /* so pixels are initialized with minimal info */
  
        project_paint_begin(&ps);
  
        if(ps.dm==NULL) {
-               brush_set_size(ps.brush, orig_brush_size);
+               brush_set_size(scene, ps.brush, orig_brush_size);
                return OPERATOR_CANCELLED;
        }
        else {
        project_paint_end(&ps);
  
        scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
-       brush_set_size(ps.brush, orig_brush_size);
+       brush_set_size(scene, ps.brush, orig_brush_size);
  
        return OPERATOR_FINISHED;
  }
index cdb82426473032a4d93ac364ecdc47e0f521bad1,c9a60236d0774df581fb8043bf62573bfb428850..ca16e8dfc7cdb9a7015e7c818460bf0f458f9617
  
  #include "BLI_blenlib.h"
  #include "BLI_math.h"
 +#include "BLI_memarena.h"
  #include "BLI_utildefines.h"
  #include "BLI_ghash.h"
 +#include "BLI_cellalloc.h"
  
  #include "IMB_imbuf.h"
  #include "IMB_imbuf_types.h"
  
  #include "paint_intern.h"
  
- /* brush->vertexpaint_tool */
- #define VP_MIX        0
- #define VP_ADD        1
- #define VP_SUB        2
- #define VP_MUL        3
- #define VP_BLUR       4
- #define VP_LIGHTEN    5
- #define VP_DARKEN     6
  /* polling - retrieve whether cursor should be set or operator should be done */
  
  
@@@ -104,7 -93,7 +95,7 @@@ int vertex_paint_mode_poll(bContext *C
  {
        Object *ob = CTX_data_active_object(C);
  
 -      return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totface;
 +      return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totpoly;
  }
  
  int vertex_paint_poll(bContext *C)
@@@ -125,7 -114,7 +116,7 @@@ int weight_paint_mode_poll(bContext *C
  {
        Object *ob = CTX_data_active_object(C);
  
 -      return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totface;
 +      return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totpoly;
  }
  
  int weight_paint_poll(bContext *C)
@@@ -161,7 -150,7 +152,7 @@@ static VPaint *new_vpaint(int wpaint
  
  static int *get_indexarray(Mesh *me)
  {
 -      return MEM_mallocN(sizeof(int)*(me->totface+1), "vertexpaint");
 +      return MEM_mallocN(sizeof(int)*(me->totpoly+1), "vertexpaint");
  }
  
  
@@@ -199,7 -188,7 +190,7 @@@ unsigned int vpaint_get_current_col(VPa
        return rgba_to_mcol(brush->rgb[0], brush->rgb[1], brush->rgb[2], 1.0f);
  }
  
 -static void do_shared_vertexcol(Mesh *me)
 +static void do_shared_vertex_tesscol(Mesh *me)
  {
        /* if no mcol: do not do */
        /* if tface: only the involved faces, otherwise all */
        MEM_freeN(scolmain);
  }
  
 +void do_shared_vertexcol(Mesh *me)
 +{
 +      MLoop *ml = me->mloop;
 +      MLoopCol *lcol = me->mloopcol;
 +      MTexPoly *mtp = me->mtpoly;
 +      MPoly *mp = me->mpoly;
 +      float (*scol)[5];
 +      int i, has_shared = 0;
 +
 +      /* if no mloopcol: do not do */
 +      /* if mtexpoly: only the involved faces, otherwise all */
 +
 +      if(me->mloopcol==0 || me->totvert==0 || me->totpoly==0) return;
 +
 +      scol = MEM_callocN(sizeof(float)*me->totvert*5, "scol");
 +
 +      for (i=0; i<me->totloop; i++, ml++, lcol++) {
 +              if (i >= mp->loopstart + mp->totloop) {
 +                      mp++;
 +                      if (mtp) mtp++;
 +              }
 +
 +              if (!(mtp && (mtp->mode & TF_SHAREDCOL)) && (me->editflag & ME_EDIT_PAINT_MASK)!=0)
 +                      continue;
 +
 +              scol[ml->v][0] += lcol->r;
 +              scol[ml->v][1] += lcol->g;
 +              scol[ml->v][2] += lcol->b;
 +              scol[ml->v][3] += lcol->a;
 +              scol[ml->v][4] += 1.0;
 +              has_shared = 1;
 +      }
 +      
 +      if (has_shared) {
 +              for (i=0; i<me->totvert; i++) {
 +                      if (!scol[i][4]) continue;
 +
 +                      scol[i][0] /= scol[i][4];
 +                      scol[i][1] /= scol[i][4];
 +                      scol[i][2] /= scol[i][4];
 +                      scol[i][3] /= scol[i][4];
 +              }
 +      
 +              ml = me->mloop;
 +              lcol = me->mloopcol;
 +              for (i=0; i<me->totloop; i++, ml++, lcol++) {
 +                      if (!scol[ml->v][4]) continue;
 +
 +                      lcol->r = scol[ml->v][0];
 +                      lcol->g = scol[ml->v][1];
 +                      lcol->b = scol[ml->v][2];
 +                      lcol->a = scol[ml->v][3];
 +              }
 +      }
 +
 +      MEM_freeN(scol);
 +
 +      if (has_shared) {
 +              do_shared_vertex_tesscol(me);
 +      }
 +}
 +
  static void make_vertexcol(Object *ob)        /* single ob */
  {
        Mesh *me;
        if(!ob || ob->id.lib) return;
        me= get_mesh(ob);
        if(me==NULL) return;
 -      if(me->edit_mesh) return;
 +      if(me->edit_btmesh) return;
  
        /* copies from shadedisplist to mcol */
 -      if(!me->mcol) {
 -              CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
 -              mesh_update_customdata_pointers(me);
 +      if(!me->mcol)
 +              CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
 +      if (!me->mloopcol) {
 +              CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);   
 +              mesh_update_customdata_pointers(me, TRUE);
        }
  
        //if(shade)
@@@ -389,7 -314,7 +380,7 @@@ static int wpaint_mirror_vgroup_ensure(
        return -1;
  }
  
 -static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
 +static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot)
  {
        if(vp->vpaint_prev) {
                MEM_freeN(vp->vpaint_prev);
        }
        vp->tot= tot;   
        
 -      if(mcol==NULL || tot==0) return;
 +      if(lcol==NULL || tot==0) return;
        
 -      vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
 -      memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
 +      vp->vpaint_prev= MEM_mallocN(sizeof(int)*tot, "vpaint_prev");
 +      memcpy(vp->vpaint_prev, lcol, sizeof(int)*tot);
        
  }
  
@@@ -423,14 -348,12 +414,14 @@@ static void copy_wpaint_prev (VPaint *w
  void vpaint_fill(Object *ob, unsigned int paintcol)
  {
        Mesh *me;
 -      MFace *mf;
 +      MFace *mf;
 +      MPoly *mp;
 +      MLoopCol *lcol;
        unsigned int *mcol;
 -      int i, selected;
 +      int i, j, selected;
  
        me= get_mesh(ob);
 -      if(me==NULL || me->totface==0) return;
 +      if(me==NULL || me->totpoly==0) return;
  
        if(!me->mcol) make_vertexcol(ob);
        if(!me->mcol) return; /* possible we can't make mcol's */
                        mcol[3] = paintcol;
                }
        }
 +
 +      mp = me->mpoly;
 +      lcol = me->mloopcol;
 +      for (i=0; i<me->totpoly; i++, mp++) {
 +              if (!(!selected || mp->flag & ME_FACE_SEL))
 +                      continue;
 +
 +              lcol = me->mloopcol + mp->loopstart;
 +              for (j=0; j<mp->totloop; j++, lcol++) {
 +                      *(int*)lcol = paintcol;
 +              }
 +      }
        
        DAG_id_tag_update(&me->id, 0);
  }
  void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
  {
        Mesh *me= ob->data;
 -      MFace *mf;
 +      MPoly *mf;
        MDeformWeight *dw, *dw_prev;
        int vgroup_active, vgroup_mirror= -1;
        unsigned int index;
        /* mutually exclusive, could be made into a */
        const short paint_selmode= ME_EDIT_PAINT_SEL_MODE(me);
  
 -      if(me->totface==0 || me->dvert==NULL || !me->mface) return;
 +      if(me->totpoly==0 || me->dvert==NULL || !me->mpoly) return;
        
        vgroup_active = ob->actdef - 1;
  
        
        copy_wpaint_prev(wp, me->dvert, me->totvert);
        
 -      for(index=0, mf= me->mface; index < me->totface; index++, mf++) {
 -              unsigned int fidx= mf->v4 ? 3:2;
 +      for(index=0, mf= me->mpoly; index < me->totpoly; index++, mf++) {
 +              unsigned int fidx= mf->totloop - 1;
  
                if ((paint_selmode == SCE_SELECT_FACE) && !(mf->flag & ME_FACE_SEL)) {
                        continue;
                }
  
                do {
 -                      unsigned int vidx= *(&mf->v1 + fidx);
 +                      unsigned int vidx= me->mloop[mf->loopstart + fidx].v;
  
                        if(!me->dvert[vidx].flag) {
                                if((paint_selmode == SCE_SELECT_VERTEX) && !(me->mvert[vidx].flag & SELECT)) {
  }
  
  /* XXX: should be re-implemented as a vertex/weight paint 'color correct' operator
 - 
 +
  void vpaint_dogamma(Scene *scene)
  {
        VPaint *vp= scene->toolsettings->vpaint;
  
        igam= 1.0/vp->gamma;
        for(a=0; a<256; a++) {
 -              
 +
                fac= ((float)a)/255.0;
                fac= vp->mul*pow( fac, igam);
 -              
 +
                temp= 255.9*fac;
 -              
 +
                if(temp<=0) gamtab[a]= 0;
                else if(temp>=255) gamtab[a]= 255;
                else gamtab[a]= temp;
        a= 4*me->totface;
        cp= (unsigned char *)me->mcol;
        while(a--) {
 -              
 +
                cp[1]= gamtab[ cp[1] ];
                cp[2]= gamtab[ cp[2] ];
                cp[3]= gamtab[ cp[3] ];
 -              
 +
                cp+= 4;
        }
  }
   */
  
 +
  static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
  {
        char *cp1, *cp2, *cp;
@@@ -735,34 -645,51 +726,51 @@@ static unsigned int mcol_darken(unsigne
        return col;
  }
  
- static void vpaint_blend(VPaint *vp, unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha)
+ /* wpaint has 'wpaint_blend_tool' */
+ static unsigned int vpaint_blend_tool(const int tool, const unsigned int col,
+                                       const unsigned int paintcol, const int alpha_i)
+ {
+       switch (tool) {
+               case PAINT_BLEND_MIX:
+               case PAINT_BLEND_BLUR:
+                       return mcol_blend(col, paintcol, alpha_i);
+               case PAINT_BLEND_ADD:
+                       return mcol_add(col, paintcol, alpha_i);
+               case PAINT_BLEND_SUB:
+                       return mcol_sub(col, paintcol, alpha_i);
+               case PAINT_BLEND_MUL:
+                       return mcol_mul(col, paintcol, alpha_i);
+               case PAINT_BLEND_LIGHTEN:
+                       return mcol_lighten(col, paintcol, alpha_i);
+               case PAINT_BLEND_DARKEN:
+                       return mcol_darken(col, paintcol, alpha_i);
+               default:
+                       BLI_assert(0);
+                       return 0;
+       }
+ }
+ /* wpaint has 'wpaint_blend' */
+ static unsigned int vpaint_blend(VPaint *vp, unsigned int col, unsigned int colorig, const
+                                  unsigned int paintcol, const int alpha_i,
+                                  /* pre scaled from [0-1] --> [0-255] */
+                                  const int brush_alpha_value_i)
  {
        Brush *brush = paint_brush(&vp->paint);
+       const int tool = brush->vertexpaint_tool;
+       col = vpaint_blend_tool(tool, col, paintcol, alpha_i);
  
-       if(brush->vertexpaint_tool==VP_MIX || brush->vertexpaint_tool==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha);
-       else if(brush->vertexpaint_tool==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
-       else if(brush->vertexpaint_tool==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
-       else if(brush->vertexpaint_tool==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
-       else if(brush->vertexpaint_tool==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha);
-       else if(brush->vertexpaint_tool==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha);
-       
        /* if no spray, clip color adding with colorig & orig alpha */
        if((vp->flag & VP_SPRAY)==0) {
-               unsigned int testcol=0, a;
+               unsigned int testcol, a;
                char *cp, *ct, *co;
                
-               alpha= (int)(255.0f*brush_alpha(brush));
+               testcol = vpaint_blend_tool(tool, colorig, paintcol, brush_alpha_value_i);
                
-               if(brush->vertexpaint_tool==VP_MIX || brush->vertexpaint_tool==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha);
-               else if(brush->vertexpaint_tool==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha);
-               else if(brush->vertexpaint_tool==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha);
-               else if(brush->vertexpaint_tool==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha);
-               else if(brush->vertexpaint_tool==VP_LIGHTEN)  testcol= mcol_lighten( *colorig, paintcol, alpha);
-               else if(brush->vertexpaint_tool==VP_DARKEN)   testcol= mcol_darken( *colorig, paintcol, alpha);
-               
-               cp= (char *)col;
+               cp= (char *)&col;
                ct= (char *)&testcol;
-               co= (char *)colorig;
+               co= (char *)&colorig;
                
                for(a=0; a<4; a++) {
                        if( ct[a]<co[a] ) {
                        }
                }
        }
+       return col;
  }
  
  
@@@ -817,7 -746,7 +827,7 @@@ static int sample_backbuf_area(ViewCont
  
  /* whats _dl mean? */
  static float calc_vp_strength_dl(VPaint *vp, ViewContext *vc, const float *vert_nor,
-                               const float mval[2], const float brush_size_final)
+                               const float mval[2], const float brush_size_pressure)
  {
        Brush *brush = paint_brush(&vp->paint);
        float dist_squared;
        project_float_noclip(vc->ar, vert_nor, vertco);
        sub_v2_v2v2(delta, mval, vertco);
        dist_squared= dot_v2v2(delta, delta); /* len squared */
-       if (dist_squared > brush_size_final * brush_size_final) {
+       if (dist_squared > brush_size_pressure * brush_size_pressure) {
                return 0.0f;
        }
        else {
                const float dist = sqrtf(dist_squared);
-               return brush_curve_strength_clamp(brush, dist, brush_size_final);
+               return brush_curve_strength_clamp(brush, dist, brush_size_pressure);
        }
  }
  
  static float calc_vp_alpha_dl(VPaint *vp, ViewContext *vc,
                                float vpimat[][3], const float *vert_nor,
                                const float mval[2],
-                               const float brush_size_final, const float brush_alpha_final)
+                               const float brush_size_pressure, const float brush_alpha_pressure)
  {
-       float strength = calc_vp_strength_dl(vp, vc, vert_nor, mval, brush_size_final);
+       float strength = calc_vp_strength_dl(vp, vc, vert_nor, mval, brush_size_pressure);
  
        if (strength > 0.0f) {
-               float alpha= brush_alpha_final * strength;
+               float alpha= brush_alpha_pressure * strength;
  
                if(vp->flag & VP_NORMALS) {
                        float dvec[3];
        return 0.0f;
  }
  
- static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *dw_prev, float alpha, float paintval, int flip, int multipaint)
+ /* vpaint has 'vpaint_blend_tool' */
+ /* result is not clamped from [0-1] */
+ static float wpaint_blend_tool(const int tool,
+                                /* dw->weight */
+                                const float weight,
+                                const float paintval, const float alpha)
+ {
+       switch (tool) {
+               case PAINT_BLEND_MIX:
+               case PAINT_BLEND_BLUR:
+                       return (paintval * alpha) + (weight * (1.0f - alpha));
+               case PAINT_BLEND_ADD:
+                       return (paintval * alpha) + weight;
+               case PAINT_BLEND_SUB:
+                       return (paintval * alpha) - weight;
+               case PAINT_BLEND_MUL:
+                       /* first mul, then blend the fac */
+                       return ((1.0f - alpha) + alpha * paintval) * weight;
+               case PAINT_BLEND_LIGHTEN:
+                       return (weight < paintval) ? (paintval * alpha) + (weight * (1.0f - alpha)) : weight;
+               case PAINT_BLEND_DARKEN:
+                       return (weight > paintval) ? (paintval * alpha) + (weight * (1.0f - alpha)) : weight;
+               default:
+                       BLI_assert(0);
+                       return 0.0f;
+       }
+ }
+ /* vpaint has 'vpaint_blend' */
+ static float wpaint_blend(VPaint *wp, float weight, float weight_prev,
+                           const float alpha, float paintval,
+                           const float brush_alpha_value,
+                           const short do_flip, const short do_multipaint_totsel)
  {
        Brush *brush = paint_brush(&wp->paint);
        int tool = brush->vertexpaint_tool;
  
-       if (flip) {
+       if (do_flip) {
                switch(tool) {
-                       case VP_MIX:
+                       case PAINT_BLEND_MIX:
                                paintval = 1.f - paintval; break;
-                       case VP_ADD:
-                               tool= VP_SUB; break;
-                       case VP_SUB:
-                               tool= VP_ADD; break;
-                       case VP_LIGHTEN:
-                               tool= VP_DARKEN; break;
-                       case VP_DARKEN:
-                               tool= VP_LIGHTEN; break;
-               }
-       }
-       
-       if(tool==VP_MIX || tool==VP_BLUR)
-               dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
-       else if(tool==VP_ADD)
-               dw->weight += paintval*alpha;
-       else if(tool==VP_SUB) 
-               dw->weight -= paintval*alpha;
-       else if(tool==VP_MUL) 
-               /* first mul, then blend the fac */
-               dw->weight = ((1.0f-alpha) + alpha*paintval)*dw->weight;
-       else if(tool==VP_LIGHTEN) {
-               if (dw->weight < paintval)
-                       dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
-       } else if(tool==VP_DARKEN) {
-               if (dw->weight > paintval)
-                       dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
-       }
-       /*  delay clamping until the end so multi-paint can function when the active group is at the limits */
-       if(multipaint == FALSE) {
-               CLAMP(dw->weight, 0.0f, 1.0f);
+                       case PAINT_BLEND_ADD:
+                               tool= PAINT_BLEND_SUB; break;
+                       case PAINT_BLEND_SUB:
+                               tool= PAINT_BLEND_ADD; break;
+                       case PAINT_BLEND_LIGHTEN:
+                               tool= PAINT_BLEND_DARKEN; break;
+                       case PAINT_BLEND_DARKEN:
+                               tool= PAINT_BLEND_LIGHTEN; break;
+               }
+       }
+       
+       weight = wpaint_blend_tool(tool, weight, paintval, alpha);
+       /* delay clamping until the end so multi-paint can function when the active group is at the limits */
+       if(do_multipaint_totsel == FALSE) {
+               CLAMP(weight, 0.0f, 1.0f);
        }
        
        /* if no spray, clip result with orig weight & orig alpha */
-       if((wp->flag & VP_SPRAY)==0) {
-               float testw=0.0f;
-               
-               alpha= brush_alpha(brush);
-               if(tool==VP_MIX || tool==VP_BLUR)
-                       testw = paintval*alpha + dw_prev->weight*(1.0f-alpha);
-               else if(tool==VP_ADD)
-                       testw = dw_prev->weight + paintval*alpha;
-               else if(tool==VP_SUB) 
-                       testw = dw_prev->weight - paintval*alpha;
-               else if(tool==VP_MUL) 
-                       /* first mul, then blend the fac */
-                       testw = ((1.0f-alpha) + alpha*paintval)*dw_prev->weight;
-               else if(tool==VP_LIGHTEN) {
-                       if (dw_prev->weight < paintval)
-                               testw = paintval*alpha + dw_prev->weight*(1.0f-alpha);
-                       else
-                               testw = dw_prev->weight;
-               } else if(tool==VP_DARKEN) {
-                       if (dw_prev->weight > paintval)
-                               testw = paintval*alpha + dw_prev->weight*(1.0f-alpha);
-                       else
-                               testw = dw_prev->weight;
-               }
-               if(multipaint == FALSE) {
+       if ((wp->flag & VP_SPRAY) == 0) {
+               if(do_multipaint_totsel == FALSE) {
+                       float testw = wpaint_blend_tool(tool, weight_prev, paintval, brush_alpha_value);
                        CLAMP(testw, 0.0f, 1.0f);
-                       if( testw<dw_prev->weight ) {
-                               if(dw->weight < testw) dw->weight= testw;
-                               else if(dw->weight > dw_prev->weight) dw->weight= dw_prev->weight;
+                       if (testw < weight_prev) {
+                               if(weight < testw) weight = testw;
+                               else if(weight > weight_prev) weight = weight_prev;
                        }
                        else {
-                               if(dw->weight > testw) dw->weight= testw;
-                               else if(dw->weight < dw_prev->weight) dw->weight= dw_prev->weight;
+                               if (weight > testw) weight = testw;
+                               else if (weight < weight_prev) weight = weight_prev;
                        }
                }
        }
-       
+       return weight;
  }
  
  /* ----------------------------------------------------- */
@@@ -971,14 -897,14 +978,14 @@@ static int weight_sample_invoke(bContex
  
                index= view3d_sample_backbuf(&vc, event->mval[0], event->mval[1]);
  
 -              if(index && index<=me->totface) {
 +              if(index && index<=me->totpoly) {
                        DerivedMesh *dm= mesh_get_derived_final(vc.scene, vc.obact, CD_MASK_BAREMESH);
  
                        if(dm->getVertCo==NULL) {
                                BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
                        }
                        else {
 -                              MFace *mf= ((MFace *)me->mface) + index-1;
 +                              MPoly *mf= ((MPoly *)me->mpoly) + index-1;
                                const int vgroup_active= vc.obact->actdef - 1;
                                ToolSettings *ts= vc.scene->toolsettings;
                                float mval_f[2];
                                mval_f[0]= (float)event->mval[0];
                                mval_f[1]= (float)event->mval[1];
  
 -                              fidx= mf->v4 ? 3:2;
 +                              fidx= mf->totloop - 1;
                                do {
                                        float co[3], sco[3], len;
 -                                      const int v_idx= (*(&mf->v1 + fidx));
 +                                      const int v_idx= me->mloop[mf->loopstart + fidx].v;
                                        dm->getVertCo(dm, v_idx, co);
                                        project_float_noclip(vc.ar, co, sco);
                                        len= len_squared_v2v2(mval_f, sco);
@@@ -1055,16 -981,16 +1062,16 @@@ static EnumPropertyItem *weight_paint_s
  
                                index= view3d_sample_backbuf(&vc, win->eventstate->x - vc.ar->winrct.xmin, win->eventstate->y - vc.ar->winrct.ymin);
  
 -                              if(index && index<=me->totface) {
 +                              if(index && index<=me->totpoly) {
                                        const int defbase_tot= BLI_countlist(&vc.obact->defbase);
                                        if(defbase_tot) {
 -                                              MFace *mf= ((MFace *)me->mface) + index-1;
 -                                              unsigned int fidx= mf->v4 ? 3:2;
 +                                              MPoly *mf= ((MPoly *)me->mpoly) + index-1;
 +                                              unsigned int fidx= mf->totloop - 1;
                                                int *groups= MEM_callocN(defbase_tot*sizeof(int), "groups");
                                                int found= FALSE;
  
                                                do {
 -                                                      MDeformVert *dvert= me->dvert + (*(&mf->v1 + fidx));
 +                                                      MDeformVert *dvert= me->dvert + me->mloop[mf->loopstart + fidx].v;
                                                        int i= dvert->totweight;
                                                        MDeformWeight *dw;
                                                        for(dw= dvert->dw; i > 0; dw++, i--) {
@@@ -1592,6 -1518,8 +1599,8 @@@ typedef struct WeightPaintInfo 
        char do_flip;
        char do_multipaint;
        char do_auto_normalize;
+       float brush_alpha_value;  /* result of brush_alpha() */
  } WeightPaintInfo;
  
  /* fresh start to make multi-paint and locking modular */
@@@ -1609,7 -1537,7 +1618,7 @@@ static int apply_mp_locks_normalize(Mes
        MDeformVert *dv= &me->dvert[index];
        MDeformVert dv_test= {NULL};
  
 -      dv_test.dw= MEM_dupallocN(dv->dw);
 +      dv_test.dw= BLI_cellalloc_dupalloc(dv->dw);
        dv_test.flag = dv->flag;
        dv_test.totweight = dv->totweight;
        /* do not multi-paint if a locked group is selected or the active group is locked
                if(tdw->weight != oldw) {
                        if(neww > oldw) {
                                if(tdw->weight <= oldw) {
 -                                      MEM_freeN(dv_test.dw);
 +                                      BLI_cellalloc_free(dv_test.dw);
                                        return TRUE;
                                }
                        }
                        else {
                                if(tdw->weight >= oldw) {
 -                                      MEM_freeN(dv_test.dw);
 +                                      BLI_cellalloc_free(dv_test.dw);
                                        return TRUE;
                                }
                        }
                }
        }
 -      MEM_freeN(dv_test.dw);
 +      BLI_cellalloc_free(dv_test.dw);
        return FALSE;
  }
  
@@@ -1676,9 -1604,9 +1685,9 @@@ static int get_first_selected_nonzero_w
  static char *wpaint_make_validmap(Object *ob);
  
  
- static void do_weight_paint_vertex( /* vars which remain the same for every vert */
+ static void do_weight_paint_vertex(/* vars which remain the same for every vert */
                                     VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
-                                     /* vars which change on each stroke */
+                                    /* vars which change on each stroke */
                                     const unsigned int index, float alpha, float paintweight
                                     )
  {
        MDeformVert *dv_mirr;
        MDeformWeight *dw_mirr;
  
+       const short do_multipaint_totsel = (wpi->do_multipaint && wpi->defbase_tot_sel > 1);
        if(wp->flag & VP_ONLYVGROUP) {
                dw= defvert_find_index(dv, wpi->vgroup_active);
                dw_prev= defvert_find_index(wp->wpaint_prev+index, wpi->vgroup_active);
                        }
                }
                else {
-                       dw_mirr = defvert_verify_index(dv_mirr, vgroup_mirr);
+                       if (index != index_mirr) {
+                               dw_mirr = defvert_verify_index(dv_mirr, vgroup_mirr);
+                       }
+                       else {
+                               /* dv and dv_mirr are the same */
+                               int totweight_prev = dv_mirr->totweight;
+                               int dw_offset = (int)(dw - dv_mirr->dw);
+                               dw_mirr = defvert_verify_index(dv_mirr, vgroup_mirr);
+                               /* if we added another, get our old one back */
+                               if (totweight_prev != dv_mirr->totweight) {
+                                       dw = &dv_mirr->dw[dw_offset];
+                               }
+                       }
                }
        }
        else {
  
        /* If there are no locks or multipaint,
         * then there is no need to run the more complicated checks */
-       if ( (wpi->do_multipaint == FALSE || wpi->defbase_tot_sel <= 1) &&
+       if ( (do_multipaint_totsel == FALSE) &&
             (wpi->lock_flags == NULL || has_locked_group(dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags) == FALSE))
        {
-               wpaint_blend(wp, dw, dw_prev, alpha, paintweight, wpi->do_flip, FALSE);
+               dw->weight = wpaint_blend(wp, dw->weight, dw_prev->weight, alpha, paintweight,
+                                         wpi->brush_alpha_value, wpi->do_flip, FALSE);
  
                /* WATCH IT: take care of the ordering of applying mirror -> normalize,
                 * can give wrong results [#26193], least confusing if normalize is done last */
                MDeformVert dv_copy= {NULL};
  
                oldw = dw->weight;
-               wpaint_blend(wp, dw, dw_prev, alpha, paintweight, wpi->do_flip, wpi->do_multipaint && wpi->defbase_tot_sel >1);
-               neww = dw->weight;
-               dw->weight = oldw;
+               neww = wpaint_blend(wp, dw->weight, dw_prev->weight, alpha, paintweight,
+                                   wpi->brush_alpha_value, wpi->do_flip, do_multipaint_totsel);
                
                /* setup multi-paint */
-               if(wpi->defbase_tot_sel > 1 && wpi->do_multipaint) {
+               if (do_multipaint_totsel) {
 -                      dv_copy.dw= MEM_dupallocN(dv->dw);
 +                      dv_copy.dw= BLI_cellalloc_dupalloc(dv->dw);
                        dv_copy.flag = dv->flag;
                        dv_copy.totweight = dv->totweight;
                        tdw = dw;
                        oldChange = 0;
                }
                if(dv_copy.dw) {
 -                      MEM_freeN(dv_copy.dw);
 +                      BLI_cellalloc_free(dv_copy.dw);
                }
  #if 0
                /* dv may have been altered greatly */
@@@ -2074,7 -2017,7 +2098,7 @@@ static int wpaint_stroke_test_start(bCo
        }
        
        me= get_mesh(ob);
 -      if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
 +      if(me==NULL || me->totpoly==0) return OPERATOR_PASS_THROUGH;
        
        /* if nothing was added yet, we make dverts and a vertex deform group */
        if (!me->dvert) {
  
  static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
  {
-       const Scene *scene= CTX_data_scene(C);
+       Scene *scene= CTX_data_scene(C);
        ToolSettings *ts= CTX_data_tool_settings(C);
        VPaint *wp= ts->wpaint;
        Brush *brush = paint_brush(&wp->paint);
        char *defbase_sel;
  
        const float pressure = RNA_float_get(itemptr, "pressure");
-       const float brush_size_final = brush_size(brush) * (brush_use_size_pressure(scene, brush) ? pressure : 1.0f);
-       const float brush_alpha_final = brush_alpha(brush) * (brush_use_alpha_pressure(scene, brush) ? pressure : 1.0f);
+       const float brush_size_pressure = brush_size(scene, brush) * (brush_use_size_pressure(scene, brush) ? pressure : 1.0f);
+       const float brush_alpha_value = brush_alpha(scene, brush);
+       const float brush_alpha_pressure = brush_alpha_value * (brush_use_alpha_pressure(scene, brush) ? pressure : 1.0f);
  
        /* intentionally dont initialize as NULL, make sure we initialize all members below */
        WeightPaintInfo wpi;
        wpi.do_flip=            RNA_boolean_get(itemptr, "pen_flip");
        wpi.do_multipaint=      (ts->multipaint != 0);
        wpi.do_auto_normalize=  ((ts->auto_normalize != 0) && (wpi.vgroup_validmap != NULL));
+       wpi.brush_alpha_value=  brush_alpha_value;
        /* *** done setting up WeightPaintInfo *** */
  
  
        if(wp->flag & VP_AREA) {
                /* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
                me->editflag &= ~ME_EDIT_VERT_SEL;
-               totindex= sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_final);
 -              totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size_pressure);
++              totindex= sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
                me->editflag |= use_vert_sel ? ME_EDIT_VERT_SEL : 0;
        }
        else {
                        
        if(wp->flag & VP_COLINDEX) {
                for(index=0; index<totindex; index++) {
 -                      if(indexar[index] && indexar[index]<=me->totface) {
 -                              MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
                                                
 -                              if(mface->mat_nr!=ob->actcol-1) {
 +                              if(mpoly->mat_nr!=ob->actcol-1) {
                                        indexar[index]= 0;
                                }
                        }
                }
        }
                        
 -      if((me->editflag & ME_EDIT_PAINT_MASK) && me->mface) {
 +      if((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
                for(index=0; index<totindex; index++) {
 -                      if(indexar[index] && indexar[index]<=me->totface) {
 -                              MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
                                                
 -                              if((mface->flag & ME_FACE_SEL)==0) {
 +                              if((mpoly->flag & ME_FACE_SEL)==0) {
                                        indexar[index]= 0;
                                }
                        }                                       
        /* make sure each vertex gets treated only once */
        /* and calculate filter weight */
        totw= 0.0f;
-       if(brush->vertexpaint_tool==VP_BLUR) 
+       if (brush->vertexpaint_tool == PAINT_BLEND_BLUR)
                paintweight= 0.0f;
        else
                paintweight= ts->vgroup_weight;
                        
        for(index=0; index<totindex; index++) {
 -              if(indexar[index] && indexar[index]<=me->totface) {
 -                      MFace *mface= me->mface + (indexar[index]-1);
 +              if(indexar[index] && indexar[index]<=me->totpoly) {
 +                      MPoly *mpoly= me->mpoly + (indexar[index]-1);
 +                      MLoop *ml = me->mloop + mpoly->loopstart;
 +                      int i;
  
                        if(use_vert_sel) {
 -                              me->dvert[mface->v1].flag = (me->mvert[mface->v1].flag & SELECT);
 -                              me->dvert[mface->v2].flag = (me->mvert[mface->v2].flag & SELECT);
 -                              me->dvert[mface->v3].flag = (me->mvert[mface->v3].flag & SELECT);
 -                              if(mface->v4) me->dvert[mface->v4].flag = (me->mvert[mface->v4].flag & SELECT);
 +                              for (i=0; i<mpoly->totloop; i++, ml++) {
 +                                      me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
 +                              }
                        }
                        else {
 -                              me->dvert[mface->v1].flag= 1;
 -                              me->dvert[mface->v2].flag= 1;
 -                              me->dvert[mface->v3].flag= 1;
 -                              if(mface->v4) me->dvert[mface->v4].flag= 1;
 +                              for (i=0; i<mpoly->totloop; i++, ml++) {
 +                                      me->dvert[ml->v].flag = 1;
 +                              }
                        }
                                        
-                       if(brush->vertexpaint_tool==VP_BLUR) {
+                       if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
                                MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
 -                              unsigned int fidx= mface->v4 ? 3:2;
                                                
                                if(wp->flag & VP_ONLYVGROUP)
                                        dw_func= (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
                                else
                                        dw_func= defvert_verify_index;
 -
 -                              do {
 -                                      unsigned int vidx= *(&mface->v1 + fidx);
 -                                      const float fac = calc_vp_strength_dl(wp, vc, wpd->vertexcosnos+6*vidx, mval, brush_size_pressure);
 +                                              
 +                              ml = me->mloop + mpoly->loopstart;
 +                              for (i=0; i<mpoly->totloop; i++, ml++) {
-                                       const float fac = calc_vp_strength_dl(wp, vc, wpd->vertexcosnos+6*ml->v, mval, brush_size_final);
++                                      const float fac = calc_vp_strength_dl(wp, vc, wpd->vertexcosnos+6*ml->v, mval, brush_size_pressure);
                                        if (fac > 0.0f) {
 -                                              dw = dw_func(&me->dvert[vidx], wpi.vgroup_active);
 +                                              dw = dw_func(&me->dvert[ml->v], wpi.vgroup_active);
                                                paintweight += dw ? (dw->weight * fac) : 0.0f;
                                                totw += fac;
                                        }
 -
 -                              } while (fidx--);
 -
 +                              }
                        }
                }
        }
                        
-       if (brush->vertexpaint_tool==VP_BLUR) {
+       if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
                paintweight /= totw;
        }
  
        for(index=0; index<totindex; index++) {
 -                              
 -              if(indexar[index] && indexar[index]<=me->totface) {
 -                      MFace *mf= me->mface + (indexar[index]-1);
 -                      unsigned int fidx= mf->v4 ? 3:2;
 -                      do {
 -                              unsigned int vidx= *(&mf->v1 + fidx);
 -
 -                              if(me->dvert[vidx].flag) {
 +              if(indexar[index] && indexar[index]<=me->totpoly) {
 +                      MPoly *mpoly= me->mpoly + (indexar[index]-1);
 +                      MLoop *ml=me->mloop+mpoly->loopstart;
 +                      int i;
 +
 +                      for (i=0; i<mpoly->totloop; i++, ml++) {
 +                              unsigned int vidx= ml->v;
 +                              if (me->dvert[vidx].flag) {
                                        alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*vidx,
-                                                               mval, brush_size_final, brush_alpha_final);
+                                                               mval, brush_size_pressure, brush_alpha_pressure);
                                        if(alpha) {
                                                do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight);
                                        }
                                        me->dvert[vidx].flag= 0;
                                }
 -                      } while (fidx--);
 +                      }
                }
        }
  
@@@ -2474,7 -2422,7 +2500,7 @@@ static int set_vpaint(bContext *C, wmOp
                return OPERATOR_PASS_THROUGH;
        }
        
 -      if(me && me->mcol==NULL) make_vertexcol(ob);
 +      if(me && me->mloopcol==NULL) make_vertexcol(ob);
        
        /* toggle: end vpaint */
        if(ob->mode & OB_MODE_VERTEX_PAINT) {
@@@ -2542,52 -2490,14 +2568,52 @@@ For future
  
  */
  
 +typedef struct polyfacemap_e {
 +      struct polyfacemap_e *next, *prev;
 +      int facenr;
 +} polyfacemap_e;
 +
  typedef struct VPaintData {
        ViewContext vc;
        unsigned int paintcol;
        int *indexar;
        float *vertexcosnos;
        float vpimat[3][3];
 +      
 +      /*mpoly -> mface mapping*/
 +      MemArena *arena;
 +      ListBase *polyfacemap;
  } VPaintData;
  
 +static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me)
 +{
 +      MFace *mf;
 +      polyfacemap_e *e;
 +      int *origIndex;
 +      int i;
 +
 +      vd->arena = BLI_memarena_new(1<<13, "vpaint tmp");
 +      BLI_memarena_use_calloc(vd->arena);
 +
 +      vd->polyfacemap = BLI_memarena_alloc(vd->arena, sizeof(ListBase)*me->totpoly);
 +
 +      origIndex = CustomData_get_layer(&me->fdata, CD_POLYINDEX);
 +      mf = me->mface;
 +
 +      if (!origIndex)
 +              return;
 +
 +      for (i=0; i<me->totface; i++, mf++, origIndex++) {
 +              if (*origIndex == ORIGINDEX_NONE)
 +                      continue;
 +
 +              e = BLI_memarena_alloc(vd->arena, sizeof(polyfacemap_e));
 +              e->facenr = i;
 +              
 +              BLI_addtail(&vd->polyfacemap[*origIndex], e);
 +      }
 +}
 +
  static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *UNUSED(event))
  {
        ToolSettings *ts= CTX_data_tool_settings(C);
  
        /* context checks could be a poll() */
        me= get_mesh(ob);
 -      if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
 +      if(me==NULL || me->totpoly==0)
 +              return OPERATOR_PASS_THROUGH;
        
 -      if(me->mcol==NULL) make_vertexcol(ob);
 -      if(me->mcol==NULL) return OPERATOR_CANCELLED;
 +      if(me->mloopcol==NULL)
 +              make_vertexcol(ob);
 +      if(me->mloopcol==NULL)
 +              return OPERATOR_CANCELLED;
        
        /* make mode data storage */
        vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
        vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
        vpd->indexar= get_indexarray(me);
        vpd->paintcol= vpaint_get_current_col(vp);
 +      vpaint_build_poly_facemap(vpd, me);
        
        /* for filtering */
 -      copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
 +      copy_vpaint_prev(vp, (unsigned int *)me->mloopcol, me->totloop);
        
        /* some old cruft to sort out later */
        mult_m4_m4m4(mat, vpd->vc.rv3d->viewmat, ob->obmat);
        return 1;
  }
  
 +#if 0
  static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob,
                                const unsigned int index, const float mval[2],
-                               const float brush_size_final, const float brush_alpha_final,
+                               const float brush_size_pressure, const float brush_alpha_pressure,
                                int UNUSED(flip))
  {
        ViewContext *vc = &vpd->vc;
        unsigned int *mcolorig= ((unsigned int*)vp->vpaint_prev) + 4*index;
        float alpha;
        int i;
+       int brush_alpha_pressure_i;
        
        if((vp->flag & VP_COLINDEX && mface->mat_nr!=ob->actcol-1) ||
           ((me->editflag & ME_EDIT_PAINT_MASK) && !(mface->flag & ME_FACE_SEL)))
                return;
  
-       if(brush->vertexpaint_tool==VP_BLUR) {
+       if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
                unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128);
                if(mface->v4) {
                        unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128);
                else {
                        vpd->paintcol= mcol_blend( mcol[2], fcol1, 170);
                }
-               
        }
  
+       brush_alpha_pressure_i = (int)(brush_alpha_pressure*255.0f);
        for(i = 0; i < (mface->v4 ? 4 : 3); ++i) {
                alpha = calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*(&mface->v1)[i],
-                                        mval, brush_size_final, brush_alpha_final);
-               if(alpha) {
-                       vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
+                                        mval, brush_size_pressure, brush_alpha_pressure);
+               if (alpha) {
+                       const int alpha_i = (int)(alpha*255.0f);
+                       mcol[i] = vpaint_blend(vp, mcol[i], mcolorig[i], vpd->paintcol, alpha_i, brush_alpha_pressure_i);
                }
        }
  }
 +#endif
  
  static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
  {
-       const Scene *scene= CTX_data_scene(C);
+       Scene *scene= CTX_data_scene(C);
        ToolSettings *ts= CTX_data_tool_settings(C);
        struct VPaintData *vpd = paint_stroke_mode_data(stroke);
        VPaint *vp= ts->vpaint;
        Brush *brush = paint_brush(&vp->paint);
        ViewContext *vc= &vpd->vc;
        Object *ob= vc->obact;
 +      polyfacemap_e *e;
        Mesh *me= ob->data;
        float mat[4][4];
        int *indexar= vpd->indexar;
        float mval[2];
  
        const float pressure = RNA_float_get(itemptr, "pressure");
-       const float brush_size_final = brush_size(brush) * (brush_use_size_pressure(scene, brush) ? pressure : 1.0f);
-       const float brush_alpha_final = brush_alpha(brush) * (brush_use_alpha_pressure(scene, brush) ? pressure : 1.0f);
+       const float brush_size_pressure = brush_size(scene, brush) * (brush_use_size_pressure(scene, brush) ? pressure : 1.0f);
+       const float brush_alpha_pressure = brush_alpha(scene, brush) * (brush_use_alpha_pressure(scene, brush) ? pressure : 1.0f);
++      int brush_alpha_pressure_i = (int)(brush_alpha_pressure*255.0f);
 +
        RNA_float_get_array(itemptr, "mouse", mval);
        flip = RNA_boolean_get(itemptr, "pen_flip");
 -                      
 +
 +      (void)flip; /* BMESH_TODO */
 +
        view3d_operator_needs_opengl(C);
                        
        /* load projection matrix */
                        
        /* which faces are involved */
        if(vp->flag & VP_AREA) {
-               totindex= sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_final);
 -              totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size_pressure);
++              totindex= sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
        }
        else {
                indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
                        
        swap_m4m4(vc->rv3d->persmat, mat);
                        
 -      for(index=0; index<totindex; index++) {                         
 -              if (indexar[index] && indexar[index]<=me->totface) {
 -                      vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval, brush_size_pressure, brush_alpha_pressure, flip);
 +      if(vp->flag & VP_COLINDEX) {
 +              for(index=0; index<totindex; index++) {
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
 +                                              
 +                              if(mpoly->mat_nr!=ob->actcol-1) {
 +                                      indexar[index]= 0;
 +                              }
 +                      }
                }
        }
 +
 +      if((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
 +              for(index=0; index<totindex; index++) {
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
                                                
 +                              if((mpoly->flag & ME_FACE_SEL)==0)
 +                                      indexar[index]= 0;
 +                      }                                       
 +              }
 +      }
 +      
        swap_m4m4(vc->rv3d->persmat, mat);
  
        /* was disabled because it is slow, but necessary for blur */
-       if(brush->vertexpaint_tool == VP_BLUR)
+       if (brush->vertexpaint_tool == PAINT_BLEND_BLUR)
                do_shared_vertexcol(me);
                        
 -      ED_region_tag_redraw(vc->ar);
 +      for(index=0; index<totindex; index++) {
 +                              
 +              if(indexar[index] && indexar[index]<=me->totpoly) {
 +                      MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
 +                      MFace *mf;
 +                      MCol *mc;
 +                      MLoop *ml;
 +                      MLoopCol *mlc;
 +                      unsigned int *lcol = ((unsigned int*)me->mloopcol) + mpoly->loopstart;
 +                      unsigned int *lcolorig = ((unsigned int*)vp->vpaint_prev) + mpoly->loopstart;
 +                      float alpha;
 +                      int i, j;
 +                                      
-                       if(brush->vertexpaint_tool==VP_BLUR) {
++                      if(brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
 +                              unsigned int blend[5] = {0};
 +                              char *col;
 +
 +                              for (j=0; j<mpoly->totloop; j += 2) {
 +                                      col = (char*)(lcol + j);
 +                                      blend[0] += col[0];
 +                                      blend[1] += col[1];
 +                                      blend[2] += col[2];
 +                                      blend[3] += col[3];
 +                              }
 +
 +                              blend[0] /= mpoly->totloop;
 +                              blend[1] /= mpoly->totloop;
 +                              blend[2] /= mpoly->totloop;
 +                              blend[3] /= mpoly->totloop;
 +                              col = (char*)(blend + 4);
 +                              col[0] = blend[0];
 +                              col[1] = blend[1];
 +                              col[2] = blend[2];
 +                              col[3] = blend[3];
 +
 +                              vpd->paintcol = *((unsigned int*)col);
 +                      }
 +
 +                      ml = me->mloop + mpoly->loopstart;
 +                      for (i=0; i<mpoly->totloop; i++, ml++) {
 +                              alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, 
 +                                                      vpd->vertexcosnos+6*ml->v, mval,
-                                                       brush_size_final, brush_alpha_final);
-                               if(alpha > 0.0f) vpaint_blend(vp, lcol+i, lcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
++                                                      brush_size_pressure, brush_alpha_pressure);
++                              if(alpha > 0.0f) {
++                                      const int alpha_i = (int)(alpha*255.0f);
++                                      lcol[i] = vpaint_blend(vp, lcol[i], lcolorig[i], vpd->paintcol, alpha_i, brush_alpha_pressure_i);
++                              }
 +                      }
 +      
 +                      #ifdef CPYCOL
 +                      #undef CPYCOL
 +                      #endif
 +                      #define CPYCOL(c, l) (c)->a = (l)->a, (c)->r = (l)->r, (c)->g = (l)->g, (c)->b = (l)->b
 +
 +                      /*update vertex colors for tesselations incrementally,
 +                        rather then regenerating the tesselation altogether.*/
 +                      for (e=vpd->polyfacemap[(indexar[index]-1)].first; e; e=e->next) {
 +                              mf = me->mface + e->facenr;
 +                              mc = me->mcol + e->facenr*4;
 +                              
 +                              ml = me->mloop + mpoly->loopstart;
 +                              mlc = me->mloopcol + mpoly->loopstart;
 +                              for (j=0; j<mpoly->totloop; j++, ml++, mlc++) {
 +                                      if (ml->v == mf->v1)
 +                                              CPYCOL(mc, mlc);
 +                                      else if (ml->v == mf->v2)
 +                                              CPYCOL(mc+1, mlc);
 +                                      else if (ml->v == mf->v3)
 +                                              CPYCOL(mc+2, mlc);
 +                                      else if (mf->v4 && ml->v == mf->v4)
 +                                              CPYCOL(mc+3, mlc);
 +
 +                              }
 +                      }
 +                      #undef CPYCOL
 +              }
 +      }
 +              
 +      swap_m4m4(vc->rv3d->persmat, mat);
                        
-       if(brush->vertexpaint_tool == VP_BLUR) {
 +      /* was disabled because it is slow, but necessary for blur */
++      if(brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
 +              do_shared_vertexcol(me);
 +      }
 +
 +      ED_region_tag_redraw(vc->ar);           
        DAG_id_tag_update(ob->data, 0);
  }
  
@@@ -2842,8 -2649,7 +2877,8 @@@ static void vpaint_stroke_done(bContex
        
        /* frees prev buffer */
        copy_vpaint_prev(ts->vpaint, NULL, 0);
 -      
 +      BLI_memarena_free(vpd->arena);
 +
        MEM_freeN(vpd);
  }
  
index f323a592b074e189a1fdf235035a1a80dcfeaf3d,27a0bc8f502ac131a1b390f7ab0c1507d2f7e3de..ae5316e71c41ae6dec8dd99908da36ba7dcc744a
@@@ -107,7 -107,7 +107,7 @@@ struct MultiresModifierData *sculpt_mul
        Mesh *me= (Mesh*)ob->data;
        ModifierData *md;
  
 -      if(!CustomData_get_layer(&me->fdata, CD_MDISPS)) {
 +      if(!CustomData_get_layer(&me->ldata, CD_MDISPS)) {
                /* multires can't work without displacement layer */
                return NULL;
        }
@@@ -543,13 -543,14 +543,14 @@@ static float calc_symmetry_feather(Scul
     special multiplier found experimentally to scale the strength factor. */
  static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
  {
+       const Scene *scene = cache->vc->scene;
        Brush *brush = paint_brush(&sd->paint);
  
        /* Primary strength input; square it to make lower values more sensitive */
-       const float root_alpha = brush_alpha(brush);
+       const float root_alpha = brush_alpha(scene, brush);
        float alpha        = root_alpha*root_alpha;
        float dir          = brush->flag & BRUSH_DIR_IN ? -1 : 1;
-       float pressure     = brush_use_alpha_pressure(cache->vc->scene, brush) ? cache->pressure : 1;
+       float pressure     = brush_use_alpha_pressure(scene, brush) ? cache->pressure : 1;
        float pen_flip     = cache->pen_flip ? -1 : 1;
        float invert       = cache->invert ? -1 : 1;
        float accum        = integrate_overlap(brush);
@@@ -679,7 -680,7 +680,7 @@@ static float tex_strength(SculptSessio
                else /* else (mtex->brush_map_mode == MTEX_MAP_MODE_TILED),
                        leave the coordinates relative to the screen */
                {
-                       radius = brush_size(br); // use unadjusted size for tiled mode
+                       radius = brush_size(ss->cache->vc->scene, br); // use unadjusted size for tiled mode
                
                        x = point_2d[0];
                        y = point_2d[1];
@@@ -1167,6 -1168,7 +1168,7 @@@ static void do_draw_brush(Sculpt *sd, O
  static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
  {
        SculptSession *ss = ob->sculpt;
+       const Scene *scene = ss->cache->vc->scene;
        Brush *brush = paint_brush(&sd->paint);
        float offset[3], area_normal[3];
        float bstrength= ss->cache->bstrength;
        
        /* we divide out the squared alpha and multiply by the squared crease to give us the pinch strength */
        
-       if(brush_alpha(brush) > 0.0f)
-               crease_correction = brush->crease_pinch_factor*brush->crease_pinch_factor/(brush_alpha(brush)*brush_alpha(brush));
+       if(brush_alpha(scene, brush) > 0.0f)
+               crease_correction = brush->crease_pinch_factor*brush->crease_pinch_factor/(brush_alpha(scene, brush)*brush_alpha(scene, brush));
        else
                crease_correction = brush->crease_pinch_factor*brush->crease_pinch_factor;
  
@@@ -2299,7 -2301,7 +2301,7 @@@ void sculpt_vertcos_to_key(Object *ob, 
                for (a= 0; a < me->totvert; a++, mvert++)
                        copy_v3_v3(mvert->co, vertCos[a]);
  
 -              mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
 +              mesh_calc_normals_mapping(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL);
        }
  
        /* apply new coords on active key block */
@@@ -2532,7 -2534,7 +2534,7 @@@ static void sculpt_flush_stroke_deform(
                /* Modifiers could depend on mesh normals, so we should update them/
                   Note, then if sculpting happens on locked key, normals should be re-calculated
                   after applying coords from keyblock on base mesh */
 -              mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
 +              mesh_calc_normals_mapping(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL);
        } else if (ss->kb)
                sculpt_update_keyblock(ob);
  }
@@@ -2658,10 -2660,10 +2660,10 @@@ static void do_symmetrical_brush_action
        cache->first_time= 0;
  }
  
- static void sculpt_update_tex(Sculpt *sd, SculptSession *ss)
+ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
  {
        Brush *brush = paint_brush(&sd->paint);
-       const int radius= brush_size(brush);
+       const int radius= brush_size(scene, brush);
  
        if(ss->texcache) {
                MEM_freeN(ss->texcache);
@@@ -2690,7 -2692,7 +2692,7 @@@ void sculpt_update_mesh_elements(Scene 
        if(mmd) {
                ss->multires = mmd;
                ss->totvert = dm->getNumVerts(dm);
 -              ss->totface = dm->getNumFaces(dm);
 +              ss->totface = dm->getNumTessFaces(dm);
                ss->mvert= NULL;
                ss->mface= NULL;
                ss->face_normals= NULL;
@@@ -3017,7 -3019,7 +3019,7 @@@ static void sculpt_update_cache_variant
                                                                                 struct PaintStroke *stroke,
                                                                                 PointerRNA *ptr)
  {
-       const Scene *scene = CTX_data_scene(C);
+       Scene *scene = CTX_data_scene(C);
        SculptSession *ss = ob->sculpt;
        StrokeCache *cache = ss->cache;
        Brush *brush = paint_brush(&sd->paint);
        sd->pressure_value= cache->pressure;
  
        cache->previous_pixel_radius = cache->pixel_radius;
-       cache->pixel_radius = brush_size(brush);
+       cache->pixel_radius = brush_size(scene, brush);
  
        if(cache->first_time) {
                if (!brush_use_locked_size(scene, brush)) {
-                       cache->initial_radius= paint_calc_object_space_radius(cache->vc, cache->true_location, brush_size(brush));
-                       brush_set_unprojected_radius(brush, cache->initial_radius);
+                       cache->initial_radius= paint_calc_object_space_radius(cache->vc, cache->true_location, brush_size(scene, brush));
+                       brush_set_unprojected_radius(scene, brush, cache->initial_radius);
                }
                else {
-                       cache->initial_radius= brush_unprojected_radius(brush);
+                       cache->initial_radius= brush_unprojected_radius(scene, brush);
                }
        }
  
@@@ -3246,7 -3248,7 +3248,7 @@@ int sculpt_stroke_get_location(bContex
        return srd.hit;
  }
  
- static void sculpt_brush_init_tex(Sculpt *sd, SculptSession *ss)
+ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
  {
        Brush *brush = paint_brush(&sd->paint);
        MTex *mtex= &brush->mtex;
        /* TODO: Shouldn't really have to do this at the start of every
           stroke, but sculpt would need some sort of notification when
           changes are made to the texture. */
-       sculpt_update_tex(sd, ss);
+       sculpt_update_tex(scene, sd, ss);
  }
  
  static int sculpt_brush_stroke_init(bContext *C, wmOperator *op)
        int is_smooth= 0;
  
        view3d_operator_needs_opengl(C);
-       sculpt_brush_init_tex(sd, ss);
+       sculpt_brush_init_tex(scene, sd, ss);
  
        is_smooth|= mode == BRUSH_STROKE_SMOOTH;
        is_smooth|= brush->sculpt_tool == SCULPT_TOOL_SMOOTH;
index 2d381b023cf5795d14b548e81cb466dcdfc546b0,9b9bdaf80bb40efcde3ddb0d2f434fc9f49a9128..0dbc0f63d4dc3084c2d79eb5feeba1dddf4bba5d
@@@ -39,8 -39,6 +39,8 @@@
  #include "DNA_userdef_types.h"
  #include "BLI_math.h"
  
 +#include "BKE_tessmesh.h"
 +
  /* Include for Bake Options */
  #include "RE_engine.h"
  #include "RE_pipeline.h"
@@@ -246,6 -244,7 +246,7 @@@ EnumPropertyItem image_color_depth_item
  #include "BLI_threads.h"
  #include "BLI_editVert.h"
  
+ #include "BKE_brush.h"
  #include "BKE_context.h"
  #include "BKE_global.h"
  #include "BKE_image.h"
@@@ -1109,9 -1108,9 +1110,9 @@@ static void rna_Scene_editmesh_select_m
  
                if(scene->basact) {
                        Mesh *me= get_mesh(scene->basact->object);
 -                      if(me && me->edit_mesh && me->edit_mesh->selectmode != flag) {
 -                              me->edit_mesh->selectmode= flag;
 -                              EM_selectmode_set(me->edit_mesh);
 +                      if(me && me->edit_btmesh && me->edit_btmesh->selectmode != flag) {
 +                              me->edit_btmesh->selectmode= flag;
 +                              EDBM_selectmode_set(me->edit_btmesh);
                        }
                }
        }
@@@ -1123,7 -1122,7 +1124,7 @@@ static void rna_Scene_editmesh_select_m
  
        if(scene->basact) {
                me= get_mesh(scene->basact->object);
 -              if(me && me->edit_mesh==NULL)
 +              if(me && me->edit_btmesh==NULL)
                        me= NULL;
        }
  
@@@ -1290,6 -1289,25 +1291,25 @@@ static KeyingSet *rna_Scene_keying_set_
        }
  }
  
+ static void rna_UnifiedPaintSettings_size_set(PointerRNA *ptr, int value)
+ {
+       UnifiedPaintSettings* ups = ptr->data;
+       /* scale unprojected radius so it stays consistent with brush size */
+       brush_scale_unprojected_radius(&ups->unprojected_radius,
+                                                                  value, ups->size);
+       ups->size= value;
+ }
+ static void rna_UnifiedPaintSettings_unprojected_radius_set(PointerRNA *ptr, float value)
+ {
+       UnifiedPaintSettings* ups = ptr->data;
+       /* scale brush size so it stays consistent with unprojected_radius */
+       brush_scale_size(&ups->size, value, ups->unprojected_radius);
+       ups->unprojected_radius= value;
+ }
  /* note: without this, when Multi-Paint is activated/deactivated, the colors
   * will not change right away when multiple bones are selected, this function
   * is not for general use and only for the few cases where changing scene
@@@ -1656,11 -1674,13 +1676,13 @@@ static void rna_def_unified_paint_setti
        /* unified paint settings that override the equivalent settings
           from the active brush */
        prop= RNA_def_property(srna, "size", PROP_INT, PROP_DISTANCE);
+       RNA_def_property_int_funcs(prop, NULL, "rna_UnifiedPaintSettings_size_set", NULL);
        RNA_def_property_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS*10);
        RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 1, 0);
        RNA_def_property_ui_text(prop, "Radius", "Radius of the brush in pixels");
  
        prop= RNA_def_property(srna, "unprojected_radius", PROP_FLOAT, PROP_DISTANCE);
+       RNA_def_property_float_funcs(prop, NULL, "rna_UnifiedPaintSettings_unprojected_radius_set", NULL);
        RNA_def_property_range(prop, 0.001, FLT_MAX);
        RNA_def_property_ui_range(prop, 0.001, 1, 0, 0);
        RNA_def_property_ui_text(prop, "Unprojected Radius", "Radius of brush in Blender units");
@@@ -2778,7 -2798,7 +2800,7 @@@ static void rna_def_scene_ffmpeg_settin
        prop = RNA_def_property(srna, "use_lossless_output", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flags", FFMPEG_LOSSLESS_OUTPUT);
        RNA_def_property_boolean_funcs(prop, NULL, "rna_FFmpegSettings_lossless_output_set");
-       RNA_def_property_ui_text(prop, "Lossless Output", "Use losslecc output for video streams");
+       RNA_def_property_ui_text(prop, "Lossless Output", "Use lossless output for video streams");
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
  
        /* FFMPEG Audio*/