diff options
author | Nick Samarin <nicks1987@bigmir.net> | 2011-02-16 20:07:18 +0300 |
---|---|---|
committer | Nick Samarin <nicks1987@bigmir.net> | 2011-02-16 20:07:18 +0300 |
commit | c5f6a01dd5998976addd2085470bb73a150579e5 (patch) | |
tree | 42b3345fb3ea2e7607a6d1eec379b8ce23b5ffbc /source/blender/editors/mesh/editmesh_add.c | |
parent | 4cf62f1e7e2bb28b47f79e4bd7c1482ab742ebbd (diff) | |
parent | 9e9e028f059f29d493dc020dda965a9bea8ffd6b (diff) |
synched with trunk at revision 34793
Diffstat (limited to 'source/blender/editors/mesh/editmesh_add.c')
-rw-r--r-- | source/blender/editors/mesh/editmesh_add.c | 166 |
1 files changed, 117 insertions, 49 deletions
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 7dac8a465fa..d9db1e99bfa 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -44,6 +44,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_editVert.h" +#include "BLI_utildefines.h" #include "BKE_context.h" #include "BKE_depsgraph.h" @@ -110,57 +111,98 @@ static short icoface[20][3] = { static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event) { ViewContext vc; - EditVert *eve, *v1; + EditVert *eve; float min[3], max[3]; int done= 0; - + short use_proj; + em_setup_viewcontext(C, &vc); + + use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) && (vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE); + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); INIT_MINMAX(min, max); - for(v1= vc.em->verts.first;v1; v1=v1->next) { - if(v1->f & SELECT) { - DO_MINMAX(v1->co, min, max); + for(eve= vc.em->verts.first; eve; eve= eve->next) { + if(eve->f & SELECT) { + DO_MINMAX(eve->co, min, max); done= 1; } } /* call extrude? */ if(done) { + short rot_src= RNA_boolean_get(op->ptr, "rotate_source"); EditEdge *eed; float vec[3], cent[3], mat[3][3]; float nor[3]= {0.0, 0.0, 0.0}; - /* check for edges that are half selected, use for rotation */ + /* 2D normal calc */ + float mval_f[2]; + + mval_f[0]= (float)event->mval[0]; + mval_f[1]= (float)event->mval[1]; + done= 0; + + /* calculate the normal for selected edges */ for(eed= vc.em->edges.first; eed; eed= eed->next) { - if( (eed->v1->f & SELECT)+(eed->v2->f & SELECT) == SELECT ) { - if(eed->v1->f & SELECT) sub_v3_v3v3(vec, eed->v1->co, eed->v2->co); - else sub_v3_v3v3(vec, eed->v2->co, eed->v1->co); - add_v3_v3(nor, vec); + if(eed->f & SELECT) { + float co1[3], co2[3]; + mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co); + mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co); + project_float_noclip(vc.ar, co1, co1); + project_float_noclip(vc.ar, co2, co2); + + /* 2D rotate by 90d while adding. + * (x, y) = (y, -x) + * + * accumulate the screenspace normal in 2D, + * with screenspace edge length weighting the result. */ + if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) { + nor[0] += (co1[1] - co2[1]); + nor[1] += -(co1[0] - co2[0]); + } + else { + nor[0] += (co2[1] - co1[1]); + nor[1] += -(co2[0] - co1[0]); + } done= 1; } } - if(done) normalize_v3(nor); + + if(done) { + float view_vec[3], cross[3]; + + /* convert the 2D nomal into 3D */ + mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */ + mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */ + + /* correct the normal to be aligned on the view plane */ + copy_v3_v3(view_vec, vc.rv3d->viewinv[2]); + mul_mat3_m4_v3(vc.obedit->imat, view_vec); + cross_v3_v3v3(cross, nor, view_vec); + cross_v3_v3v3(nor, view_vec, cross); + normalize_v3(nor); + } /* center */ - add_v3_v3v3(cent, min, max); - mul_v3_fl(cent, 0.5f); - VECCOPY(min, cent); + mid_v3_v3v3(cent, min, max); + copy_v3_v3(min, cent); mul_m4_v3(vc.obedit->obmat, min); // view space view3d_get_view_aligned_coordinate(&vc, min, event->mval); - invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); mul_m4_v3(vc.obedit->imat, min); // back in object space - sub_v3_v3v3(min, min, cent); + sub_v3_v3(min, cent); /* calculate rotation */ unit_m3(mat); if(done) { float dot; - VECCOPY(vec, min); + copy_v3_v3(vec, min); normalize_v3(vec); dot= INPR(vec, nor); @@ -170,27 +212,38 @@ static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event) cross_v3_v3v3(cross, nor, vec); normalize_v3(cross); dot= 0.5f*saacos(dot); + + /* halve the rotation if its applied twice */ + if(rot_src) dot *= 0.5f; + si= (float)sin(dot); q1[0]= (float)cos(dot); q1[1]= cross[0]*si; q1[2]= cross[1]*si; - q1[3]= cross[2]*si; - + q1[3]= cross[2]*si; quat_to_mat3( mat,q1); } } + if(rot_src) { + rotateflag(vc.em, SELECT, cent, mat); + /* also project the source, for retopo workflow */ + if(use_proj) + EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em); + } + extrudeflag(vc.obedit, vc.em, SELECT, nor, 0); rotateflag(vc.em, SELECT, cent, mat); translateflag(vc.em, SELECT, min); recalc_editnormals(vc.em); } - else { + else if(vc.em->selectmode & SCE_SELECT_VERTEX) { + float mat[3][3],imat[3][3]; float *curs= give_cursor(vc.scene, vc.v3d); - VECCOPY(min, curs); + copy_v3_v3(min, curs); view3d_get_view_aligned_coordinate(&vc, min, event->mval); eve= addvertlist(vc.em, 0, NULL); @@ -198,16 +251,18 @@ static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event) copy_m3_m4(mat, vc.obedit->obmat); invert_m3_m3(imat, mat); - VECCOPY(eve->co, min); + copy_v3_v3(eve->co, min); mul_m3_v3(imat, eve->co); sub_v3_v3v3(eve->co, eve->co, vc.obedit->obmat[3]); eve->f= SELECT; } - - //retopo_do_all(); + + if(use_proj) + EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); - DAG_id_flush_update(vc.obedit->data, OB_RECALC_DATA); + DAG_id_tag_update(vc.obedit->data, 0); return OPERATOR_FINISHED; } @@ -225,6 +280,8 @@ void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "rotate_source", 1, "Rotate Source", "Rotate initial selection giving better shape"); } @@ -303,13 +360,13 @@ int make_fgon(EditMesh *em, wmOperator *op, int make) if(eve->f1==1) break; } if(eve) { - BKE_report(op->reports, RPT_ERROR, "Cannot make a polygon with interior vertices"); + BKE_report(op->reports, RPT_WARNING, "Cannot make a polygon with interior vertices"); return 0; } // check for faces if(nor==NULL) { - BKE_report(op->reports, RPT_ERROR, "No faces were selected to make FGon"); + BKE_report(op->reports, RPT_WARNING, "No faces were selected to make FGon"); return 0; } @@ -332,7 +389,7 @@ static int make_fgon_exec(bContext *C, wmOperator *op) EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); if( make_fgon(em, op, 1) ) { - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); BKE_mesh_end_editmesh(obedit->data, em); @@ -364,7 +421,7 @@ static int clear_fgon_exec(bContext *C, wmOperator *op) EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); if( make_fgon(em, op, 0) ) { - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); BKE_mesh_end_editmesh(obedit->data, em); @@ -653,7 +710,7 @@ void addfaces_from_edgenet(EditMesh *em) EM_select_flush(em); -// XXX DAG_id_flush_update(obedit->data, OB_RECALC_DATA); +// XXX DAG_id_tag_update(obedit->data, 0); } static void addedgeface_mesh(EditMesh *em, wmOperator *op) @@ -682,7 +739,7 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op) eed= addedgelist(em, neweve[0], neweve[1], NULL); EM_select_edge(eed, 1); - // XXX DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + // XXX DAG_id_tag_update(obedit->data, 0); return; } else if(amount > 4) { @@ -690,7 +747,7 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op) return; } else if(amount<2) { - BKE_report(op->reports, RPT_ERROR, "More vertices are needed to make an edge/face"); + BKE_report(op->reports, RPT_WARNING, "More vertices are needed to make an edge/face"); return; } @@ -702,7 +759,7 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op) efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL); EM_select_face(efa, 1); } - else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face"); + else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face"); } else if(amount==4) { /* this test survives when theres 2 triangles */ @@ -754,14 +811,14 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op) else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co) ) { efa= addfacelist(em, neweve[0], neweve[3], neweve[1], neweve[2], NULL, NULL); } - else BKE_report(op->reports, RPT_ERROR, "cannot find nice quad from concave set of vertices"); + else BKE_report(op->reports, RPT_WARNING, "cannot find nice quad from concave set of vertices"); } } } - else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face"); + else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face"); } - else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face"); + else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face"); } if(efa) { @@ -780,7 +837,7 @@ static int addedgeface_mesh_exec(bContext *C, wmOperator *op) addedgeface_mesh(em, op); - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); BKE_mesh_end_editmesh(obedit->data, em); @@ -997,15 +1054,13 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se /* one segment first: the X axis */ phi = (2*dia)/(float)(tot-1); phid = (2*dia)/(float)(seg-1); - for(a=0;a<tot;a++) { + for(a=tot-1;a>=0;a--) { vec[0] = (phi*a) - dia; vec[1]= - dia; vec[2]= 0.0f; eve= addvertlist(em, vec, NULL); eve->f= 1+2+4; - if (a) { - addedgelist(em, eve->prev, eve, NULL); - } + if(a < tot -1) addedgelist(em, eve->prev, eve, NULL); } /* extrude and translate */ vec[0]= vec[2]= 0.0; @@ -1015,7 +1070,17 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused translateflag(em, 2, vec); } + + /* and now do imat */ + eve= em->verts.first; + while(eve) { + if(eve->f & SELECT) { + mul_m4_v3(mat,eve->co); + } + eve= eve->next; + } break; + case PRIM_UVSPHERE: /* UVsphere */ /* clear all flags */ @@ -1148,7 +1213,10 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se else if(ext==0) depth= 0.0f; - /* vertices */ + /* first vertex at 0° for circular objects */ + if( ELEM3(type, PRIM_CIRCLE,PRIM_CYLINDER,PRIM_CONE) ) + phi = 0.0f; + vtop= vdown= v1= v2= 0; for(b=0; b<=ext; b++) { for(a=0; a<tot; a++) { @@ -1259,7 +1327,7 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se /* ********* add primitive operators ************* */ -static char *get_mesh_defname(int type) +static const char *get_mesh_defname(int type) { switch (type) { case PRIM_PLANE: return "Plane"; @@ -1295,7 +1363,7 @@ static void make_prim_ext(bContext *C, float *loc, float *rot, int enter_editmod ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); /* rare cases the active layer is messed up */ newob = 1; } - else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA); + else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); scale= ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); @@ -1304,7 +1372,7 @@ static void make_prim_ext(bContext *C, float *loc, float *rot, int enter_editmod make_prim(obedit, type, mat, tot, seg, subdiv, dia, depth, ext, fill); - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); @@ -1499,7 +1567,7 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot) RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500); RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00); RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00); - RNA_def_boolean(ot->srna, "cap_end", 0, "Cap End", ""); + RNA_def_boolean(ot->srna, "cap_end", 1, "Cap End", ""); ED_object_add_generic_props(ot, TRUE); } @@ -1657,7 +1725,7 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot) /****************** add duplicate operator ***************/ -static int mesh_duplicate_exec(bContext *C, wmOperator *op) +static int mesh_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob= CTX_data_edit_object(C); EditMesh *em= BKE_mesh_get_editmesh(ob->data); @@ -1666,13 +1734,13 @@ static int mesh_duplicate_exec(bContext *C, wmOperator *op) BKE_mesh_end_editmesh(ob->data, em); - DAG_id_flush_update(ob->data, OB_RECALC_DATA); + DAG_id_tag_update(ob->data, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); return OPERATOR_FINISHED; } -static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { WM_cursor_wait(1); mesh_duplicate_exec(C, op); |