diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index e3518e77477..fac86f79e23 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -109,6 +109,7 @@ struct EditMesh; #define BM_SMOOTH (1<<5) #define BM_ACTIVE (1<<6) #define BM_NONORMCALC (1<<7) +#define BM_PINNED (1<<8) typedef struct BMHeader { struct BMHeader *next, *prev; diff --git a/source/blender/bmesh/bmesh_marking.h b/source/blender/bmesh/bmesh_marking.h index c7bf6c263aa..5b390bb8a01 100644 --- a/source/blender/bmesh/bmesh_marking.h +++ b/source/blender/bmesh/bmesh_marking.h @@ -8,6 +8,12 @@ typedef struct BMEditSelection void *data; } BMEditSelection; +/* pinning code */ +void BM_Pin(BMesh *bm, void *element, int pin); +void BM_Pin_Vert(BMesh *bm, BMVert *v, int pin); +void BM_Pin_Edge(BMesh *bm, BMEdge *e, int pin); +void BM_Pin_Face(BMesh *bm, BMFace *f, int pin); + /*geometry hiding code*/ void BM_Hide(BMesh *bm, void *element, int hide); void BM_Hide_Vert(BMesh *bm, BMVert *v, int hide); diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 25e863e7de2..d57f00ce608 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -542,6 +542,7 @@ int BMFlags_To_MEFlags(void *element) { BMHeader *h = element; int f = 0; + if (h->flag & BM_PINNED) f |= ME_PIN; if (h->flag & BM_HIDDEN) f |= ME_HIDE; if (h->type == BM_FACE) { @@ -571,6 +572,7 @@ int BMFlags_To_MEFlags(void *element) { */ int MEFlags_To_BMFlags(int flag, int type) { int f = 0; + if (flag & ME_PIN) f |= BM_PINNED; if (type == BM_FACE) { if (flag & ME_FACE_SEL) f |= BM_SELECT; diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 3a622bd0bbb..3d6a02e1160 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -532,6 +532,51 @@ void BM_validate_selections(BMesh *em) } } +/***************** Pinning **************/ + +#define SETPIN(ele) pin ? BM_SetHFlag(ele, BM_PINNED) : BM_ClearHFlag(ele, BM_PINNED); + + +void BM_Pin_Vert(BMesh *bm, BMVert *v, int pin) +{ + SETPIN(v); +} + +void BM_Pin_Edge(BMesh *bm, BMEdge *e, int pin) +{ + SETPIN(e->v1); + SETPIN(e->v2); +} + +void BM_Pin_Face(BMesh *bm, BMFace *f, int pin) +{ + BMIter vfiter; + BMVert *vf; + + BM_ITER(vf, &vfiter, bm, BM_VERTS_OF_FACE, f) { + SETPIN(vf); + } +} + +void BM_Pin(BMesh *bm, void *element, int pin) +{ + BMHeader *h = element; + + switch (h->type) { + case BM_VERT: + BM_Pin_Vert(bm, element, pin); + break; + case BM_EDGE: + BM_Pin_Edge(bm, element, pin); + break; + case BM_FACE: + BM_Pin_Face(bm, element, pin); + break; + } +} + + + /***************** Mesh Hiding stuff *************/ #define SETHIDE(ele) hide ? BM_SetHFlag(ele, BM_HIDDEN) : BM_ClearHFlag(ele, BM_HIDDEN); diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index ed2c2f20789..317d36dad0f 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -194,8 +194,6 @@ void BM_Compute_Normals(BMesh *bm) unsigned int maxlength = 0; float (*projectverts)[3]; - //return; - /*first, find out the largest face in mesh*/ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f = BMIter_Step(&faces)){ if (BM_TestHFlag(f, BM_HIDDEN)) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 8847c9fa52c..9dde4bfd83d 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -111,6 +111,9 @@ void EDBM_editselection_plane(struct BMEditMesh *em, float *plane, struct BMEdit void EDBM_editselection_normal(float *normal, struct BMEditSelection *ese); int EDBM_vertColorCheck(struct BMEditMesh *em); +void EDBM_pin_mesh(struct BMEditMesh *em, int swap); +void EDBM_unpin_mesh(struct BMEditMesh *em, int swap); + void EDBM_hide_mesh(struct BMEditMesh *em, int swap); void EDBM_reveal_mesh(struct BMEditMesh *em); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 1ae3634c73b..6e7814ad0f8 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -202,6 +202,9 @@ enum { TH_DOPESHEET_CHANNELOB, TH_DOPESHEET_CHANNELSUBOB, + + TH_PIN, + TH_PIN_OPAC, }; /* XXX WARNING: previous is saved in file, so do not change order! */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 8aaede7515a..d21aabb5e2d 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -355,6 +355,10 @@ char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) case TH_DOPESHEET_CHANNELSUBOB: cp= ts->ds_subchannel; break; + case TH_PIN: + cp= ts->pin; break; + case TH_PIN_OPAC: + cp= &ts->pin_opac; break; } } @@ -475,6 +479,9 @@ void ui_theme_init_userdef(void) SETCOL(btheme->tv3d.bone_solid, 200, 200, 200, 255); SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 80); // alpha 80 is not meant editable, used for wire+action draw + + SETCOL(btheme->tv3d.pin, 115, 171, 209, 255); + btheme->tv3d.pin_opac = 40; /* space buttons */ diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c index 990198c9216..e02707c7a67 100644 --- a/source/blender/editors/mesh/bmesh_tools.c +++ b/source/blender/editors/mesh/bmesh_tools.c @@ -1703,6 +1703,127 @@ void MESH_OT_edge_rotate(wmOperatorType *ot) RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "direction", "direction to rotate edge around."); } +/* pinning code */ + +/* swap is 0 or 1, if 1 it pins not selected */ +void EDBM_pin_mesh(BMEditMesh *em, int swap) +{ + BMIter iter; + BMHeader *h; + int itermode; + + if(em==NULL) return; + + if (em->selectmode & SCE_SELECT_VERTEX) + itermode = BM_VERTS_OF_MESH; + else if (em->selectmode & SCE_SELECT_EDGE) + itermode = BM_EDGES_OF_MESH; + else + itermode = BM_FACES_OF_MESH; + + BM_ITER(h, &iter, em->bm, itermode, NULL) { + if (BM_TestHFlag(h, BM_SELECT) ^ swap) + BM_Pin(em->bm, h, 1); + } + + EDBM_selectmode_flush(em); +} + +static int pin_mesh_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + Mesh *me= ((Mesh *)obedit->data); + + me->drawflag |= ME_DRAW_PINS; + + EDBM_pin_mesh(em, RNA_boolean_get(op->ptr, "unselected")); + + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); + DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + + return OPERATOR_FINISHED; +} + +void MESH_OT_pin(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Pin Selection"; + ot->idname= "MESH_OT_pin"; + + /* api callbacks */ + ot->exec= pin_mesh_exec; + ot->poll= ED_operator_editmesh; + ot->description= "Pin (un)selected vertices, edges or faces."; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Pin unselected rather than selected."); +} + +/* swap is 0 or 1, if 1 it unhides not selected */ +void EDBM_unpin_mesh(BMEditMesh *em, int swap) +{ + BMIter iter; + BMHeader *ele; + int i, types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + int sels[3] = {1, !(em->selectmode & SCE_SELECT_VERTEX), !(em->selectmode & SCE_SELECT_VERTEX | SCE_SELECT_EDGE)}; + int itermode; + + if(em==NULL) return; + + if (em->selectmode & SCE_SELECT_VERTEX) + itermode = BM_VERTS_OF_MESH; + else if (em->selectmode & SCE_SELECT_EDGE) + itermode = BM_EDGES_OF_MESH; + else + itermode = BM_FACES_OF_MESH; + + BM_ITER(ele, &iter, em->bm, itermode, NULL) { + if (BM_TestHFlag(ele, BM_SELECT) ^ swap) + BM_Pin(em->bm, ele, 0); + } + + EDBM_selectmode_flush(em); +} + +static int unpin_mesh_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + Mesh *me= ((Mesh *)obedit->data); + + EDBM_unpin_mesh(em, RNA_boolean_get(op->ptr, "unselected")); + + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); + DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + + return OPERATOR_FINISHED; +} + +void MESH_OT_unpin(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Unpin Selection"; + ot->idname= "MESH_OT_unpin"; + ot->description= "Unpin (un)selected vertices, edges or faces."; + + /* api callbacks */ + ot->exec= unpin_mesh_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Unpin unselected rather than selected."); +} + + /* swap is 0 or 1, if 1 it hides not selected */ void EDBM_hide_mesh(BMEditMesh *em, int swap) { diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 0c2131e8098..37803d4c00a 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -205,6 +205,8 @@ void MESH_OT_select_inverse(struct wmOperatorType *ot); void MESH_OT_select_non_manifold(struct wmOperatorType *ot); void MESH_OT_select_linked(struct wmOperatorType *ot); void MESH_OT_select_linked_pick(struct wmOperatorType *ot); +void MESH_OT_pin(struct wmOperatorType *ot); +void MESH_OT_unpin(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); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 1498f3573f1..9570ae16a4b 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -204,6 +204,8 @@ static int specials_invoke(bContext *C, wmOperator *op, wmEvent *event) uiItemO(layout, "Remove Doubles", 0, "MESH_OT_remove_doubles"); uiItemO(layout, "Hide", 0, "MESH_OT_hide"); uiItemO(layout, "Reveal", 0, "MESH_OT_reveal"); + uiItemO(layout, "Pin", 0, "MESH_OT_pin"); + uiItemO(layout, "Unpin", 0, "MESH_OT_unpin"); uiItemO(layout, "Select Inverse", 0, "MESH_OT_select_inverse"); uiItemO(layout, NULL, 0, "MESH_OT_flip_normals"); uiItemO(layout, "Smooth", 0, "MESH_OT_vertices_smooth"); @@ -248,6 +250,8 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_select_linked_pick); WM_operatortype_append(MESH_OT_select_random); WM_operatortype_append(MESH_OT_selection_type); + WM_operatortype_append(MESH_OT_pin); + WM_operatortype_append(MESH_OT_unpin); WM_operatortype_append(MESH_OT_hide); WM_operatortype_append(MESH_OT_reveal); WM_operatortype_append(MESH_OT_select_by_number_vertices); @@ -396,6 +400,12 @@ void ED_keymap_mesh(wmWindowManager *wm) /* selection mode */ WM_keymap_add_item(keymap, "MESH_OT_selection_type", TABKEY, KM_PRESS, KM_CTRL, 0); + /* pin */ + WM_keymap_add_item(keymap, "MESH_OT_pin", RETKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_pin", RETKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1); + WM_keymap_add_item(keymap, "MESH_OT_unpin", RETKEY, KM_PRESS, KM_ALT, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_unpin", RETKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "unselected", 1); + /* hide */ WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 114d1fb503a..d432cac248f 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1528,6 +1528,62 @@ static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) glEnd(); } +/* check if all verts of the face are pinned */ +static int check_pinned_face(BMesh *bm, BMFace *efa) +{ + BMIter vfiter; + BMVert *v; + int vcount = 0; + + BM_ITER(v, &vfiter, bm, BM_VERTS_OF_FACE, efa) { + if(BM_TestHFlag(v, BM_PINNED)) vcount ++; + } + + if( vcount == efa->len) return 1; + return 0; +} + +static void draw_dm_vert_pins__mapFunc(void *userData, int index, float *co) +{ + struct {BMEditMesh *em; Mesh *me;} *data = userData; + BMVert *eve = EDBM_get_vert_for_index(data->em, index); + BMFace *fv; + BMIter fviter; + float vsize = UI_GetThemeValuef(TH_VERTEX_SIZE); + int small=0; + + if (!BM_TestHFlag(eve, BM_HIDDEN)) { + if (BM_TestHFlag(eve, BM_PINNED)) { + BM_ITER(fv, &fviter, data->em->bm, BM_FACES_OF_VERT, eve) { + small += check_pinned_face(data->em->bm, fv); + } + if(small == 0) { + bglEnd(); + glPointSize(vsize*1.5); + glBegin(GL_POINTS); + glVertex3fv(co); + } + else { + bglEnd(); + glPointSize(vsize*0.5); + glBegin(GL_POINTS); + glVertex3fv(co); + } + } + } +} + +static void draw_dm_vert_pins(BMEditMesh *em, DerivedMesh *dm, Mesh *me) +{ + struct { BMEditMesh *em; Mesh *me;} data; + + data.em = em; + data.me = me; + + dm->foreachMappedVert(dm, draw_dm_vert_pins__mapFunc, &data); + glEnd(); +} + /* Draw verts with color set based on selection */ static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { @@ -1661,6 +1717,55 @@ static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm) dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em); } +/* Draw only pinned edges */ +static int draw_dm_edges_pins__setDrawOptions(void *userData, int index) +{ + struct {BMEditMesh *em; Mesh *me;} *data = userData; + + BMEdge *eed = EDBM_get_edge_for_index(data->em, index); + BMIter feiter; + BMFace *fe; + + int fcount, fpcount = 0; + int pin = 0; + + /* If pinned faces are drawn then only draw pinned edges at the borders. + This looks way better and the user still has all the info he needs. */ + if(data->me->drawflag & ME_DRAW_PINS) { + if( BM_TestHFlag(eed->v1, BM_PINNED) && BM_TestHFlag(eed->v2, BM_PINNED) ) { + pin = 1; + + fcount = 0; + BM_ITER(fe, &feiter, data->em->bm, BM_FACES_OF_EDGE, eed) { + fcount ++; + fpcount += check_pinned_face(data->em->bm, fe); + } + } + } + else { + pin = BM_TestHFlag(eed->v1, BM_PINNED) && BM_TestHFlag(eed->v2, BM_PINNED); + } + + if( !BM_TestHFlag(eed, BM_HIDDEN)) { + /* Edges with at least one adherent pinned face are considered borders. + If there are more than two adherent faces overall of which at least two are pinned it's also consideres a border. */ + if( fpcount == 2 && fcount <= 2) { + return 0; } + else { + return pin; } + } +} + +static void draw_dm_edges_pins(BMEditMesh *em, DerivedMesh *dm, Mesh *me) +{ + struct { BMEditMesh *em; Mesh *me;} data; + + data.em = em; + data.me = me; + + dm->drawMappedEdges(dm, draw_dm_edges_pins__setDrawOptions, &data); +} + /* Draw only sharp edges */ static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index) { @@ -1678,18 +1783,35 @@ static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm) * return 2 for the active face so it renders with stipple enabled */ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r) { - struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; } *data = userData; + struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} *data = userData; BMFace *efa = EDBM_get_face_for_index(data->em, index); unsigned char *col; + BMIter vfiter; + BMVert *v; + int vcount, pin=0; + int opac = UI_GetThemeValue(TH_PIN_OPAC); if (!BM_TestHFlag(efa, BM_HIDDEN)) { + + /* Check if all verts of a face are pinned. If so, then display it in a darker shade. */ + if(data->me->drawflag & ME_DRAW_PINS) + pin = check_pinned_face(data->em->bm, efa); + if (efa == data->efa_act) { - glColor4ubv(data->cols[2]); + if(pin==0) { glColor4ubv(data->cols[2]); } + else { + col = data->cols[2]; + glColor4ub(col[0]-col[0]*0.9, col[1]-col[1]*0.9, col[2]-col[2]*0.9, opac*2.55); + } + return 2; /* stipple */ } else { col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0]; if (col[3]==0) return 0; - glColor4ubv(col); + + if(pin==0) { glColor4ubv(col); } + else { glColor4ub(col[0]-col[0]*0.9, col[1]-col[1]*0.9, col[2]-col[2]*0.9, opac*2.55); } + return 1; } } @@ -1698,15 +1820,16 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *dra /* also draws the active face */ static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, - unsigned char *selCol, unsigned char *actCol, BMFace *efa_act) + unsigned char *selCol, unsigned char *actCol, BMFace *efa_act, Mesh *me) { - struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; } data; + struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} data; data.cols[0] = baseCol; data.em = em; data.cols[1] = selCol; data.cols[2] = actCol; data.efa_act = efa_act; + data.me = me; dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0); } @@ -2168,7 +2291,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object if CHECK_OB_DRAWTEXTURE(v3d, dt) col1[3] = 0; - draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act); + draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me); glDisable(GL_BLEND); glDepthMask(1); // restore write in zbuffer @@ -2183,7 +2306,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object glEnable(GL_BLEND); glDepthMask(0); // disable write in zbuffer, needed for nice transp - draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act); + draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me); glDisable(GL_BLEND); glDepthMask(1); // restore write in zbuffer @@ -2224,6 +2347,16 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object if(me->drawflag & ME_DRAWBWEIGHTS) { draw_dm_bweights(em, scene, cageDM); } + + if(me->drawflag & ME_DRAW_PINS) { + UI_ThemeColor(TH_PIN); + glLineWidth(2); + + draw_dm_edges_pins(em, cageDM, me); + + glColor3ub(0,0,0); + glLineWidth(1); + } draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act); } @@ -2240,6 +2373,10 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object UI_ThemeColor(TH_NORMAL); draw_dm_vert_normals(em, scene, cageDM); } + if(me->drawflag & ME_DRAW_PINS) { + UI_ThemeColor(TH_PIN); + draw_dm_vert_pins(em, cageDM, me); + } if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG)) draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f7acab46c4b..22d12477624 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2281,6 +2281,9 @@ static void createTransEditVerts(bContext *C, TransInfo *t) if(propmode || selstate[a]) { VertsToTransData(t, tob, bm, eve); + /* pinned */ + if(BM_TestHFlag(eve,BM_PINNED)) tob->flag |= TD_SKIP; + /* selected */ if(selstate[a]) tob->flag |= TD_SELECTED; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 52323913ee4..74e0a25a26f 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -162,6 +162,8 @@ typedef struct TFace { #define ME_DRAW_FACEAREA (1 << 11) #define ME_DRAW_EDGEANG (1 << 12) +#define ME_DRAW_PINS (1 << 13) + /* old global flags: #define G_DRAWEDGES (1 << 18) #define G_DRAWFACES (1 << 7) diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 27cd63fd7db..9bd495b1e39 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -210,6 +210,7 @@ typedef struct PartialVisibility { #define ME_SPHERETEST 2 #define ME_SPHERETEMP 4 #define ME_HIDE 16 +#define ME_PIN 64 #define ME_VERT_MERGED (1<<6) /* medge->flag (1=SELECT)*/ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 100f55ffe33..54d03fe085f 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -218,6 +218,9 @@ typedef struct ThemeSpace { char hpad[3]; char pad[4]; + + char pin[4]; + int pin_opac; } ThemeSpace; diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 5f47b3d1d95..c930f59fe35 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -1412,6 +1412,11 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Face Area", "Displays the area of selected faces"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + prop= RNA_def_property(srna, "draw_pins", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_PINS); + RNA_def_property_ui_text(prop, "Draw Pins", "Displays pinned mesh elements"); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + rna_def_texmat_common(srna, "rna_Mesh_texspace_editable"); RNA_api_mesh(srna); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 946aa1cd682..d169edd65dd 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -679,6 +679,16 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, NC_WINDOW, NULL); + + prop= RNA_def_property(srna, "pin", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Pin", ""); + RNA_def_property_update(prop, NC_WINDOW, NULL); + + prop= RNA_def_property(srna, "pin_opac", PROP_INT, PROP_PERCENTAGE); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Pin Face Opacity", ""); + RNA_def_property_update(prop, NC_WINDOW, NULL); } static void rna_def_userdef_theme_space_graph(BlenderRNA *brna)