- editmesh select mirror (in editmode select menu)
authorCampbell Barton <ideasman42@gmail.com>
Tue, 20 Oct 2009 16:31:03 +0000 (16:31 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 20 Oct 2009 16:31:03 +0000 (16:31 +0000)
- weight blending (Vertex specials menu), currently blends from surrounding unselected verts (nice for blending edge loops), but will eventually support face mask mode.

release/scripts/ui/space_view3d.py
source/blender/editors/include/ED_mesh.h
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/mesh_intern.h
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_vgroup.c

index 3dac3700c940ca094ee4270f2cbb01db3eeb0273..4e6438e4271aad6325419d78fe6b49fecfe54b02 100644 (file)
@@ -827,6 +827,8 @@ class VIEW3D_MT_edit_mesh_vertices(bpy.types.Menu):
                layout.itemO("mesh.select_vertex_path")
                
                layout.itemO("mesh.blend_from_shape")
+               
+               layout.itemO("object.vertex_group_blend")
                # uiItemO(layout, "Propagate to All Shapes", 0, "mesh.shape_propagate_to_all");
 
 class VIEW3D_MT_edit_mesh_edges(bpy.types.Menu):
index 59f8c2441c1a4c4fcee8acd1e1c5a079b9cfa022..01444c0ecfb5fbde8625ed9a06c61321744d9ca5 100644 (file)
@@ -147,6 +147,7 @@ void                EM_free_data_layer(struct EditMesh *em, struct CustomData *data, int type)
 /* editmesh_mods.c */
 extern unsigned int em_vertoffs, em_solidoffs, em_wireoffs;
 
+void           EM_cache_x_mirror_vert(struct Object *ob, struct EditMesh *em);
 void           mouse_mesh(struct bContext *C, short mval[2], short extend);
 int                    EM_check_backbuf(unsigned int index);
 int                    EM_mask_init_backbuf_border(struct ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax);
index 968bb30b0cd0d2a099587f7fcef45b986f889506..7ca044b80878a11bda459acfb727e6e9f4baffac 100644 (file)
@@ -100,19 +100,39 @@ static int pupmenu() {return 0;}
 
 /* ****************************** MIRROR **************** */
 
-void EM_select_mirrored(Object *obedit, EditMesh *em)
+void EM_cache_x_mirror_vert(struct Object *ob, struct EditMesh *em)
 {
-       if(em->selectmode & SCE_SELECT_VERTEX) {
-               EditVert *eve, *v1;
-               
-               for(eve= em->verts.first; eve; eve= eve->next) {
-                       if(eve->f & SELECT) {
-                               v1= editmesh_get_x_mirror_vert(obedit, em, eve->co);
-                               if(v1) {
-                                       eve->f &= ~SELECT;
-                                       v1->f |= SELECT;
-                               }
-                       }
+       EditVert *eve, *eve_mirror;
+
+       for(eve= em->verts.first; eve; eve= eve->next) {
+               eve->tmp.v= NULL;
+       }
+
+       for(eve= em->verts.first; eve; eve= eve->next) {
+               if(eve->tmp.v==NULL) {
+                       eve_mirror = editmesh_get_x_mirror_vert(ob, em, eve->co);
+                       eve->tmp.v= eve_mirror;
+                       eve_mirror->tmp.v = eve;
+               }
+       }
+}
+
+void EM_select_mirrored(Object *obedit, EditMesh *em, int extend)
+{
+
+       EditVert *eve;
+
+       EM_cache_x_mirror_vert(obedit, em);
+
+       for(eve= em->verts.first; eve; eve= eve->next) {
+               if(eve->f & SELECT && eve->tmp.v) {
+                       eve->tmp.v->f |= SELECT;
+
+                       if(extend==FALSE)
+                               eve->f &= ~SELECT;
+
+                       /* remove the interference */
+                       eve->tmp.v->tmp.v= eve->tmp.v= NULL;
                }
        }
 }
@@ -2825,6 +2845,39 @@ void MESH_OT_select_by_number_vertices(wmOperatorType *ot)
        RNA_def_enum(ot->srna, "type", type_items, 3, "Type", "Type of elements to select.");
 }
 
+
+int select_mirror_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+       int extend= RNA_boolean_get(op->ptr, "extend");
+
+       EM_select_mirrored(obedit, em, extend);
+
+       WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+
+       return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_mirror(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Select Mirror";
+       ot->description= "Select mesh items at mirrored locations.";
+       ot->idname= "MESH_OT_select_mirror";
+
+       /* api callbacks */
+       ot->exec= select_mirror_exec;
+       ot->poll= ED_operator_editmesh;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* props */
+       RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
+}
+
 static int select_sharp_edges_exec(bContext *C, wmOperator *op)
 {
        /* Find edges that have exactly two neighboring faces,
index 8615f97f58f00ad716d121008217b0a810d27740..cab56ad5110f66bd5f1c56f91ab18b91e0282335 100644 (file)
@@ -151,6 +151,7 @@ void MESH_OT_select_linked_pick(struct wmOperatorType *ot);
 void MESH_OT_hide(struct wmOperatorType *ot);
 void MESH_OT_reveal(struct wmOperatorType *ot);
 void MESH_OT_select_by_number_vertices(struct wmOperatorType *ot);
+void MESH_OT_select_mirror(struct wmOperatorType *ot);
 void MESH_OT_normals_make_consistent(struct wmOperatorType *ot);
 void MESH_OT_faces_select_linked_flat(struct wmOperatorType *ot);
 void MESH_OT_edges_select_sharp(struct wmOperatorType *ot);
index e49dc0a5869b3acbb87bd2b4445601dc5df5552d..7159feced037d96c3bee635ade38ef4924dedd23 100644 (file)
@@ -80,6 +80,7 @@ void ED_operatortypes_mesh(void)
        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_mirror);
        WM_operatortype_append(MESH_OT_normals_make_consistent);
        WM_operatortype_append(MESH_OT_merge);
        WM_operatortype_append(MESH_OT_subdivide);
index 36d897b76c8bc7b267685d2928a07a0c4c529fa0..8c206ce9d4b0b9675a1f1a9d3cc7b50084adf5d7 100644 (file)
@@ -169,6 +169,7 @@ void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_normalize_all(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_invert(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_blend(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_clean(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_menu(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_set_active(struct wmOperatorType *ot);
index 06b554f0406df5da6480467375b3ad27dd1a8da8..4d823a842b47abbf90291ec82f00400780264168 100644 (file)
@@ -166,6 +166,7 @@ void ED_operatortypes_object(void)
        WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
        WM_operatortype_append(OBJECT_OT_vertex_group_normalize_all);
        WM_operatortype_append(OBJECT_OT_vertex_group_invert);
+       WM_operatortype_append(OBJECT_OT_vertex_group_blend);
        WM_operatortype_append(OBJECT_OT_vertex_group_clean);
        WM_operatortype_append(OBJECT_OT_vertex_group_menu);
        WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
index e5467e509722ef92d0e16dcd2073b12e25bdd764..5d76990b0e90555c08876895a0ebf32a3ae55cb9 100644 (file)
@@ -733,6 +733,90 @@ static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
        }
 }
 
+static void vgroup_blend(Object *ob)
+{
+       bDeformGroup *dg;
+       MDeformWeight *dw;
+       MDeformVert *dvert_array=NULL, *dvert;
+       int i, def_nr, dvert_tot=0;
+
+       EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)ob->data));
+       // ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
+
+       if(em==NULL)
+               return;
+
+       dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
+
+       if(dg) {
+               int sel1, sel2;
+               int i1, i2;
+
+               EditEdge *eed;
+               EditVert *eve;
+               float *vg_weights;
+               float *vg_users;
+
+               def_nr= ob->actdef-1;
+
+               i= 0;
+               for(eve= em->verts.first; eve; eve= eve->next)
+                       eve->tmp.l= i++;
+
+               dvert_tot= i;
+
+               vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f");
+               vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i");
+
+               for(eed= em->edges.first; eed; eed= eed->next) {
+                       sel1= eed->v1->f & SELECT;
+                       sel2= eed->v2->f & SELECT;
+
+                       if(sel1 != sel2) {
+                               /* i1 is always the selected one */
+                               if(sel1==TRUE && sel2==FALSE) {
+                                       i1= eed->v1->tmp.l;
+                                       i2= eed->v2->tmp.l;
+                                       eve= eed->v2;
+                               }
+                               else {
+                                       i2= eed->v1->tmp.l;
+                                       i1= eed->v2->tmp.l;
+                                       eve= eed->v1;
+                               }
+
+                               vg_users[i1]++;
+
+                               /* TODO, we may want object mode blending */
+                               if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+                               else    dvert= dvert_array+i2;
+
+                               dw= ED_vgroup_weight_get(dvert, def_nr);
+
+                               if(dw) {
+                                       vg_weights[i1] += dw->weight;
+                               }
+                       }
+               }
+
+               i= 0;
+               for(eve= em->verts.first; eve; eve= eve->next) {
+                       if(eve->f & SELECT && vg_users[i] > 0) {
+                               /* TODO, we may want object mode blending */
+                               if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+                               else    dvert= dvert_array+i;
+
+                               dw= ED_vgroup_weight_verify(dvert, def_nr);
+                               dw->weight= vg_weights[i] / (float)vg_users[i];
+                       }
+
+                       i++;
+               }
+               MEM_freeN(vg_weights);
+               MEM_freeN(vg_users);
+       }
+}
+
 static void vgroup_clean(Object *ob, float eul, int keep_single)
 {
        bDeformGroup *dg;
@@ -1472,6 +1556,35 @@ void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
        RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting.");
 }
 
+
+static int vertex_group_blend_exec(bContext *C, wmOperator *op)
+{
+       Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+
+       vgroup_blend(ob);
+
+       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Blend Vertex Group";
+       ot->idname= "OBJECT_OT_vertex_group_blend";
+
+       /* api callbacks */
+       ot->poll= vertex_group_poll;
+       ot->exec= vertex_group_blend_exec;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
 {
        Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;