Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/uvedit/uvedit_ops.c')
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c277
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);