diff options
Diffstat (limited to 'source/blender/editors/uvedit/uvedit_ops.c')
-rw-r--r-- | source/blender/editors/uvedit/uvedit_ops.c | 277 |
1 files changed, 254 insertions, 23 deletions
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index a11d5935e22..c468da6b937 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -20,7 +20,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Antony Riakiotakis. * * ***** END GPL LICENSE BLOCK ***** */ @@ -103,6 +103,28 @@ int ED_uvedit_test(Object *obedit) return ret; } +static int ED_operator_uvedit_can_uv_sculpt(struct bContext *C) +{ + SpaceImage *sima= CTX_wm_space_image(C); + ToolSettings *toolsettings = CTX_data_tool_settings(C); + Object *obedit= CTX_data_edit_object(C); + + return ED_space_image_show_uvedit(sima, obedit) && !(toolsettings->use_uv_sculpt); +} + +static int ED_operator_uvmap_mesh(bContext *C) +{ + Object *ob= CTX_data_active_object(C); + + if(ob && ob->type==OB_MESH) { + Mesh *me = ob->data; + + if(CustomData_get_layer(&me->fdata, CD_MTFACE) != NULL) + return 1; + } + + return 0; +} /**************************** object active image *****************************/ static int is_image_texture_node(bNode *node) @@ -247,7 +269,13 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist { int width, height; - ED_space_image_size(sima, &width, &height); + if(sima) { + ED_space_image_size(sima, &width, &height); + } + else { + width= 256; + height= 256; + } dist[0]= pixeldist/width; dist[1]= pixeldist/height; @@ -468,7 +496,7 @@ void uvedit_uv_deselect(BMEditMesh *em, Scene *scene, BMLoop *l) /*********************** live unwrap utilities ***********************/ -static void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit) +void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit) { if(sima && (sima->flag & SI_LIVE_UNWRAP)) { ED_uvedit_live_unwrap_begin(scene, obedit); @@ -643,16 +671,7 @@ static int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, /************************** find nearest ****************************/ -typedef struct NearestHit { - BMFace *efa; - MTexPoly *tf; - BMLoop *l, *nextl; - MLoopUV *luv, *nextluv; - int lindex; //index of loop within face - int vert1, vert2; //index in mesh of edge vertices -} NearestHit; - -static void find_nearest_uv_edge(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit) +void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit) { MTexPoly *tf; BMFace *efa; @@ -712,7 +731,7 @@ static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, float memset(hit, 0, sizeof(*hit)); /*this will fill in hit.vert1 and hit.vert2*/ - find_nearest_uv_edge(scene, ima, em, co, hit); + uv_find_nearest_edge(scene, ima, em, co, hit); hit->l = hit->nextl = NULL; hit->luv = hit->nextluv = NULL; @@ -786,8 +805,8 @@ static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), i return (c1*c2 >= 0.0f); } -static void find_nearest_uv_vert(Scene *scene, Image *ima, BMEditMesh *em, - float co[2], float penalty[2], NearestHit *hit) +void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, + float co[2], float penalty[2], NearestHit *hit) { BMFace *efa; BMLoop *l; @@ -798,7 +817,7 @@ static void find_nearest_uv_vert(Scene *scene, Image *ima, BMEditMesh *em, int i; /*this will fill in hit.vert1 and hit.vert2*/ - find_nearest_uv_edge(scene, ima, em, co, hit); + uv_find_nearest_edge(scene, ima, em, co, hit); hit->l = hit->nextl = NULL; hit->luv = hit->nextluv = NULL; @@ -918,6 +937,27 @@ static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, BMFace *efa, int a) return NULL; } +/* BMESH_TODO - in some cases we already know the loop so looking up the index isnt needed */ + +UvElement *ED_get_uv_element(UvElementMap *map, BMFace *efa, int index) +{ + BMLoop *loop = efa->loops.first; + UvElement *element; + + while (index >= 0) { + loop = loop->next; + index--; + } + + element = map->vert[BM_GetIndex(loop->v)]; + + for(; element; element = element->next) + if(element->face == efa) + return element; + + return NULL; +} + static int uv_edge_tag_faces(BMEditMesh *em, UvMapVert *first1, UvMapVert *first2, int *totface) { UvMapVert *iterv1, *iterv2; @@ -1536,6 +1576,7 @@ static void UV_OT_weld(wmOperatorType *ot) ot->poll= ED_operator_uvedit; } +#if 0 // BMESH_TODO --- this function has been moved elsewhere /* ******************** stitch operator **************** */ /* just for averaging UVs */ @@ -1703,6 +1744,8 @@ static void UV_OT_stitch(wmOperatorType *ot) RNA_def_float(ot->srna, "limit", 20.0, 0.0f, FLT_MAX, "Limit", "Limit distance in image pixels", -FLT_MAX, FLT_MAX); } +#endif + /* ******************** (de)select all operator **************** */ static void select_all_perform(bContext *C, int action) @@ -1891,7 +1934,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) /* find nearest element */ if(loop) { /* find edge */ - find_nearest_uv_edge(scene, ima, em, co, &hit); + uv_find_nearest_edge(scene, ima, em, co, &hit); if(hit.efa == NULL) { BLI_array_free(hitv); BLI_array_free(hituv); @@ -1902,7 +1945,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) } else if(selectmode == UV_SELECT_VERTEX) { /* find vertex */ - find_nearest_uv_vert(scene, ima, em, co, penalty, &hit); + uv_find_nearest_vert(scene, ima, em, co, penalty, &hit); if(hit.efa == NULL) { BLI_array_free(hitv); BLI_array_free(hituv); @@ -1923,7 +1966,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) } else if(selectmode == UV_SELECT_EDGE) { /* find edge */ - find_nearest_uv_edge(scene, ima, em, co, &hit); + uv_find_nearest_edge(scene, ima, em, co, &hit); if(hit.efa == NULL) { BLI_array_free(hitv); BLI_array_free(hituv); @@ -1973,7 +2016,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) hitlen = hit.efa->len; } else if(selectmode == UV_SELECT_ISLAND) { - find_nearest_uv_vert(scene, ima, em, co, NULL, &hit); + uv_find_nearest_vert(scene, ima, em, co, NULL, &hit); if(hit.efa==NULL) { BLI_array_free(hitv); @@ -2257,7 +2300,7 @@ static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, i RNA_float_get_array(op->ptr, "location", co); } - find_nearest_uv_vert(scene, ima, em, co, NULL, &hit); + uv_find_nearest_vert(scene, ima, em, co, NULL, &hit); hit_p= &hit; } @@ -3457,6 +3500,183 @@ static void UV_OT_tile_set(wmOperatorType *ot) RNA_def_int_vector(ot->srna, "tile", 2, NULL, 0, INT_MAX, "Tile", "Tile coordinate", 0, 10); } + +static int seams_from_islands_exec(bContext *C, wmOperator *op) +{ + UvVertMap *vmap; + Object *ob = CTX_data_edit_object(C); + Mesh *me= (Mesh*)ob->data; + BMEditMesh *em; + BMEdge *editedge; + float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT}; + char mark_seams = RNA_boolean_get(op->ptr, "mark_seams"); + char mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp"); + + BMesh *bm; + BMIter iter; + + em = me->edit_btmesh; + bm = em->bm; + + if(!EDBM_texFaceCheck(em)) { + return OPERATOR_CANCELLED; + } + + /* This code sets editvert->tmp.l to the index. This will be useful later on. */ + EDBM_init_index_arrays(em, 0, 0, 1); + vmap = EDBM_make_uv_vert_map(em, 0, 0, limit); + + BM_ITER(editedge, &iter, bm, BM_EDGES_OF_MESH, NULL) { + /* flags to determine if we uv is separated from first editface match */ + char separated1 = 0, separated2; + /* set to denote edge must be flagged as seam */ + char faces_separated = 0; + /* flag to keep track if uv1 is disconnected from first editface match */ + char v1coincident = 1; + /* For use with v1coincident. v1coincident will change only if we've had commonFaces */ + int commonFaces = 0; + + BMFace *efa1, *efa2; + + UvMapVert *mv1, *mvinit1, *mv2, *mvinit2, *mviter; + /* mv2cache stores the first of the list of coincident uv's for later comparison + * mv2sep holds the last separator and is copied to mv2cache when a hit is first found */ + UvMapVert *mv2cache = NULL, *mv2sep = NULL; + + mvinit1 = vmap->vert[BM_GetIndex(editedge->v1)]; + if(mark_seams) + BM_ClearHFlag(editedge, BM_SEAM); + + for(mv1 = mvinit1; mv1 && !faces_separated; mv1 = mv1->next) { + if(mv1->separate && commonFaces) + v1coincident = 0; + + separated2 = 0; + efa1 = EDBM_get_face_for_index(em, mv1->f); + mvinit2 = vmap->vert[BM_GetIndex(editedge->v2)]; + + for(mv2 = mvinit2; mv2; mv2 = mv2->next) { + if(mv2->separate) + mv2sep = mv2; + + efa2 = EDBM_get_face_for_index(em, mv2->f); + if(efa1 == efa2) { + /* if v1 is not coincident no point in comparing */ + if(v1coincident) { + /* have we found previously anything? */ + if(mv2cache) { + /* flag seam unless proved to be coincident with previous hit */ + separated2 = 1; + for(mviter = mv2cache; mviter; mviter = mviter->next) { + if(mviter->separate && mviter != mv2cache) + break; + /* coincident with previous hit, do not flag seam */ + if(mviter == mv2) + separated2 = 0; + } + } + /* First hit case, store the hit in the cache */ + else { + mv2cache = mv2sep; + commonFaces = 1; + } + } + else + separated1 = 1; + + if(separated1 || separated2) { + faces_separated = 1; + break; + } + } + } + } + + if(faces_separated) { + if(mark_seams) + BM_SetHFlag(editedge, BM_SEAM); + if(mark_sharp) + BM_SetHFlag(editedge, BM_SHARP); + } + } + + me->drawflag |= ME_DRAWSEAMS; + + EDBM_free_uv_vert_map(vmap); + EDBM_free_index_arrays(em); + + DAG_id_tag_update(&me->id, 0); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, me); + + return OPERATOR_FINISHED; +} + + +static void UV_OT_seams_from_islands(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Seams From Islands"; + ot->description= "Set mesh seams according to island setup in the UV editor"; + ot->idname= "UV_OT_seams_from_islands"; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= seams_from_islands_exec; + ot->poll= ED_operator_uvedit; + + RNA_def_boolean(ot->srna, "mark_seams", 1, "Mark Seams", "Mark boundary edges as seams"); + RNA_def_boolean(ot->srna, "mark_sharp", 0, "Mark Sharp", "Mark boundary edges as sharp"); +} + +static int mark_seam_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + Mesh *me= (Mesh*)ob->data; + BMEditMesh *em= me->edit_btmesh; + BMesh *bm = em->bm; + BMFace *efa; + BMLoop *loop; + + BMIter iter, liter; + + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + BM_ITER(loop, &liter, bm, BM_LOOPS_OF_FACE, efa) { + if(uvedit_edge_selected(em, scene, loop)) { + BM_SetHFlag(loop, BM_SEAM); + } + } + } + + me->drawflag |= ME_DRAWSEAMS; + + if(scene->toolsettings->edge_mode_live_unwrap) + ED_unwrap_lscm(scene, ob, FALSE); + + DAG_id_tag_update(&me->id, 0); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, me); + + return OPERATOR_FINISHED; +} + +static void UV_OT_mark_seam(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Mark Seams"; + ot->description= "Mark selected UV edges as seams"; + ot->idname= "UV_OT_mark_seam"; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= mark_seam_exec; + ot->poll= ED_operator_uvedit; +} + + /* ************************** registration **********************************/ void ED_operatortypes_uvedit(void) @@ -3475,7 +3695,11 @@ void ED_operatortypes_uvedit(void) WM_operatortype_append(UV_OT_snap_selected); WM_operatortype_append(UV_OT_align); +#if 0 /* BMESH_TODO */ WM_operatortype_append(UV_OT_stitch); +#endif + WM_operatortype_append(UV_OT_seams_from_islands); + WM_operatortype_append(UV_OT_mark_seam); WM_operatortype_append(UV_OT_weld); WM_operatortype_append(UV_OT_pin); @@ -3502,7 +3726,14 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf) wmKeyMapItem *kmi; keymap= WM_keymap_find(keyconf, "UV Editor", 0, 0); - keymap->poll= ED_operator_uvedit; + keymap->poll= ED_operator_uvedit_can_uv_sculpt; + + /* Uv sculpt toggle */ + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", QKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_uv_sculpt"); + + /* Mark edge seam */ + WM_keymap_add_item(keymap, "UV_OT_mark_seam", EKEY, KM_PRESS, KM_CTRL, 0); /* pick selection */ RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, 0, 0)->ptr, "extend", FALSE); |