|
Blender
V2.59
|
00001 /* 00002 * $Id: uvedit_ops.c 38727 2011-07-26 13:33:04Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include <stdlib.h> 00036 #include <string.h> 00037 #include <math.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "DNA_object_types.h" 00042 #include "DNA_meshdata_types.h" 00043 #include "DNA_scene_types.h" 00044 00045 #include "BLI_math.h" 00046 #include "BLI_blenlib.h" 00047 #include "BLI_editVert.h" 00048 #include "BLI_utildefines.h" 00049 00050 #include "BKE_context.h" 00051 #include "BKE_customdata.h" 00052 #include "BKE_depsgraph.h" 00053 #include "BKE_image.h" 00054 #include "BKE_library.h" 00055 #include "BKE_mesh.h" 00056 #include "BKE_report.h" 00057 00058 #include "ED_image.h" 00059 #include "ED_mesh.h" 00060 #include "ED_uvedit.h" 00061 #include "ED_object.h" 00062 #include "ED_screen.h" 00063 #include "ED_transform.h" 00064 00065 #include "RNA_access.h" 00066 #include "RNA_define.h" 00067 00068 #include "WM_api.h" 00069 #include "WM_types.h" 00070 00071 #include "UI_view2d.h" 00072 00073 #include "uvedit_intern.h" 00074 00075 /************************* state testing ************************/ 00076 00077 int ED_uvedit_test(Object *obedit) 00078 { 00079 EditMesh *em; 00080 int ret; 00081 00082 if(!obedit || obedit->type != OB_MESH) 00083 return 0; 00084 00085 em = BKE_mesh_get_editmesh(obedit->data); 00086 ret = EM_texFaceCheck(em); 00087 BKE_mesh_end_editmesh(obedit->data, em); 00088 00089 return ret; 00090 } 00091 00092 /************************* assign image ************************/ 00093 00094 void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *previma) 00095 { 00096 EditMesh *em; 00097 EditFace *efa; 00098 MTFace *tf; 00099 int update= 0; 00100 00101 /* skip assigning these procedural images... */ 00102 if(ima && (ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)) 00103 return; 00104 00105 /* verify we have a mesh we can work with */ 00106 if(!obedit || (obedit->type != OB_MESH)) 00107 return; 00108 00109 em= BKE_mesh_get_editmesh(((Mesh*)obedit->data)); 00110 if(!em || !em->faces.first) { 00111 BKE_mesh_end_editmesh(obedit->data, em); 00112 return; 00113 } 00114 00115 /* ensure we have a uv layer */ 00116 if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) { 00117 EM_add_data_layer(em, &em->fdata, CD_MTFACE, NULL); 00118 update= 1; 00119 } 00120 00121 /* now assign to all visible faces */ 00122 for(efa= em->faces.first; efa; efa= efa->next) { 00123 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00124 00125 if(uvedit_face_visible(scene, previma, efa, tf)) { 00126 if(ima) { 00127 tf->tpage= ima; 00128 tf->mode |= TF_TEX; 00129 00130 if(ima->id.us==0) id_us_plus(&ima->id); 00131 else id_lib_extern(&ima->id); 00132 } 00133 else { 00134 tf->tpage= NULL; 00135 tf->mode &= ~TF_TEX; 00136 } 00137 00138 update = 1; 00139 } 00140 } 00141 00142 /* and update depdency graph */ 00143 if(update) 00144 DAG_id_tag_update(obedit->data, 0); 00145 00146 BKE_mesh_end_editmesh(obedit->data, em); 00147 } 00148 00149 /* dotile - 1, set the tile flag (from the space image) 00150 * 2, set the tile index for the faces. */ 00151 static int uvedit_set_tile(Object *obedit, Image *ima, int curtile) 00152 { 00153 EditMesh *em; 00154 EditFace *efa; 00155 MTFace *tf; 00156 00157 /* verify if we have something to do */ 00158 if(!ima || !ED_uvedit_test(obedit)) 00159 return 0; 00160 00161 if((ima->tpageflag & IMA_TILES) == 0) 00162 return 0; 00163 00164 /* skip assigning these procedural images... */ 00165 if(ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE) 00166 return 0; 00167 00168 em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 00169 00170 for(efa= em->faces.first; efa; efa= efa->next) { 00171 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00172 00173 if(efa->h==0 && efa->f & SELECT) 00174 tf->tile= curtile; /* set tile index */ 00175 } 00176 00177 DAG_id_tag_update(obedit->data, 0); 00178 BKE_mesh_end_editmesh(obedit->data, em); 00179 00180 return 1; 00181 } 00182 00183 /*********************** space conversion *********************/ 00184 00185 static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist) 00186 { 00187 int width, height; 00188 00189 if(sima) { 00190 ED_space_image_size(sima, &width, &height); 00191 } 00192 else { 00193 width= 256; 00194 height= 256; 00195 } 00196 00197 dist[0]= pixeldist/width; 00198 dist[1]= pixeldist/height; 00199 } 00200 00201 /*************** visibility and selection utilities **************/ 00202 00203 int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa) 00204 { 00205 ToolSettings *ts= scene->toolsettings; 00206 00207 if(ts->uv_flag & UV_SYNC_SELECTION) 00208 return (efa->h==0); 00209 else 00210 return (efa->h==0 && (efa->f & SELECT)); 00211 } 00212 00213 int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf) 00214 { 00215 ToolSettings *ts= scene->toolsettings; 00216 00217 if(ts->uv_flag & UV_SHOW_SAME_IMAGE) 00218 return (tf->tpage==ima)? uvedit_face_visible_nolocal(scene, efa): 0; 00219 else 00220 return uvedit_face_visible_nolocal(scene, efa); 00221 } 00222 00223 int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf) 00224 { 00225 ToolSettings *ts= scene->toolsettings; 00226 00227 if(ts->uv_flag & UV_SYNC_SELECTION) 00228 return (efa->f & SELECT); 00229 else 00230 return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4)); 00231 } 00232 00233 void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf) 00234 { 00235 ToolSettings *ts= scene->toolsettings; 00236 00237 if(ts->uv_flag & UV_SYNC_SELECTION) 00238 EM_select_face(efa, 1); 00239 else 00240 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 00241 } 00242 00243 void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf) 00244 { 00245 ToolSettings *ts= scene->toolsettings; 00246 00247 if(ts->uv_flag & UV_SYNC_SELECTION) 00248 EM_select_face(efa, 0); 00249 else 00250 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 00251 } 00252 00253 int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i) 00254 { 00255 ToolSettings *ts= scene->toolsettings; 00256 int nvert= (efa->v4)? 4: 3; 00257 00258 if(ts->uv_flag & UV_SYNC_SELECTION) { 00259 if(ts->selectmode & SCE_SELECT_FACE) 00260 return (efa->f & SELECT); 00261 else if(ts->selectmode & SCE_SELECT_EDGE) 00262 return (*(&efa->e1 + i))->f & SELECT; 00263 else 00264 return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT)); 00265 } 00266 else 00267 return (tf->flag & TF_SEL_MASK(i)) && (tf->flag & TF_SEL_MASK((i+1)%nvert)); 00268 } 00269 00270 void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i) 00271 { 00272 ToolSettings *ts= scene->toolsettings; 00273 int nvert= (efa->v4)? 4: 3; 00274 00275 if(ts->uv_flag & UV_SYNC_SELECTION) { 00276 if(ts->selectmode & SCE_SELECT_FACE) 00277 EM_select_face(efa, 1); 00278 else if(ts->selectmode & SCE_SELECT_EDGE) 00279 EM_select_edge((*(&efa->e1 + i)), 1); 00280 else { 00281 (efa->v1 + i)->f |= SELECT; 00282 (efa->v1 + (i+1)%nvert)->f |= SELECT; 00283 } 00284 } 00285 else 00286 tf->flag |= TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert); 00287 } 00288 00289 void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i) 00290 { 00291 ToolSettings *ts= scene->toolsettings; 00292 int nvert= (efa->v4)? 4: 3; 00293 00294 if(ts->uv_flag & UV_SYNC_SELECTION) { 00295 if(ts->selectmode & SCE_SELECT_FACE) 00296 EM_select_face(efa, 0); 00297 else if(ts->selectmode & SCE_SELECT_EDGE) 00298 EM_select_edge((*(&efa->e1 + i)), 0); 00299 else { 00300 (efa->v1 + i)->f &= ~SELECT; 00301 (efa->v1 + (i+1)%nvert)->f &= ~SELECT; 00302 } 00303 } 00304 else 00305 tf->flag &= ~(TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert)); 00306 } 00307 00308 int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i) 00309 { 00310 ToolSettings *ts= scene->toolsettings; 00311 00312 if(ts->uv_flag & UV_SYNC_SELECTION) { 00313 if(ts->selectmode & SCE_SELECT_FACE) 00314 return (efa->f & SELECT); 00315 else 00316 return (*(&efa->v1 + i))->f & SELECT; 00317 } 00318 else 00319 return tf->flag & TF_SEL_MASK(i); 00320 } 00321 00322 void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i) 00323 { 00324 ToolSettings *ts= scene->toolsettings; 00325 00326 if(ts->uv_flag & UV_SYNC_SELECTION) { 00327 if(ts->selectmode & SCE_SELECT_FACE) 00328 EM_select_face(efa, 1); 00329 else 00330 (*(&efa->v1 + i))->f |= SELECT; 00331 } 00332 else 00333 tf->flag |= TF_SEL_MASK(i); 00334 } 00335 00336 void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i) 00337 { 00338 ToolSettings *ts= scene->toolsettings; 00339 00340 if(ts->uv_flag & UV_SYNC_SELECTION) { 00341 if(ts->selectmode & SCE_SELECT_FACE) 00342 EM_select_face(efa, 0); 00343 else 00344 (*(&efa->v1 + i))->f &= ~SELECT; 00345 } 00346 else 00347 tf->flag &= ~TF_SEL_MASK(i); 00348 } 00349 00350 /*********************** live unwrap utilities ***********************/ 00351 00352 static void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit) 00353 { 00354 if(sima && (sima->flag & SI_LIVE_UNWRAP)) { 00355 ED_uvedit_live_unwrap_begin(scene, obedit); 00356 ED_uvedit_live_unwrap_re_solve(); 00357 ED_uvedit_live_unwrap_end(0); 00358 } 00359 } 00360 00361 /*********************** geometric utilities ***********************/ 00362 00363 void uv_center(float uv[][2], float cent[2], int quad) 00364 { 00365 if(quad) { 00366 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0] + uv[3][0]) / 4.0f; 00367 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1] + uv[3][1]) / 4.0f; 00368 } 00369 else { 00370 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0]) / 3.0f; 00371 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1]) / 3.0f; 00372 } 00373 } 00374 00375 float uv_area(float uv[][2], int quad) 00376 { 00377 if(quad) 00378 return area_tri_v2(uv[0], uv[1], uv[2]) + area_tri_v2(uv[0], uv[2], uv[3]); 00379 else 00380 return area_tri_v2(uv[0], uv[1], uv[2]); 00381 } 00382 00383 void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy) 00384 { 00385 uv[0][0] = uv_orig[0][0]*aspx; 00386 uv[0][1] = uv_orig[0][1]*aspy; 00387 00388 uv[1][0] = uv_orig[1][0]*aspx; 00389 uv[1][1] = uv_orig[1][1]*aspy; 00390 00391 uv[2][0] = uv_orig[2][0]*aspx; 00392 uv[2][1] = uv_orig[2][1]*aspy; 00393 00394 uv[3][0] = uv_orig[3][0]*aspx; 00395 uv[3][1] = uv_orig[3][1]*aspy; 00396 } 00397 00398 int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float *max) 00399 { 00400 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 00401 EditFace *efa; 00402 MTFace *tf; 00403 int sel; 00404 00405 INIT_MINMAX2(min, max); 00406 00407 sel= 0; 00408 for(efa= em->faces.first; efa; efa= efa->next) { 00409 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00410 if(uvedit_face_visible(scene, ima, efa, tf)) { 00411 if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); sel = 1; } 00412 if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); sel = 1; } 00413 if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); sel = 1; } 00414 if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); sel = 1; } 00415 } 00416 } 00417 00418 BKE_mesh_end_editmesh(obedit->data, em); 00419 return sel; 00420 } 00421 00422 static int ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[3]) 00423 { 00424 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 00425 EditFace *efa; 00426 MTFace *tf; 00427 unsigned int sel= 0; 00428 00429 zero_v3(co); 00430 00431 for(efa= em->faces.first; efa; efa= efa->next) { 00432 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00433 if(uvedit_face_visible(scene, ima, efa, tf)) { 00434 if(uvedit_uv_selected(scene, efa, tf, 0)) { add_v3_v3(co, tf->uv[0]); sel++; } 00435 if(uvedit_uv_selected(scene, efa, tf, 1)) { add_v3_v3(co, tf->uv[1]); sel++; } 00436 if(uvedit_uv_selected(scene, efa, tf, 2)) { add_v3_v3(co, tf->uv[2]); sel++; } 00437 if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { add_v3_v3(co, tf->uv[3]); sel++; } 00438 } 00439 } 00440 00441 mul_v3_fl(co, 1.0f/(float)sel); 00442 00443 BKE_mesh_end_editmesh(obedit->data, em); 00444 return (sel != 0); 00445 } 00446 00447 static int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, char mode) 00448 { 00449 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 00450 float min[2], max[2]; 00451 int change= 0; 00452 00453 if(mode==V3D_CENTER) { /* bounding box */ 00454 if(ED_uvedit_minmax(scene, ima, obedit, min, max)) { 00455 change = 1; 00456 00457 cent[0]= (min[0]+max[0])/2.0f; 00458 cent[1]= (min[1]+max[1])/2.0f; 00459 } 00460 } 00461 else { 00462 if(ED_uvedit_median(scene, ima, obedit, cent)) { 00463 change = 1; 00464 } 00465 00466 } 00467 00468 if(change) { 00469 BKE_mesh_end_editmesh(obedit->data, em); 00470 return 1; 00471 } 00472 00473 BKE_mesh_end_editmesh(obedit->data, em); 00474 return 0; 00475 } 00476 00477 /************************** find nearest ****************************/ 00478 00479 typedef struct NearestHit { 00480 EditFace *efa; 00481 MTFace *tf; 00482 00483 int vert, uv; 00484 int edge, vert2; 00485 } NearestHit; 00486 00487 static void find_nearest_uv_edge(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit) 00488 { 00489 MTFace *tf; 00490 EditFace *efa; 00491 EditVert *eve; 00492 float mindist, dist; 00493 int i, nverts; 00494 00495 mindist= 1e10f; 00496 memset(hit, 0, sizeof(*hit)); 00497 00498 for(i=0, eve=em->verts.first; eve; eve=eve->next, i++) 00499 eve->tmp.l = i; 00500 00501 for(efa= em->faces.first; efa; efa= efa->next) { 00502 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00503 00504 if(uvedit_face_visible(scene, ima, efa, tf)) { 00505 nverts= efa->v4? 4: 3; 00506 00507 for(i=0; i<nverts; i++) { 00508 dist= dist_to_line_segment_v2(co, tf->uv[i], tf->uv[(i+1)%nverts]); 00509 00510 if(dist < mindist) { 00511 hit->tf= tf; 00512 hit->efa= efa; 00513 hit->edge= i; 00514 mindist= dist; 00515 00516 hit->vert= (*(&efa->v1 + i))->tmp.l; 00517 hit->vert2= (*(&efa->v1 + ((i+1)%nverts)))->tmp.l; 00518 } 00519 } 00520 } 00521 } 00522 } 00523 00524 static void find_nearest_uv_face(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit) 00525 { 00526 MTFace *tf; 00527 EditFace *efa; 00528 float mindist, dist, cent[2]; 00529 int i, nverts; 00530 00531 mindist= 1e10f; 00532 memset(hit, 0, sizeof(*hit)); 00533 00534 for(efa= em->faces.first; efa; efa= efa->next) { 00535 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00536 00537 if(uvedit_face_visible(scene, ima, efa, tf)) { 00538 nverts= efa->v4? 4: 3; 00539 cent[0]= cent[1]= 0.0f; 00540 00541 for(i=0; i<nverts; i++) { 00542 cent[0] += tf->uv[i][0]; 00543 cent[1] += tf->uv[i][1]; 00544 } 00545 00546 cent[0] /= nverts; 00547 cent[1] /= nverts; 00548 dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]); 00549 00550 if(dist < mindist) { 00551 hit->tf= tf; 00552 hit->efa= efa; 00553 mindist= dist; 00554 } 00555 } 00556 } 00557 } 00558 00559 static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float uv[2]) 00560 { 00561 float m[3], v1[3], v2[3], c1, c2; 00562 int id1, id2; 00563 00564 id1= (id+nverts-1)%nverts; 00565 id2= (id+nverts+1)%nverts; 00566 00567 m[0]= co[0]-uv[0]; 00568 m[1]= co[1]-uv[1]; 00569 sub_v2_v2v2(v1, tf->uv[id1], tf->uv[id]); 00570 sub_v2_v2v2(v2, tf->uv[id2], tf->uv[id]); 00571 00572 /* m and v2 on same side of v-v1? */ 00573 c1= v1[0]*m[1] - v1[1]*m[0]; 00574 c2= v1[0]*v2[1] - v1[1]*v2[0]; 00575 00576 if(c1*c2 < 0.0f) 00577 return 0; 00578 00579 /* m and v1 on same side of v-v2? */ 00580 c1= v2[0]*m[1] - v2[1]*m[0]; 00581 c2= v2[0]*v1[1] - v2[1]*v1[0]; 00582 00583 return (c1*c2 >= 0.0f); 00584 } 00585 00586 static void find_nearest_uv_vert(Scene *scene, Image *ima, EditMesh *em, float co[2], float penalty[2], NearestHit *hit) 00587 { 00588 EditFace *efa; 00589 EditVert *eve; 00590 MTFace *tf; 00591 float mindist, dist; 00592 int i, nverts; 00593 00594 mindist= 1e10f; 00595 memset(hit, 0, sizeof(*hit)); 00596 00597 for(i=0, eve=em->verts.first; eve; eve=eve->next, i++) 00598 eve->tmp.l = i; 00599 00600 for(efa= em->faces.first; efa; efa= efa->next) { 00601 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00602 00603 if(uvedit_face_visible(scene, ima, efa, tf)) { 00604 nverts= efa->v4? 4: 3; 00605 00606 for(i=0; i<nverts; i++) { 00607 if(penalty && uvedit_uv_selected(scene, efa, tf, i)) 00608 dist= fabsf(co[0]-tf->uv[i][0])+penalty[0] + fabsf(co[1]-tf->uv[i][1]) + penalty[1]; 00609 else 00610 dist= fabsf(co[0]-tf->uv[i][0]) + fabsf(co[1]-tf->uv[i][1]); 00611 00612 if(dist<=mindist) { 00613 if(dist==mindist) 00614 if(!nearest_uv_between(tf, nverts, i, co, tf->uv[i])) 00615 continue; 00616 00617 mindist= dist; 00618 00619 hit->uv= i; 00620 hit->tf= tf; 00621 hit->efa= efa; 00622 00623 hit->vert= (*(&efa->v1 + i))->tmp.l; 00624 } 00625 } 00626 } 00627 } 00628 } 00629 00630 int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2], float uv[2]) 00631 { 00632 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 00633 EditFace *efa; 00634 MTFace *tf; 00635 float mindist, dist; 00636 int i, nverts, found= 0; 00637 00638 mindist= 1e10f; 00639 uv[0]= co[0]; 00640 uv[1]= co[1]; 00641 00642 for(efa= em->faces.first; efa; efa= efa->next) { 00643 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00644 00645 if(uvedit_face_visible(scene, ima, efa, tf)) { 00646 nverts= efa->v4? 4: 3; 00647 00648 for(i=0; i<nverts; i++) { 00649 if(uvedit_uv_selected(scene, efa, tf, i)) 00650 continue; 00651 00652 dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]); 00653 00654 if(dist<=mindist) { 00655 mindist= dist; 00656 00657 uv[0]= tf->uv[i][0]; 00658 uv[1]= tf->uv[i][1]; 00659 found= 1; 00660 } 00661 } 00662 } 00663 } 00664 00665 BKE_mesh_end_editmesh(obedit->data, em); 00666 return found; 00667 } 00668 00669 /*********************** loop select ***********************/ 00670 00671 static void uv_vertex_loop_flag(UvMapVert *first) 00672 { 00673 UvMapVert *iterv; 00674 int count= 0; 00675 00676 for(iterv=first; iterv; iterv=iterv->next) { 00677 if(iterv->separate && iterv!=first) 00678 break; 00679 00680 count++; 00681 } 00682 00683 if(count < 5) 00684 first->flag= 1; 00685 } 00686 00687 static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a) 00688 { 00689 UvMapVert *iterv, *first; 00690 00691 first= EM_get_uv_map_vert(vmap, (*(&efa->v1 + a))->tmp.l); 00692 00693 for(iterv=first; iterv; iterv=iterv->next) { 00694 if(iterv->separate) 00695 first= iterv; 00696 if(iterv->f == efa->tmp.l) 00697 return first; 00698 } 00699 00700 return NULL; 00701 } 00702 00703 static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface) 00704 { 00705 UvMapVert *iterv1, *iterv2; 00706 EditFace *efa; 00707 int tot = 0; 00708 00709 /* count number of faces this edge has */ 00710 for(iterv1=first1; iterv1; iterv1=iterv1->next) { 00711 if(iterv1->separate && iterv1 != first1) 00712 break; 00713 00714 for(iterv2=first2; iterv2; iterv2=iterv2->next) { 00715 if(iterv2->separate && iterv2 != first2) 00716 break; 00717 00718 if(iterv1->f == iterv2->f) { 00719 /* if face already tagged, don't do this edge */ 00720 efa= EM_get_face_for_index(iterv1->f); 00721 if(efa->f1) 00722 return 0; 00723 00724 tot++; 00725 break; 00726 } 00727 } 00728 } 00729 00730 if(*totface == 0) /* start edge */ 00731 *totface= tot; 00732 else if(tot != *totface) /* check for same number of faces as start edge */ 00733 return 0; 00734 00735 /* tag the faces */ 00736 for(iterv1=first1; iterv1; iterv1=iterv1->next) { 00737 if(iterv1->separate && iterv1 != first1) 00738 break; 00739 00740 for(iterv2=first2; iterv2; iterv2=iterv2->next) { 00741 if(iterv2->separate && iterv2 != first2) 00742 break; 00743 00744 if(iterv1->f == iterv2->f) { 00745 efa= EM_get_face_for_index(iterv1->f); 00746 efa->f1= 1; 00747 break; 00748 } 00749 } 00750 } 00751 00752 return 1; 00753 } 00754 00755 static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *hit, float limit[2], int extend) 00756 { 00757 EditVert *eve; 00758 EditFace *efa; 00759 MTFace *tf; 00760 UvVertMap *vmap; 00761 UvMapVert *iterv1, *iterv2; 00762 int a, count, looking, nverts, starttotf, select; 00763 00764 /* setup */ 00765 EM_init_index_arrays(em, 0, 0, 1); 00766 vmap= EM_make_uv_vert_map(em, 0, 0, limit); 00767 00768 for(count=0, eve=em->verts.first; eve; count++, eve= eve->next) 00769 eve->tmp.l = count; 00770 00771 for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) { 00772 if(!extend) { 00773 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00774 uvedit_face_deselect(scene, efa, tf); 00775 } 00776 00777 efa->tmp.l= count; 00778 efa->f1= 0; 00779 } 00780 00781 /* set flags for first face and verts */ 00782 nverts= (hit->efa->v4)? 4: 3; 00783 iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge); 00784 iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts); 00785 uv_vertex_loop_flag(iterv1); 00786 uv_vertex_loop_flag(iterv2); 00787 00788 starttotf= 0; 00789 uv_edge_tag_faces(iterv1, iterv2, &starttotf); 00790 00791 /* sorry, first edge isnt even ok */ 00792 if(iterv1->flag==0 && iterv2->flag==0) looking= 0; 00793 else looking= 1; 00794 00795 /* iterate */ 00796 while(looking) { 00797 looking= 0; 00798 00799 /* find correct valence edges which are not tagged yet, but connect to tagged one */ 00800 for(efa= em->faces.first; efa; efa=efa->next) { 00801 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00802 00803 if(!efa->f1 && uvedit_face_visible(scene, ima, efa, tf)) { 00804 nverts= (efa->v4)? 4: 3; 00805 for(a=0; a<nverts; a++) { 00806 /* check face not hidden and not tagged */ 00807 iterv1= uv_vertex_map_get(vmap, efa, a); 00808 iterv2= uv_vertex_map_get(vmap, efa, (a+1)%nverts); 00809 00810 /* check if vertex is tagged and has right valence */ 00811 if(iterv1->flag || iterv2->flag) { 00812 if(uv_edge_tag_faces(iterv1, iterv2, &starttotf)) { 00813 looking= 1; 00814 efa->f1= 1; 00815 00816 uv_vertex_loop_flag(iterv1); 00817 uv_vertex_loop_flag(iterv2); 00818 break; 00819 } 00820 } 00821 } 00822 } 00823 } 00824 } 00825 00826 /* do the actual select/deselect */ 00827 nverts= (hit->efa->v4)? 4: 3; 00828 iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge); 00829 iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts); 00830 iterv1->flag= 1; 00831 iterv2->flag= 1; 00832 00833 if(extend) { 00834 tf= CustomData_em_get(&em->fdata, hit->efa->data, CD_MTFACE); 00835 00836 if(uvedit_uv_selected(scene, hit->efa, tf, hit->edge) && uvedit_uv_selected(scene, hit->efa, tf, hit->edge)) 00837 select= 0; 00838 else 00839 select= 1; 00840 } 00841 else 00842 select= 1; 00843 00844 for(efa= em->faces.first; efa; efa=efa->next) { 00845 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00846 00847 nverts= (efa->v4)? 4: 3; 00848 for(a=0; a<nverts; a++) { 00849 iterv1= uv_vertex_map_get(vmap, efa, a); 00850 00851 if(iterv1->flag) { 00852 if(select) uvedit_uv_select(scene, efa, tf, a); 00853 else uvedit_uv_deselect(scene, efa, tf, a); 00854 } 00855 } 00856 } 00857 00858 /* cleanup */ 00859 EM_free_uv_vert_map(vmap); 00860 EM_free_index_arrays(); 00861 00862 return (select)? 1: -1; 00863 } 00864 00865 /*********************** linked select ***********************/ 00866 00867 static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2], NearestHit *hit, int extend) 00868 { 00869 EditFace *efa; 00870 MTFace *tf; 00871 UvVertMap *vmap; 00872 UvMapVert *vlist, *iterv, *startv; 00873 int i, nverts, stacksize= 0, *stack; 00874 unsigned int a; 00875 char *flag; 00876 00877 EM_init_index_arrays(em, 0, 0, 1); /* we can use this too */ 00878 vmap= EM_make_uv_vert_map(em, 1, 0, limit); 00879 if(vmap == NULL) 00880 return; 00881 00882 stack= MEM_mallocN(sizeof(*stack) * em->totface, "UvLinkStack"); 00883 flag= MEM_callocN(sizeof(*flag) * em->totface, "UvLinkFlag"); 00884 00885 if(!hit) { 00886 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { 00887 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00888 00889 if(uvedit_face_visible(scene, ima, efa, tf)) { 00890 const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); 00891 if(tf->flag & select_flag) { 00892 stack[stacksize]= a; 00893 stacksize++; 00894 flag[a]= 1; 00895 } 00896 } 00897 } 00898 } 00899 else { 00900 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { 00901 if(efa == hit->efa) { 00902 stack[stacksize]= a; 00903 stacksize++; 00904 flag[a]= 1; 00905 break; 00906 } 00907 } 00908 } 00909 00910 while(stacksize > 0) { 00911 stacksize--; 00912 a= stack[stacksize]; 00913 00914 efa = EM_get_face_for_index(a); 00915 00916 nverts= efa->v4? 4: 3; 00917 00918 for(i=0; i<nverts; i++) { 00919 /* make_uv_vert_map_EM sets verts tmp.l to the indices */ 00920 vlist= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l); 00921 00922 startv= vlist; 00923 00924 for(iterv=vlist; iterv; iterv=iterv->next) { 00925 if(iterv->separate) 00926 startv= iterv; 00927 if(iterv->f == a) 00928 break; 00929 } 00930 00931 for(iterv=startv; iterv; iterv=iterv->next) { 00932 if((startv != iterv) && (iterv->separate)) 00933 break; 00934 else if(!flag[iterv->f]) { 00935 flag[iterv->f]= 1; 00936 stack[stacksize]= iterv->f; 00937 stacksize++; 00938 } 00939 } 00940 } 00941 } 00942 00943 if(!extend) { 00944 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { 00945 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00946 if(flag[a]) 00947 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 00948 else 00949 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 00950 } 00951 } 00952 else { 00953 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { 00954 if(flag[a]) { 00955 const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); 00956 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00957 if((tf->flag & select_flag)) 00958 break; 00959 } 00960 } 00961 00962 if(efa) { 00963 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { 00964 if(flag[a]) { 00965 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00966 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 00967 } 00968 } 00969 } 00970 else { 00971 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) { 00972 if(flag[a]) { 00973 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00974 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 00975 } 00976 } 00977 } 00978 } 00979 00980 MEM_freeN(stack); 00981 MEM_freeN(flag); 00982 EM_free_uv_vert_map(vmap); 00983 EM_free_index_arrays(); 00984 } 00985 00986 /* ******************** align operator **************** */ 00987 00988 static void weld_align_uv(bContext *C, int tool) 00989 { 00990 SpaceImage *sima; 00991 Scene *scene; 00992 Object *obedit; 00993 Image *ima; 00994 EditMesh *em; 00995 EditFace *efa; 00996 MTFace *tf; 00997 float cent[2], min[2], max[2]; 00998 00999 scene= CTX_data_scene(C); 01000 obedit= CTX_data_edit_object(C); 01001 em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 01002 ima= CTX_data_edit_image(C); 01003 sima= CTX_wm_space_image(C); 01004 01005 INIT_MINMAX2(min, max); 01006 01007 if(tool == 'a') { 01008 for(efa= em->faces.first; efa; efa= efa->next) { 01009 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01010 01011 if(uvedit_face_visible(scene, ima, efa, tf)) { 01012 if(uvedit_uv_selected(scene, efa, tf, 0)) 01013 DO_MINMAX2(tf->uv[0], min, max) 01014 if(uvedit_uv_selected(scene, efa, tf, 1)) 01015 DO_MINMAX2(tf->uv[1], min, max) 01016 if(uvedit_uv_selected(scene, efa, tf, 2)) 01017 DO_MINMAX2(tf->uv[2], min, max) 01018 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) 01019 DO_MINMAX2(tf->uv[3], min, max) 01020 } 01021 } 01022 01023 tool= (max[0]-min[0] >= max[1]-min[1])? 'y': 'x'; 01024 } 01025 01026 uvedit_center(scene, ima, obedit, cent, 0); 01027 01028 if(tool == 'x' || tool == 'w') { 01029 for(efa= em->faces.first; efa; efa= efa->next) { 01030 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01031 if(uvedit_face_visible(scene, ima, efa, tf)) { 01032 if(uvedit_uv_selected(scene, efa, tf, 0)) 01033 tf->uv[0][0]= cent[0]; 01034 if(uvedit_uv_selected(scene, efa, tf, 1)) 01035 tf->uv[1][0]= cent[0]; 01036 if(uvedit_uv_selected(scene, efa, tf, 2)) 01037 tf->uv[2][0]= cent[0]; 01038 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) 01039 tf->uv[3][0]= cent[0]; 01040 } 01041 } 01042 } 01043 01044 if(tool == 'y' || tool == 'w') { 01045 for(efa= em->faces.first; efa; efa= efa->next) { 01046 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01047 if(uvedit_face_visible(scene, ima, efa, tf)) { 01048 if(uvedit_uv_selected(scene, efa, tf, 0)) 01049 tf->uv[0][1]= cent[1]; 01050 if(uvedit_uv_selected(scene, efa, tf, 1)) 01051 tf->uv[1][1]= cent[1]; 01052 if(uvedit_uv_selected(scene, efa, tf, 2)) 01053 tf->uv[2][1]= cent[1]; 01054 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) 01055 tf->uv[3][1]= cent[1]; 01056 } 01057 } 01058 } 01059 01060 if(tool == 's' || tool == 't' || tool == 'u') { 01061 /* pass 1&2 variables */ 01062 int i, j; 01063 int starttmpl= -1, connectedtostarttmpl= -1, startcorner; 01064 int endtmpl= -1, connectedtoendtmpl= -1, endcorner; 01065 MTFace *startface, *endface; 01066 int itmpl, jtmpl; 01067 EditVert *eve; 01068 int pass; /* first 2 passes find endpoints, 3rd pass moves middle points, 4th pass is fail-on-face-selected */ 01069 EditFace *startefa, *endefa; 01070 01071 /* pass 3 variables */ 01072 float startx, starty, firstm, firstb, midx, midy; 01073 float endx, endy, secondm, secondb, midmovedx, midmovedy; 01074 float IsVertical_check= -1; 01075 float IsHorizontal_check= -1; 01076 01077 for(i= 0, eve= em->verts.first; eve; eve= eve->next, i++) /* give each point a unique name */ 01078 eve->tmp.l= i; 01079 for(pass= 1; pass <= 3; pass++) { /* do this for each endpoint */ 01080 if(pass == 3){ /* calculate */ 01081 startx= startface->uv[startcorner][0]; 01082 starty= startface->uv[startcorner][1]; 01083 endx= endface->uv[endcorner][0]; 01084 endy= endface->uv[endcorner][1]; 01085 firstm= (endy-starty)/(endx-startx); 01086 firstb= starty-(firstm*startx); 01087 secondm= -1.0f/firstm; 01088 if(startx == endx) IsVertical_check= startx; 01089 if(starty == endy) IsHorizontal_check= starty; 01090 } 01091 for(efa= em->faces.first; efa; efa= efa->next) { /* for each face */ 01092 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); /* get face */ 01093 if(uvedit_face_visible(scene, ima, efa, tf)) { /* if you can see it */ 01094 if(uvedit_face_selected(scene, efa, tf)) { /* if the face is selected, get out now! */ 01095 pass= 4; 01096 break; 01097 } 01098 for(i= 0; (i < 3 || (i == 3 && efa->v4)); i++) { /* for each point of the face */ 01099 itmpl= (*(&efa->v1 + i))->tmp.l; /* get unique name for points */ 01100 if(pass == 3) { /* move */ 01101 if(uvedit_uv_selected(scene, efa, tf, i)) { 01102 if(!(itmpl == starttmpl || itmpl == endtmpl)) { 01103 if(IsVertical_check != -1) tf->uv[i][0]= IsVertical_check; 01104 if(IsHorizontal_check != -1) tf->uv[i][1]= IsHorizontal_check; 01105 if((IsVertical_check == -1) && (IsHorizontal_check == -1)) { 01106 midx= tf->uv[i][0]; 01107 midy= tf->uv[i][1]; 01108 if(tool == 's') { 01109 secondb= midy-(secondm*midx); 01110 midmovedx= (secondb-firstb)/(firstm-secondm); 01111 midmovedy= (secondm*midmovedx)+secondb; 01112 tf->uv[i][0]= midmovedx; 01113 tf->uv[i][1]= midmovedy; 01114 } 01115 else if(tool == 't') { 01116 tf->uv[i][0]= (midy-firstb)/firstm; /* midmovedx */ 01117 } 01118 else if(tool == 'u') { 01119 tf->uv[i][1]= (firstm*midx)+firstb; /* midmovedy */ 01120 } 01121 } 01122 } 01123 } 01124 } 01125 else { 01126 for(j= 0; (j < 3 || (j == 3 && efa->v4)); j++) { /* also for each point on the face */ 01127 jtmpl= (*(&efa->v1 + j))->tmp.l; 01128 if(i != j && (!efa->v4 || ABS(i-j) != 2)) { /* if the points are connected */ 01129 /* quad (0,1,2,3) 0,1 0,3 1,0 1,2 2,1 2,3 3,0 3,2 01130 * triangle (0,1,2) 0,1 0,2 1,0 1,2 2,0 2,1 */ 01131 if(uvedit_uv_selected(scene, efa, tf, i) && uvedit_uv_selected(scene, efa, tf, j)) { 01132 /* if the edge is selected */ 01133 if(pass == 1) { /* if finding first endpoint */ 01134 if(starttmpl == -1) { /* if the first endpoint isn't found yet */ 01135 starttmpl= itmpl; /* set unique name for endpoint */ 01136 connectedtostarttmpl= jtmpl; 01137 /* get point that endpoint is connected to */ 01138 startface= tf; /* get face it's on */ 01139 startcorner= i; /* what corner of the face? */ 01140 startefa= efa; 01141 efa= em->faces.first; 01142 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01143 i= -1; 01144 break; 01145 } 01146 if(starttmpl == itmpl && jtmpl != connectedtostarttmpl) { 01147 starttmpl= -1; /* not an endpoint */ 01148 efa= startefa; 01149 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01150 i= startcorner; 01151 break; 01152 } 01153 } 01154 else if(pass == 2) { /* if finding second endpoint */ 01155 if(endtmpl == -1 && itmpl != starttmpl) { 01156 endtmpl= itmpl; 01157 connectedtoendtmpl= jtmpl; 01158 endface= tf; 01159 endcorner= i; 01160 endefa= efa; 01161 efa= em->faces.first; 01162 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01163 i= -1; 01164 break; 01165 } 01166 if(endtmpl == itmpl && jtmpl != connectedtoendtmpl) { 01167 endtmpl= -1; 01168 efa= endefa; 01169 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01170 i= endcorner; 01171 break; 01172 } 01173 } 01174 } 01175 } 01176 } 01177 } 01178 } 01179 } 01180 } 01181 if(pass == 2 && (starttmpl == -1 || endtmpl == -1)) { 01182 /* if endpoints aren't found */ 01183 pass=4; 01184 } 01185 } 01186 } 01187 01188 uvedit_live_unwrap_update(sima, scene, obedit); 01189 DAG_id_tag_update(obedit->data, 0); 01190 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 01191 01192 BKE_mesh_end_editmesh(obedit->data, em); 01193 } 01194 01195 static int align_exec(bContext *C, wmOperator *op) 01196 { 01197 weld_align_uv(C, RNA_enum_get(op->ptr, "axis")); 01198 01199 return OPERATOR_FINISHED; 01200 } 01201 01202 static void UV_OT_align(wmOperatorType *ot) 01203 { 01204 static EnumPropertyItem axis_items[] = { 01205 {'s', "ALIGN_S", 0, "Straighten", "Align UVs along the line defined by the endpoints"}, 01206 {'t', "ALIGN_T", 0, "Straighten X", "Align UVs along the line defined by the endpoints along the X axis"}, 01207 {'u', "ALIGN_U", 0, "Straighten Y", "Align UVs along the line defined by the endpoints along the Y axis"}, 01208 {'a', "ALIGN_AUTO", 0, "Align Auto", "Automatically choose the axis on which there is most alignment already"}, 01209 {'x', "ALIGN_X", 0, "Align X", "Align UVs on X axis"}, 01210 {'y', "ALIGN_Y", 0, "Align Y", "Align UVs on Y axis"}, 01211 {0, NULL, 0, NULL, NULL}}; 01212 01213 /* identifiers */ 01214 ot->name= "Align"; 01215 ot->description= "Align selected UV vertices to an axis"; 01216 ot->idname= "UV_OT_align"; 01217 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01218 01219 /* api callbacks */ 01220 ot->exec= align_exec; 01221 ot->poll= ED_operator_image_active; /* requires space image */; 01222 01223 /* properties */ 01224 RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on."); 01225 } 01226 01227 /* ******************** weld operator **************** */ 01228 01229 static int weld_exec(bContext *C, wmOperator *UNUSED(op)) 01230 { 01231 weld_align_uv(C, 'w'); 01232 01233 return OPERATOR_FINISHED; 01234 } 01235 01236 static void UV_OT_weld(wmOperatorType *ot) 01237 { 01238 /* identifiers */ 01239 ot->name= "Weld"; 01240 ot->description= "Weld selected UV vertices together"; 01241 ot->idname= "UV_OT_weld"; 01242 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01243 01244 /* api callbacks */ 01245 ot->exec= weld_exec; 01246 ot->poll= ED_operator_uvedit; 01247 } 01248 01249 /* ******************** stitch operator **************** */ 01250 01251 /* just for averaging UVs */ 01252 typedef struct UVVertAverage { 01253 float uv[2]; 01254 int count; 01255 } UVVertAverage; 01256 01257 static int stitch_exec(bContext *C, wmOperator *op) 01258 { 01259 SpaceImage *sima; 01260 Scene *scene; 01261 Object *obedit; 01262 EditMesh *em; 01263 EditFace *efa; 01264 EditVert *eve; 01265 Image *ima; 01266 MTFace *tf; 01267 01268 scene= CTX_data_scene(C); 01269 obedit= CTX_data_edit_object(C); 01270 em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 01271 ima= CTX_data_edit_image(C); 01272 sima= CTX_wm_space_image(C); 01273 01274 if(RNA_boolean_get(op->ptr, "use_limit")) { 01275 UvVertMap *vmap; 01276 UvMapVert *vlist, *iterv; 01277 float newuv[2], limit[2]; 01278 int a, vtot; 01279 01280 limit[0]= RNA_float_get(op->ptr, "limit"); 01281 limit[1]= limit[0]; 01282 01283 EM_init_index_arrays(em, 0, 0, 1); 01284 vmap= EM_make_uv_vert_map(em, 1, 0, limit); 01285 01286 if(vmap == NULL) { 01287 BKE_mesh_end_editmesh(obedit->data, em); 01288 return OPERATOR_CANCELLED; 01289 } 01290 01291 for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) { 01292 vlist= EM_get_uv_map_vert(vmap, a); 01293 01294 while(vlist) { 01295 newuv[0]= 0; newuv[1]= 0; 01296 vtot= 0; 01297 01298 for(iterv=vlist; iterv; iterv=iterv->next) { 01299 if((iterv != vlist) && iterv->separate) 01300 break; 01301 01302 efa = EM_get_face_for_index(iterv->f); 01303 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01304 01305 if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) { 01306 newuv[0] += tf->uv[iterv->tfindex][0]; 01307 newuv[1] += tf->uv[iterv->tfindex][1]; 01308 vtot++; 01309 } 01310 } 01311 01312 if(vtot > 1) { 01313 newuv[0] /= vtot; newuv[1] /= vtot; 01314 01315 for(iterv=vlist; iterv; iterv=iterv->next) { 01316 if((iterv != vlist) && iterv->separate) 01317 break; 01318 01319 efa = EM_get_face_for_index(iterv->f); 01320 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01321 01322 if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) { 01323 tf->uv[iterv->tfindex][0]= newuv[0]; 01324 tf->uv[iterv->tfindex][1]= newuv[1]; 01325 } 01326 } 01327 } 01328 01329 vlist= iterv; 01330 } 01331 } 01332 01333 EM_free_uv_vert_map(vmap); 01334 EM_free_index_arrays(); 01335 } 01336 else { 01337 UVVertAverage *uv_average, *uvav; 01338 int count; 01339 01340 // index and count verts 01341 for(count=0, eve=em->verts.first; eve; count++, eve= eve->next) 01342 eve->tmp.l = count; 01343 01344 uv_average= MEM_callocN(sizeof(UVVertAverage)*count, "Stitch"); 01345 01346 // gather uv averages per vert 01347 for(efa= em->faces.first; efa; efa= efa->next) { 01348 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01349 01350 if(uvedit_face_visible(scene, ima, efa, tf)) { 01351 if(uvedit_uv_selected(scene, efa, tf, 0)) { 01352 uvav = uv_average + efa->v1->tmp.l; 01353 uvav->count++; 01354 uvav->uv[0] += tf->uv[0][0]; 01355 uvav->uv[1] += tf->uv[0][1]; 01356 } 01357 01358 if(uvedit_uv_selected(scene, efa, tf, 1)) { 01359 uvav = uv_average + efa->v2->tmp.l; 01360 uvav->count++; 01361 uvav->uv[0] += tf->uv[1][0]; 01362 uvav->uv[1] += tf->uv[1][1]; 01363 } 01364 01365 if(uvedit_uv_selected(scene, efa, tf, 2)) { 01366 uvav = uv_average + efa->v3->tmp.l; 01367 uvav->count++; 01368 uvav->uv[0] += tf->uv[2][0]; 01369 uvav->uv[1] += tf->uv[2][1]; 01370 } 01371 01372 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) { 01373 uvav = uv_average + efa->v4->tmp.l; 01374 uvav->count++; 01375 uvav->uv[0] += tf->uv[3][0]; 01376 uvav->uv[1] += tf->uv[3][1]; 01377 } 01378 } 01379 } 01380 01381 // apply uv welding 01382 for(efa= em->faces.first; efa; efa= efa->next) { 01383 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01384 01385 if(uvedit_face_visible(scene, ima, efa, tf)) { 01386 if(uvedit_uv_selected(scene, efa, tf, 0)) { 01387 uvav = uv_average + efa->v1->tmp.l; 01388 tf->uv[0][0] = uvav->uv[0]/uvav->count; 01389 tf->uv[0][1] = uvav->uv[1]/uvav->count; 01390 } 01391 01392 if(uvedit_uv_selected(scene, efa, tf, 1)) { 01393 uvav = uv_average + efa->v2->tmp.l; 01394 tf->uv[1][0] = uvav->uv[0]/uvav->count; 01395 tf->uv[1][1] = uvav->uv[1]/uvav->count; 01396 } 01397 01398 if(uvedit_uv_selected(scene, efa, tf, 2)) { 01399 uvav = uv_average + efa->v3->tmp.l; 01400 tf->uv[2][0] = uvav->uv[0]/uvav->count; 01401 tf->uv[2][1] = uvav->uv[1]/uvav->count; 01402 } 01403 01404 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) { 01405 uvav = uv_average + efa->v4->tmp.l; 01406 tf->uv[3][0] = uvav->uv[0]/uvav->count; 01407 tf->uv[3][1] = uvav->uv[1]/uvav->count; 01408 } 01409 } 01410 } 01411 01412 MEM_freeN(uv_average); 01413 } 01414 01415 uvedit_live_unwrap_update(sima, scene, obedit); 01416 DAG_id_tag_update(obedit->data, 0); 01417 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 01418 01419 BKE_mesh_end_editmesh(obedit->data, em); 01420 return OPERATOR_FINISHED; 01421 } 01422 01423 static void UV_OT_stitch(wmOperatorType *ot) 01424 { 01425 /* identifiers */ 01426 ot->name= "Stitch"; 01427 ot->description= "Stitch selected UV vertices by proximity"; 01428 ot->idname= "UV_OT_stitch"; 01429 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01430 01431 /* api callbacks */ 01432 ot->exec= stitch_exec; 01433 ot->poll= ED_operator_uvedit; 01434 01435 /* properties */ 01436 RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs within a specified limit distance."); 01437 RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit distance in normalized coordinates.", -FLT_MAX, FLT_MAX); 01438 } 01439 01440 /* ******************** (de)select all operator **************** */ 01441 01442 static int select_all_exec(bContext *C, wmOperator *op) 01443 { 01444 Scene *scene; 01445 ToolSettings *ts; 01446 Object *obedit; 01447 EditMesh *em; 01448 EditFace *efa; 01449 Image *ima; 01450 MTFace *tf; 01451 int action = RNA_enum_get(op->ptr, "action"); 01452 01453 scene= CTX_data_scene(C); 01454 ts= CTX_data_tool_settings(C); 01455 obedit= CTX_data_edit_object(C); 01456 em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 01457 ima= CTX_data_edit_image(C); 01458 01459 if(ts->uv_flag & UV_SYNC_SELECTION) { 01460 switch (action) { 01461 case SEL_TOGGLE: 01462 EM_toggle_select_all(em); 01463 break; 01464 case SEL_SELECT: 01465 EM_select_all(em); 01466 break; 01467 case SEL_DESELECT: 01468 EM_deselect_all(em); 01469 break; 01470 case SEL_INVERT: 01471 EM_select_swap(em); 01472 break; 01473 } 01474 } 01475 else { 01476 01477 if (action == SEL_TOGGLE) { 01478 action = SEL_SELECT; 01479 for(efa= em->faces.first; efa; efa= efa->next) { 01480 const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); 01481 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01482 01483 if(uvedit_face_visible(scene, ima, efa, tf)) { 01484 if(tf->flag & select_flag) { 01485 action = SEL_DESELECT; 01486 break; 01487 } 01488 } 01489 } 01490 } 01491 01492 for(efa= em->faces.first; efa; efa= efa->next) { 01493 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01494 01495 if(uvedit_face_visible(scene, ima, efa, tf)) { 01496 const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); 01497 01498 switch (action) { 01499 case SEL_SELECT: 01500 tf->flag |= select_flag; 01501 break; 01502 case SEL_DESELECT: 01503 tf->flag &= ~select_flag; 01504 break; 01505 case SEL_INVERT: 01506 tf->flag ^= select_flag; 01507 break; 01508 } 01509 } 01510 } 01511 } 01512 01513 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 01514 01515 BKE_mesh_end_editmesh(obedit->data, em); 01516 return OPERATOR_FINISHED; 01517 } 01518 01519 static void UV_OT_select_all(wmOperatorType *ot) 01520 { 01521 /* identifiers */ 01522 ot->name= "Select or Deselect All"; 01523 ot->description= "Change selection of all UV vertices"; 01524 ot->idname= "UV_OT_select_all"; 01525 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01526 01527 /* api callbacks */ 01528 ot->exec= select_all_exec; 01529 ot->poll= ED_operator_uvedit; 01530 01531 WM_operator_properties_select_all(ot); 01532 } 01533 01534 /* ******************** mouse select operator **************** */ 01535 01536 static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky) 01537 { 01538 int i; 01539 01540 /* this function test if some vertex needs to selected 01541 * in addition to the existing ones due to sticky select */ 01542 if(sticky == SI_STICKY_DISABLE) 01543 return 0; 01544 01545 for(i=0; i<4; i++) { 01546 if(hitv[i] == v) { 01547 if(sticky == SI_STICKY_LOC) { 01548 if(fabsf(hituv[i][0]-uv[0]) < limit[0] && fabsf(hituv[i][1]-uv[1]) < limit[1]) 01549 return 1; 01550 } 01551 else if(sticky == SI_STICKY_VERTEX) 01552 return 1; 01553 } 01554 } 01555 01556 return 0; 01557 } 01558 01559 static int mouse_select(bContext *C, float co[2], int extend, int loop) 01560 { 01561 SpaceImage *sima= CTX_wm_space_image(C); 01562 Scene *scene= CTX_data_scene(C); 01563 ToolSettings *ts= CTX_data_tool_settings(C); 01564 Object *obedit= CTX_data_edit_object(C); 01565 Image *ima= CTX_data_edit_image(C); 01566 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 01567 EditFace *efa; 01568 MTFace *tf; 01569 NearestHit hit; 01570 int a, i, select = 1, selectmode, sticky, sync, hitv[4], nvert; 01571 int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ 01572 float limit[2], *hituv[4], penalty[2]; 01573 01574 /* notice 'limit' is the same no matter the zoom level, since this is like 01575 * remove doubles and could annoying if it joined points when zoomed out. 01576 * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and 01577 * shift-selecting can consider an adjacent point close enough to add to 01578 * the selection rather than de-selecting the closest. */ 01579 01580 uvedit_pixel_to_float(sima, limit, 0.05f); 01581 uvedit_pixel_to_float(sima, penalty, 5.0f / sima->zoom); 01582 01583 /* retrieve operation mode */ 01584 if(ts->uv_flag & UV_SYNC_SELECTION) { 01585 sync= 1; 01586 01587 if(ts->selectmode & SCE_SELECT_FACE) 01588 selectmode= UV_SELECT_FACE; 01589 else if(ts->selectmode & SCE_SELECT_EDGE) 01590 selectmode= UV_SELECT_EDGE; 01591 else 01592 selectmode= UV_SELECT_VERTEX; 01593 01594 sticky= SI_STICKY_DISABLE; 01595 } 01596 else { 01597 sync= 0; 01598 selectmode= ts->uv_selectmode; 01599 sticky= (sima)? sima->sticky: 1; 01600 } 01601 01602 /* find nearest element */ 01603 if(loop) { 01604 /* find edge */ 01605 find_nearest_uv_edge(scene, ima, em, co, &hit); 01606 if(hit.efa == NULL) { 01607 BKE_mesh_end_editmesh(obedit->data, em); 01608 return OPERATOR_CANCELLED; 01609 } 01610 } 01611 else if(selectmode == UV_SELECT_VERTEX) { 01612 /* find vertex */ 01613 find_nearest_uv_vert(scene, ima, em, co, penalty, &hit); 01614 if(hit.efa == NULL) { 01615 BKE_mesh_end_editmesh(obedit->data, em); 01616 return OPERATOR_CANCELLED; 01617 } 01618 01619 /* mark 1 vertex as being hit */ 01620 for(i=0; i<4; i++) 01621 hitv[i]= 0xFFFFFFFF; 01622 01623 hitv[hit.uv]= hit.vert; 01624 hituv[hit.uv]= hit.tf->uv[hit.uv]; 01625 } 01626 else if(selectmode == UV_SELECT_EDGE) { 01627 /* find edge */ 01628 find_nearest_uv_edge(scene, ima, em, co, &hit); 01629 if(hit.efa == NULL) { 01630 BKE_mesh_end_editmesh(obedit->data, em); 01631 return OPERATOR_CANCELLED; 01632 } 01633 01634 /* mark 2 edge vertices as being hit */ 01635 for(i=0; i<4; i++) 01636 hitv[i]= 0xFFFFFFFF; 01637 01638 nvert= (hit.efa->v4)? 4: 3; 01639 01640 hitv[hit.edge]= hit.vert; 01641 hitv[(hit.edge+1)%nvert]= hit.vert2; 01642 hituv[hit.edge]= hit.tf->uv[hit.edge]; 01643 hituv[(hit.edge+1)%nvert]= hit.tf->uv[(hit.edge+1)%nvert]; 01644 } 01645 else if(selectmode == UV_SELECT_FACE) { 01646 /* find face */ 01647 find_nearest_uv_face(scene, ima, em, co, &hit); 01648 if(hit.efa == NULL) { 01649 BKE_mesh_end_editmesh(obedit->data, em); 01650 return OPERATOR_CANCELLED; 01651 } 01652 01653 /* make active */ 01654 EM_set_actFace(em, hit.efa); 01655 01656 /* mark all face vertices as being hit */ 01657 for(i=0; i<4; i++) 01658 hituv[i]= hit.tf->uv[i]; 01659 01660 hitv[0]= hit.efa->v1->tmp.l; 01661 hitv[1]= hit.efa->v2->tmp.l; 01662 hitv[2]= hit.efa->v3->tmp.l; 01663 01664 if(hit.efa->v4) hitv[3]= hit.efa->v4->tmp.l; 01665 else hitv[3]= 0xFFFFFFFF; 01666 } 01667 else if(selectmode == UV_SELECT_ISLAND) { 01668 find_nearest_uv_vert(scene, ima, em, co, NULL, &hit); 01669 01670 if(hit.efa==NULL) { 01671 BKE_mesh_end_editmesh(obedit->data, em); 01672 return OPERATOR_CANCELLED; 01673 } 01674 } 01675 else { 01676 BKE_mesh_end_editmesh(obedit->data, em); 01677 return OPERATOR_CANCELLED; 01678 } 01679 01680 /* do selection */ 01681 if(loop) { 01682 flush= select_edgeloop(scene, ima, em, &hit, limit, extend); 01683 } 01684 else if(selectmode == UV_SELECT_ISLAND) { 01685 select_linked(scene, ima, em, limit, &hit, extend); 01686 } 01687 else if(extend) { 01688 if(selectmode == UV_SELECT_VERTEX) { 01689 /* (de)select uv vertex */ 01690 if(uvedit_uv_selected(scene, hit.efa, hit.tf, hit.uv)) { 01691 uvedit_uv_deselect(scene, hit.efa, hit.tf, hit.uv); 01692 select= 0; 01693 } 01694 else { 01695 uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv); 01696 select= 1; 01697 } 01698 flush = 1; 01699 } 01700 else if(selectmode == UV_SELECT_EDGE) { 01701 /* (de)select edge */ 01702 if(uvedit_edge_selected(scene, hit.efa, hit.tf, hit.edge)) { 01703 uvedit_edge_deselect(scene, hit.efa, hit.tf, hit.edge); 01704 select= 0; 01705 } 01706 else { 01707 uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge); 01708 select= 1; 01709 } 01710 flush = 1; 01711 } 01712 else if(selectmode == UV_SELECT_FACE) { 01713 /* (de)select face */ 01714 if(uvedit_face_selected(scene, hit.efa, hit.tf)) { 01715 uvedit_face_deselect(scene, hit.efa, hit.tf); 01716 select= 0; 01717 } 01718 else { 01719 uvedit_face_select(scene, hit.efa, hit.tf); 01720 select= 1; 01721 } 01722 flush = -1; 01723 } 01724 01725 /* (de)select sticky uv nodes */ 01726 if(sticky != SI_STICKY_DISABLE) { 01727 EditVert *ev; 01728 01729 for(a=0, ev=em->verts.first; ev; ev = ev->next, a++) 01730 ev->tmp.l = a; 01731 01732 /* deselect */ 01733 if(select==0) { 01734 for(efa= em->faces.first; efa; efa= efa->next) { 01735 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01736 01737 if(uvedit_face_visible(scene, ima, efa, tf)) { 01738 if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky)) 01739 uvedit_uv_deselect(scene, efa, tf, 0); 01740 if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky)) 01741 uvedit_uv_deselect(scene, efa, tf, 1); 01742 if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky)) 01743 uvedit_uv_deselect(scene, efa, tf, 2); 01744 if(efa->v4) 01745 if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky)) 01746 uvedit_uv_deselect(scene, efa, tf, 3); 01747 } 01748 } 01749 flush = -1; 01750 } 01751 /* select */ 01752 else { 01753 for(efa= em->faces.first; efa; efa= efa->next) { 01754 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01755 01756 if(uvedit_face_visible(scene, ima, efa, tf)) { 01757 if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky)) 01758 uvedit_uv_select(scene, efa, tf, 0); 01759 if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky)) 01760 uvedit_uv_select(scene, efa, tf, 1); 01761 if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky)) 01762 uvedit_uv_select(scene, efa, tf, 2); 01763 if(efa->v4) 01764 if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky)) 01765 uvedit_uv_select(scene, efa, tf, 3); 01766 } 01767 } 01768 01769 flush = 1; 01770 } 01771 } 01772 } 01773 else { 01774 /* deselect all */ 01775 for(efa= em->faces.first; efa; efa= efa->next) { 01776 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01777 uvedit_face_deselect(scene, efa, tf); 01778 } 01779 01780 if(selectmode == UV_SELECT_VERTEX) { 01781 /* select vertex */ 01782 uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv); 01783 flush= 1; 01784 } 01785 else if(selectmode == UV_SELECT_EDGE) { 01786 /* select edge */ 01787 uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge); 01788 flush= 1; 01789 } 01790 else if(selectmode == UV_SELECT_FACE) { 01791 /* select face */ 01792 uvedit_face_select(scene, hit.efa, hit.tf); 01793 } 01794 01795 /* select sticky uvs */ 01796 if(sticky != SI_STICKY_DISABLE) { 01797 for(efa= em->faces.first; efa; efa= efa->next) { 01798 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 01799 if(uvedit_face_visible(scene, ima, efa, tf)) { 01800 if(sticky == SI_STICKY_DISABLE) continue; 01801 01802 if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky)) 01803 uvedit_uv_select(scene, efa, tf, 0); 01804 if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky)) 01805 uvedit_uv_select(scene, efa, tf, 1); 01806 if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky)) 01807 uvedit_uv_select(scene, efa, tf, 2); 01808 if(efa->v4) 01809 if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky)) 01810 uvedit_uv_select(scene, efa, tf, 3); 01811 01812 flush= 1; 01813 } 01814 } 01815 } 01816 } 01817 01818 if(sync) { 01819 /* flush for mesh selection */ 01820 if(ts->selectmode != SCE_SELECT_FACE) { 01821 if(flush==1) EM_select_flush(em); 01822 else if(flush==-1) EM_deselect_flush(em); 01823 } 01824 } 01825 01826 DAG_id_tag_update(obedit->data, 0); 01827 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 01828 01829 BKE_mesh_end_editmesh(obedit->data, em); 01830 return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED; 01831 } 01832 01833 static int select_exec(bContext *C, wmOperator *op) 01834 { 01835 float co[2]; 01836 int extend, loop; 01837 01838 RNA_float_get_array(op->ptr, "location", co); 01839 extend= RNA_boolean_get(op->ptr, "extend"); 01840 loop= 0; 01841 01842 return mouse_select(C, co, extend, loop); 01843 } 01844 01845 static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) 01846 { 01847 ARegion *ar= CTX_wm_region(C); 01848 float co[2]; 01849 01850 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); 01851 RNA_float_set_array(op->ptr, "location", co); 01852 01853 return select_exec(C, op); 01854 } 01855 01856 static void UV_OT_select(wmOperatorType *ot) 01857 { 01858 /* identifiers */ 01859 ot->name= "Select"; 01860 ot->description= "Select UV vertices"; 01861 ot->idname= "UV_OT_select"; 01862 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01863 01864 /* api callbacks */ 01865 ot->exec= select_exec; 01866 ot->invoke= select_invoke; 01867 ot->poll= ED_operator_image_active; /* requires space image */; 01868 01869 /* properties */ 01870 RNA_def_boolean(ot->srna, "extend", 0, 01871 "Extend", "Extend selection rather than clearing the existing selection."); 01872 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, 01873 "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f); 01874 } 01875 01876 /* ******************** loop select operator **************** */ 01877 01878 static int select_loop_exec(bContext *C, wmOperator *op) 01879 { 01880 float co[2]; 01881 int extend, loop; 01882 01883 RNA_float_get_array(op->ptr, "location", co); 01884 extend= RNA_boolean_get(op->ptr, "extend"); 01885 loop= 1; 01886 01887 return mouse_select(C, co, extend, loop); 01888 } 01889 01890 static int select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) 01891 { 01892 ARegion *ar= CTX_wm_region(C); 01893 float co[2]; 01894 01895 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); 01896 RNA_float_set_array(op->ptr, "location", co); 01897 01898 return select_loop_exec(C, op); 01899 } 01900 01901 static void UV_OT_select_loop(wmOperatorType *ot) 01902 { 01903 /* identifiers */ 01904 ot->name= "Loop Select"; 01905 ot->description= "Select a loop of connected UV vertices"; 01906 ot->idname= "UV_OT_select_loop"; 01907 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01908 01909 /* api callbacks */ 01910 ot->exec= select_loop_exec; 01911 ot->invoke= select_loop_invoke; 01912 ot->poll= ED_operator_image_active; /* requires space image */; 01913 01914 /* properties */ 01915 RNA_def_boolean(ot->srna, "extend", 0, 01916 "Extend", "Extend selection rather than clearing the existing selection."); 01917 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, 01918 "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f); 01919 } 01920 01921 /* ******************** linked select operator **************** */ 01922 01923 static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, int pick) 01924 { 01925 SpaceImage *sima= CTX_wm_space_image(C); 01926 Scene *scene= CTX_data_scene(C); 01927 ToolSettings *ts= CTX_data_tool_settings(C); 01928 Object *obedit= CTX_data_edit_object(C); 01929 Image *ima= CTX_data_edit_image(C); 01930 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 01931 float limit[2]; 01932 int extend; 01933 01934 NearestHit hit, *hit_p= NULL; 01935 01936 if(ts->uv_flag & UV_SYNC_SELECTION) { 01937 BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled."); 01938 BKE_mesh_end_editmesh(obedit->data, em); 01939 return OPERATOR_CANCELLED; 01940 } 01941 01942 extend= RNA_boolean_get(op->ptr, "extend"); 01943 uvedit_pixel_to_float(sima, limit, 0.05f); 01944 01945 if(pick) { 01946 float co[2]; 01947 01948 if(event) { 01949 /* invoke */ 01950 ARegion *ar= CTX_wm_region(C); 01951 01952 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); 01953 RNA_float_set_array(op->ptr, "location", co); 01954 } 01955 else { 01956 /* exec */ 01957 RNA_float_get_array(op->ptr, "location", co); 01958 } 01959 01960 find_nearest_uv_vert(scene, ima, em, co, NULL, &hit); 01961 hit_p= &hit; 01962 } 01963 01964 select_linked(scene, ima, em, limit, hit_p, extend); 01965 01966 DAG_id_tag_update(obedit->data, 0); 01967 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 01968 01969 BKE_mesh_end_editmesh(obedit->data, em); 01970 return OPERATOR_FINISHED; 01971 } 01972 01973 static int select_linked_exec(bContext *C, wmOperator *op) 01974 { 01975 return select_linked_internal(C, op, NULL, 0); 01976 } 01977 01978 static void UV_OT_select_linked(wmOperatorType *ot) 01979 { 01980 /* identifiers */ 01981 ot->name= "Select Linked"; 01982 ot->description= "Select all UV vertices linked to the active UV map"; 01983 ot->idname= "UV_OT_select_linked"; 01984 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01985 01986 /* api callbacks */ 01987 ot->exec= select_linked_exec; 01988 ot->poll= ED_operator_image_active; /* requires space image */ 01989 01990 /* properties */ 01991 RNA_def_boolean(ot->srna, "extend", 0, 01992 "Extend", "Extend selection rather than clearing the existing selection."); 01993 } 01994 01995 static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) 01996 { 01997 return select_linked_internal(C, op, event, 1); 01998 } 01999 02000 static int select_linked_pick_exec(bContext *C, wmOperator *op) 02001 { 02002 return select_linked_internal(C, op, NULL, 1); 02003 } 02004 02005 static void UV_OT_select_linked_pick(wmOperatorType *ot) 02006 { 02007 /* identifiers */ 02008 ot->name= "Select Linked Pick"; 02009 ot->description= "Select all UV vertices linked under the mouse"; 02010 ot->idname= "UV_OT_select_linked_pick"; 02011 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02012 02013 /* api callbacks */ 02014 ot->invoke= select_linked_pick_invoke; 02015 ot->exec= select_linked_pick_exec; 02016 ot->poll= ED_operator_image_active; /* requires space image */; 02017 02018 /* properties */ 02019 RNA_def_boolean(ot->srna, "extend", 0, 02020 "Extend", "Extend selection rather than clearing the existing selection."); 02021 02022 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, 02023 "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f); 02024 } 02025 02026 /* ******************** unlink selection operator **************** */ 02027 02028 static int unlink_selection_exec(bContext *C, wmOperator *op) 02029 { 02030 Scene *scene= CTX_data_scene(C); 02031 ToolSettings *ts= CTX_data_tool_settings(C); 02032 Object *obedit= CTX_data_edit_object(C); 02033 Image *ima= CTX_data_edit_image(C); 02034 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02035 EditFace *efa; 02036 MTFace *tf; 02037 02038 if(ts->uv_flag & UV_SYNC_SELECTION) { 02039 BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled."); 02040 BKE_mesh_end_editmesh(obedit->data, em); 02041 return OPERATOR_CANCELLED; 02042 } 02043 02044 for(efa= em->faces.first; efa; efa= efa->next) { 02045 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02046 02047 if(uvedit_face_visible(scene, ima, efa, tf)) { 02048 const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); 02049 if(~tf->flag & select_flag) 02050 tf->flag &= ~select_flag; 02051 02052 } 02053 } 02054 02055 DAG_id_tag_update(obedit->data, 0); 02056 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02057 02058 BKE_mesh_end_editmesh(obedit->data, em); 02059 return OPERATOR_FINISHED; 02060 } 02061 02062 static void UV_OT_unlink_selected(wmOperatorType *ot) 02063 { 02064 /* identifiers */ 02065 ot->name= "Unlink Selection"; 02066 ot->description= "Unlink selected UV vertices from active UV map"; 02067 ot->idname= "UV_OT_unlink_selected"; 02068 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02069 02070 /* api callbacks */ 02071 ot->exec= unlink_selection_exec; 02072 ot->poll= ED_operator_uvedit; 02073 } 02074 02075 /* ******************** border select operator **************** */ 02076 02077 /* This function sets the selection on tagged faces, need because settings the 02078 * selection a face is done in a number of places but it also needs to respect 02079 * the sticky modes for the UV verts, so dealing with the sticky modes is best 02080 * done in a separate function. 02081 * 02082 * De-selects faces that have been tagged on efa->tmp.l. */ 02083 02084 static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, short select) 02085 { 02086 /* Selecting UV Faces with some modes requires us to change 02087 * the selection in other faces (depending on the sticky mode). 02088 * 02089 * This only needs to be done when the Mesh is not used for 02090 * selection (so for sticky modes, vertex or location based). */ 02091 02092 ToolSettings *ts= CTX_data_tool_settings(C); 02093 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02094 EditFace *efa; 02095 MTFace *tf; 02096 int nverts, i; 02097 02098 if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) { 02099 /* Tag all verts as untouched, then touch the ones that have a face center 02100 * in the loop and select all MTFace UV's that use a touched vert. */ 02101 EditVert *eve; 02102 02103 for(eve= em->verts.first; eve; eve= eve->next) 02104 eve->tmp.l = 0; 02105 02106 for(efa= em->faces.first; efa; efa= efa->next) { 02107 if(efa->tmp.l) { 02108 if(efa->v4) 02109 efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1; 02110 else 02111 efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1; 02112 } 02113 } 02114 02115 /* now select tagged verts */ 02116 for(efa= em->faces.first; efa; efa= efa->next) { 02117 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02118 nverts= efa->v4? 4: 3; 02119 for(i=0; i<nverts; i++) { 02120 if((*(&efa->v1 + i))->tmp.l) { 02121 if(select) 02122 uvedit_uv_select(scene, efa, tf, i); 02123 else 02124 uvedit_uv_deselect(scene, efa, tf, i); 02125 } 02126 } 02127 } 02128 } 02129 else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) { 02130 EditFace *efa_vlist; 02131 MTFace *tf_vlist; 02132 UvMapVert *start_vlist=NULL, *vlist_iter; 02133 struct UvVertMap *vmap; 02134 float limit[2]; 02135 unsigned int efa_index; 02136 //EditVert *eve; /* removed vert counting for now */ 02137 //int a; 02138 02139 uvedit_pixel_to_float(sima, limit, 0.05); 02140 02141 EM_init_index_arrays(em, 0, 0, 1); 02142 vmap= EM_make_uv_vert_map(em, 0, 0, limit); 02143 02144 /* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */ 02145 /*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) 02146 eve->tmp.l = a; */ 02147 02148 if(vmap == NULL) { 02149 BKE_mesh_end_editmesh(obedit->data, em); 02150 return; 02151 } 02152 02153 for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) { 02154 if(efa->tmp.l) { 02155 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02156 nverts= efa->v4? 4: 3; 02157 02158 for(i=0; i<nverts; i++) { 02159 if(select) 02160 uvedit_uv_select(scene, efa, tf, i); 02161 else 02162 uvedit_uv_deselect(scene, efa, tf, i); 02163 02164 vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l); 02165 02166 while (vlist_iter) { 02167 if(vlist_iter->separate) 02168 start_vlist = vlist_iter; 02169 02170 if(efa_index == vlist_iter->f) 02171 break; 02172 02173 vlist_iter = vlist_iter->next; 02174 } 02175 02176 vlist_iter = start_vlist; 02177 while (vlist_iter) { 02178 02179 if(vlist_iter != start_vlist && vlist_iter->separate) 02180 break; 02181 02182 if(efa_index != vlist_iter->f) { 02183 efa_vlist = EM_get_face_for_index(vlist_iter->f); 02184 tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE); 02185 02186 if(select) 02187 uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); 02188 else 02189 uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); 02190 } 02191 vlist_iter = vlist_iter->next; 02192 } 02193 } 02194 } 02195 } 02196 EM_free_index_arrays(); 02197 EM_free_uv_vert_map(vmap); 02198 02199 } 02200 else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ 02201 for(efa= em->faces.first; efa; efa= efa->next) { 02202 if(efa->tmp.l) { 02203 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02204 if(select) 02205 uvedit_face_select(scene, efa, tf); 02206 else 02207 uvedit_face_deselect(scene, efa, tf); 02208 } 02209 } 02210 } 02211 BKE_mesh_end_editmesh(obedit->data, em); 02212 } 02213 02214 static int border_select_exec(bContext *C, wmOperator *op) 02215 { 02216 SpaceImage *sima= CTX_wm_space_image(C); 02217 Scene *scene= CTX_data_scene(C); 02218 ToolSettings *ts= CTX_data_tool_settings(C); 02219 Object *obedit= CTX_data_edit_object(C); 02220 Image *ima= CTX_data_edit_image(C); 02221 ARegion *ar= CTX_wm_region(C); 02222 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02223 EditFace *efa; 02224 MTFace *tface; 02225 rcti rect; 02226 rctf rectf; 02227 int change, pinned, select, faces; 02228 02229 /* get rectangle from operator */ 02230 rect.xmin= RNA_int_get(op->ptr, "xmin"); 02231 rect.ymin= RNA_int_get(op->ptr, "ymin"); 02232 rect.xmax= RNA_int_get(op->ptr, "xmax"); 02233 rect.ymax= RNA_int_get(op->ptr, "ymax"); 02234 02235 UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin); 02236 UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax); 02237 02238 /* figure out what to select/deselect */ 02239 select= (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT); 02240 pinned= RNA_boolean_get(op->ptr, "pinned"); 02241 02242 if(ts->uv_flag & UV_SYNC_SELECTION) 02243 faces= (ts->selectmode == SCE_SELECT_FACE); 02244 else 02245 faces= (ts->uv_selectmode == UV_SELECT_FACE); 02246 02247 /* do actual selection */ 02248 if(faces && !pinned) { 02249 /* handle face selection mode */ 02250 float cent[2]; 02251 02252 change= 0; 02253 02254 for(efa= em->faces.first; efa; efa= efa->next) { 02255 /* assume not touched */ 02256 efa->tmp.l = 0; 02257 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02258 if(uvedit_face_visible(scene, ima, efa, tface)) { 02259 uv_center(tface->uv, cent, efa->v4 != NULL); 02260 if(BLI_in_rctf(&rectf, cent[0], cent[1])) { 02261 efa->tmp.l = change = 1; 02262 } 02263 } 02264 } 02265 02266 /* (de)selects all tagged faces and deals with sticky modes */ 02267 if(change) 02268 uv_faces_do_sticky(C, sima, scene, obedit, select); 02269 } 02270 else { 02271 /* other selection modes */ 02272 change= 1; 02273 02274 for(efa= em->faces.first; efa; efa= efa->next) { 02275 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02276 if(uvedit_face_visible(scene, ima, efa, tface)) { 02277 if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) { 02278 /* UV_SYNC_SELECTION - can't do pinned selection */ 02279 if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) { 02280 if(select) uvedit_uv_select(scene, efa, tface, 0); 02281 else uvedit_uv_deselect(scene, efa, tface, 0); 02282 } 02283 if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) { 02284 if(select) uvedit_uv_select(scene, efa, tface, 1); 02285 else uvedit_uv_deselect(scene, efa, tface, 1); 02286 } 02287 if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) { 02288 if(select) uvedit_uv_select(scene, efa, tface, 2); 02289 else uvedit_uv_deselect(scene, efa, tface, 2); 02290 } 02291 if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) { 02292 if(select) uvedit_uv_select(scene, efa, tface, 3); 02293 else uvedit_uv_deselect(scene, efa, tface, 3); 02294 } 02295 } 02296 else if(pinned) { 02297 if((tface->unwrap & TF_PIN1) && 02298 BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) { 02299 02300 if(select) uvedit_uv_select(scene, efa, tface, 0); 02301 else uvedit_uv_deselect(scene, efa, tface, 0); 02302 } 02303 if((tface->unwrap & TF_PIN2) && 02304 BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) { 02305 02306 if(select) uvedit_uv_select(scene, efa, tface, 1); 02307 else uvedit_uv_deselect(scene, efa, tface, 1); 02308 } 02309 if((tface->unwrap & TF_PIN3) && 02310 BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) { 02311 02312 if(select) uvedit_uv_select(scene, efa, tface, 2); 02313 else uvedit_uv_deselect(scene, efa, tface, 2); 02314 } 02315 if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) { 02316 if(select) uvedit_uv_select(scene, efa, tface, 3); 02317 else uvedit_uv_deselect(scene, efa, tface, 3); 02318 } 02319 } 02320 } 02321 } 02322 } 02323 02324 if(change) { 02325 /* make sure newly selected vert selection is updated*/ 02326 if(ts->uv_flag & UV_SYNC_SELECTION) { 02327 if(ts->selectmode != SCE_SELECT_FACE) { 02328 if(select) EM_select_flush(em); 02329 else EM_deselect_flush(em); 02330 } 02331 } 02332 02333 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02334 02335 BKE_mesh_end_editmesh(obedit->data, em); 02336 return OPERATOR_FINISHED; 02337 } 02338 02339 BKE_mesh_end_editmesh(obedit->data, em); 02340 return OPERATOR_CANCELLED; 02341 } 02342 02343 static void UV_OT_select_border(wmOperatorType *ot) 02344 { 02345 /* identifiers */ 02346 ot->name= "Border Select"; 02347 ot->description= "Select UV vertices using border selection"; 02348 ot->idname= "UV_OT_select_border"; 02349 02350 /* api callbacks */ 02351 ot->invoke= WM_border_select_invoke; 02352 ot->exec= border_select_exec; 02353 ot->modal= WM_border_select_modal; 02354 ot->poll= ED_operator_image_active; /* requires space image */; 02355 ot->cancel= WM_border_select_cancel; 02356 02357 /* flags */ 02358 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02359 02360 /* properties */ 02361 RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only."); 02362 02363 WM_operator_properties_gesture_border(ot, FALSE); 02364 } 02365 02366 /* ******************** circle select operator **************** */ 02367 02368 static void select_uv_inside_ellipse(Scene *scene, int select, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, int select_index) 02369 { 02370 /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ 02371 float x, y, r2, *uv; 02372 02373 uv= tface->uv[index]; 02374 02375 x= (uv[0] - offset[0])*ell[0]; 02376 y= (uv[1] - offset[1])*ell[1]; 02377 02378 r2 = x*x + y*y; 02379 if(r2 < 1.0f) { 02380 if(select) uvedit_uv_select(scene, efa, tface, select_index); 02381 else uvedit_uv_deselect(scene, efa, tface, select_index); 02382 } 02383 } 02384 02385 static int circle_select_exec(bContext *C, wmOperator *op) 02386 { 02387 SpaceImage *sima= CTX_wm_space_image(C); 02388 Scene *scene= CTX_data_scene(C); 02389 Object *obedit= CTX_data_edit_object(C); 02390 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02391 ARegion *ar= CTX_wm_region(C); 02392 EditFace *efa; 02393 MTFace *tface; 02394 int x, y, radius, width, height, select; 02395 float zoomx, zoomy, offset[2], ellipse[2]; 02396 int gesture_mode= RNA_int_get(op->ptr, "gesture_mode"); 02397 02398 /* get operator properties */ 02399 select= (gesture_mode == GESTURE_MODAL_SELECT); 02400 x= RNA_int_get(op->ptr, "x"); 02401 y= RNA_int_get(op->ptr, "y"); 02402 radius= RNA_int_get(op->ptr, "radius"); 02403 02404 /* compute ellipse size and location, not a circle since we deal 02405 * with non square image. ellipse is normalized, r = 1.0. */ 02406 ED_space_image_size(sima, &width, &height); 02407 ED_space_image_zoom(sima, ar, &zoomx, &zoomy); 02408 02409 ellipse[0]= width*zoomx/radius; 02410 ellipse[1]= height*zoomy/radius; 02411 02412 UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]); 02413 02414 /* do selection */ 02415 for(efa= em->faces.first; efa; efa= efa->next) { 02416 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02417 select_uv_inside_ellipse(scene, select, efa, tface, 0, offset, ellipse, 0); 02418 select_uv_inside_ellipse(scene, select, efa, tface, 1, offset, ellipse, 1); 02419 select_uv_inside_ellipse(scene, select, efa, tface, 2, offset, ellipse, 2); 02420 if(efa->v4) 02421 select_uv_inside_ellipse(scene, select, efa, tface, 3, offset, ellipse, 3); 02422 } 02423 02424 if(select) EM_select_flush(em); 02425 else EM_deselect_flush(em); 02426 02427 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02428 02429 BKE_mesh_end_editmesh(obedit->data, em); 02430 return OPERATOR_FINISHED; 02431 } 02432 02433 static void UV_OT_circle_select(wmOperatorType *ot) 02434 { 02435 /* identifiers */ 02436 ot->name= "Circle Select"; 02437 ot->description= "Select UV vertices using circle selection"; 02438 ot->idname= "UV_OT_circle_select"; 02439 02440 /* api callbacks */ 02441 ot->invoke= WM_gesture_circle_invoke; 02442 ot->modal= WM_gesture_circle_modal; 02443 ot->exec= circle_select_exec; 02444 ot->poll= ED_operator_image_active; /* requires space image */; 02445 ot->cancel= WM_gesture_circle_cancel; 02446 02447 /* flags */ 02448 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02449 02450 /* properties */ 02451 RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); 02452 RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); 02453 RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX); 02454 RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); 02455 } 02456 02457 /* ******************** snap cursor operator **************** */ 02458 02459 static void snap_uv_to_pixel(float *uvco, float w, float h) 02460 { 02461 uvco[0] = ((float)((int)((uvco[0]*w) + 0.5f)))/w; 02462 uvco[1] = ((float)((int)((uvco[1]*h) + 0.5f)))/h; 02463 } 02464 02465 static void snap_cursor_to_pixels(SpaceImage *sima) 02466 { 02467 int width= 0, height= 0; 02468 02469 ED_space_image_size(sima, &width, &height); 02470 snap_uv_to_pixel(sima->cursor, width, height); 02471 } 02472 02473 static int snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima) 02474 { 02475 return uvedit_center(scene, ima, obedit, sima->cursor, sima->around); 02476 } 02477 02478 static int snap_cursor_exec(bContext *C, wmOperator *op) 02479 { 02480 SpaceImage *sima= CTX_wm_space_image(C); 02481 Scene *scene= CTX_data_scene(C); 02482 Object *obedit= CTX_data_edit_object(C); 02483 Image *ima= CTX_data_edit_image(C); 02484 int change= 0; 02485 02486 switch(RNA_enum_get(op->ptr, "target")) { 02487 case 0: 02488 snap_cursor_to_pixels(sima); 02489 change= 1; 02490 break; 02491 case 1: 02492 change= snap_cursor_to_selection(scene, ima, obedit, sima); 02493 break; 02494 } 02495 02496 if(!change) 02497 return OPERATOR_CANCELLED; 02498 02499 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_IMAGE, sima); 02500 02501 return OPERATOR_FINISHED; 02502 } 02503 02504 static void UV_OT_snap_cursor(wmOperatorType *ot) 02505 { 02506 static EnumPropertyItem target_items[] = { 02507 {0, "PIXELS", 0, "Pixels", ""}, 02508 {1, "SELECTED", 0, "Selected", ""}, 02509 {0, NULL, 0, NULL, NULL}}; 02510 02511 /* identifiers */ 02512 ot->name= "Snap Cursor"; 02513 ot->description= "Snap cursor to target type"; 02514 ot->idname= "UV_OT_snap_cursor"; 02515 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02516 02517 /* api callbacks */ 02518 ot->exec= snap_cursor_exec; 02519 ot->poll= ED_operator_image_active; /* requires space image */; 02520 02521 /* properties */ 02522 RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to."); 02523 } 02524 02525 /* ******************** snap selection operator **************** */ 02526 02527 static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima) 02528 { 02529 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02530 EditFace *efa; 02531 MTFace *tface; 02532 short change= 0; 02533 02534 for(efa= em->faces.first; efa; efa= efa->next) { 02535 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02536 if(uvedit_face_visible(scene, ima, efa, tface)) { 02537 if(uvedit_uv_selected(scene, efa, tface, 0)) VECCOPY2D(tface->uv[0], sima->cursor); 02538 if(uvedit_uv_selected(scene, efa, tface, 1)) VECCOPY2D(tface->uv[1], sima->cursor); 02539 if(uvedit_uv_selected(scene, efa, tface, 2)) VECCOPY2D(tface->uv[2], sima->cursor); 02540 if(efa->v4) 02541 if(uvedit_uv_selected(scene, efa, tface, 3)) VECCOPY2D(tface->uv[3], sima->cursor); 02542 02543 change= 1; 02544 } 02545 } 02546 02547 BKE_mesh_end_editmesh(obedit->data, em); 02548 return change; 02549 } 02550 02551 static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit) 02552 { 02553 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02554 EditFace *efa; 02555 EditVert *eve; 02556 MTFace *tface; 02557 short change = 0; 02558 int count = 0; 02559 float *coords; 02560 short *usercount, users; 02561 02562 /* set all verts to -1 : an unused index*/ 02563 for(eve= em->verts.first; eve; eve= eve->next) 02564 eve->tmp.l=-1; 02565 02566 /* index every vert that has a selected UV using it, but only once so as to 02567 * get unique indices and to count how much to malloc */ 02568 for(efa= em->faces.first; efa; efa= efa->next) { 02569 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02570 02571 if(uvedit_face_visible(scene, ima, efa, tface)) { 02572 if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->tmp.l==-1) efa->v1->tmp.l= count++; 02573 if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->tmp.l==-1) efa->v2->tmp.l= count++; 02574 if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->tmp.l==-1) efa->v3->tmp.l= count++; 02575 if(efa->v4) 02576 if(uvedit_uv_selected(scene, efa, tface, 3) && efa->v4->tmp.l==-1) efa->v4->tmp.l= count++; 02577 02578 change = 1; 02579 02580 /* optional speedup */ 02581 efa->tmp.p = tface; 02582 } 02583 else 02584 efa->tmp.p = NULL; 02585 } 02586 02587 coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords"); 02588 usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts"); 02589 02590 /* add all UV coords from visible, unselected UV coords as well as counting them to average later */ 02591 for(efa= em->faces.first; efa; efa= efa->next) { 02592 if((tface=(MTFace *)efa->tmp.p)) { 02593 /* is this an unselected UV we can snap to? */ 02594 if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 0))) { 02595 coords[efa->v1->tmp.l*2] += tface->uv[0][0]; 02596 coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1]; 02597 usercount[efa->v1->tmp.l]++; 02598 change = 1; 02599 } 02600 if(efa->v2->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 1))) { 02601 coords[efa->v2->tmp.l*2] += tface->uv[1][0]; 02602 coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1]; 02603 usercount[efa->v2->tmp.l]++; 02604 change = 1; 02605 } 02606 if(efa->v3->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 2))) { 02607 coords[efa->v3->tmp.l*2] += tface->uv[2][0]; 02608 coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1]; 02609 usercount[efa->v3->tmp.l]++; 02610 change = 1; 02611 } 02612 02613 if(efa->v4) { 02614 if(efa->v4->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 3))) { 02615 coords[efa->v4->tmp.l*2] += tface->uv[3][0]; 02616 coords[(efa->v4->tmp.l*2)+1] += tface->uv[3][1]; 02617 usercount[efa->v4->tmp.l]++; 02618 change = 1; 02619 } 02620 } 02621 } 02622 } 02623 02624 /* no other verts selected, bail out */ 02625 if(!change) { 02626 MEM_freeN(coords); 02627 MEM_freeN(usercount); 02628 BKE_mesh_end_editmesh(obedit->data, em); 02629 return change; 02630 } 02631 02632 /* copy the averaged unselected UVs back to the selected UVs */ 02633 for(efa= em->faces.first; efa; efa= efa->next) { 02634 if((tface=(MTFace *)efa->tmp.p)) { 02635 02636 if( uvedit_uv_selected(scene, efa, tface, 0) && 02637 efa->v1->tmp.l >= 0 && 02638 (users = usercount[efa->v1->tmp.l]) 02639 ) { 02640 tface->uv[0][0] = coords[efa->v1->tmp.l*2] / users; 02641 tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1] / users; 02642 } 02643 02644 if( uvedit_uv_selected(scene, efa, tface, 1) && 02645 efa->v2->tmp.l >= 0 && 02646 (users = usercount[efa->v2->tmp.l]) 02647 ) { 02648 tface->uv[1][0] = coords[efa->v2->tmp.l*2] / users; 02649 tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1] / users; 02650 } 02651 02652 if( uvedit_uv_selected(scene, efa, tface, 2) && 02653 efa->v3->tmp.l >= 0 && 02654 (users = usercount[efa->v3->tmp.l]) 02655 ) { 02656 tface->uv[2][0] = coords[efa->v3->tmp.l*2] / users; 02657 tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1] / users; 02658 } 02659 02660 if(efa->v4) { 02661 if( uvedit_uv_selected(scene, efa, tface, 3) && 02662 efa->v4->tmp.l >= 0 && 02663 (users = usercount[efa->v4->tmp.l]) 02664 ) { 02665 tface->uv[3][0] = coords[efa->v4->tmp.l*2] / users; 02666 tface->uv[3][1] = coords[(efa->v4->tmp.l*2)+1] / users; 02667 } 02668 } 02669 } 02670 } 02671 02672 MEM_freeN(coords); 02673 MEM_freeN(usercount); 02674 02675 BKE_mesh_end_editmesh(obedit->data, em); 02676 return change; 02677 } 02678 02679 static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) 02680 { 02681 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02682 Image *ima; 02683 EditFace *efa; 02684 MTFace *tface; 02685 int width= 0, height= 0; 02686 float w, h; 02687 short change = 0; 02688 02689 if(!sima) 02690 return 0; 02691 02692 ima= sima->image; 02693 02694 ED_space_image_size(sima, &width, &height); 02695 w = (float)width; 02696 h = (float)height; 02697 02698 for(efa= em->faces.first; efa; efa= efa->next) { 02699 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02700 if(uvedit_face_visible(scene, ima, efa, tface)) { 02701 if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_pixel(tface->uv[0], w, h); 02702 if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_pixel(tface->uv[1], w, h); 02703 if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_pixel(tface->uv[2], w, h); 02704 if(efa->v4) 02705 if(uvedit_uv_selected(scene, efa, tface, 3)) snap_uv_to_pixel(tface->uv[3], w, h); 02706 02707 change = 1; 02708 } 02709 } 02710 02711 BKE_mesh_end_editmesh(obedit->data, em); 02712 return change; 02713 } 02714 02715 static int snap_selection_exec(bContext *C, wmOperator *op) 02716 { 02717 SpaceImage *sima= CTX_wm_space_image(C); 02718 Scene *scene= CTX_data_scene(C); 02719 Object *obedit= CTX_data_edit_object(C); 02720 Image *ima= CTX_data_edit_image(C); 02721 int change= 0; 02722 02723 switch(RNA_enum_get(op->ptr, "target")) { 02724 case 0: 02725 change= snap_uvs_to_pixels(sima, scene, obedit); 02726 break; 02727 case 1: 02728 change= snap_uvs_to_cursor(scene, ima, obedit, sima); 02729 break; 02730 case 2: 02731 change= snap_uvs_to_adjacent_unselected(scene, ima, obedit); 02732 break; 02733 } 02734 02735 if(!change) 02736 return OPERATOR_CANCELLED; 02737 02738 uvedit_live_unwrap_update(sima, scene, obedit); 02739 DAG_id_tag_update(obedit->data, 0); 02740 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 02741 02742 return OPERATOR_FINISHED; 02743 } 02744 02745 static void UV_OT_snap_selected(wmOperatorType *ot) 02746 { 02747 static EnumPropertyItem target_items[] = { 02748 {0, "PIXELS", 0, "Pixels", ""}, 02749 {1, "CURSOR", 0, "Cursor", ""}, 02750 {2, "ADJACENT_UNSELECTED", 0, "Adjacent Unselected", ""}, 02751 {0, NULL, 0, NULL, NULL}}; 02752 02753 /* identifiers */ 02754 ot->name= "Snap Selection"; 02755 ot->description= "Snap selected UV vertices to target type"; 02756 ot->idname= "UV_OT_snap_selected"; 02757 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02758 02759 /* api callbacks */ 02760 ot->exec= snap_selection_exec; 02761 ot->poll= ED_operator_image_active; /* requires space image */; 02762 02763 /* properties */ 02764 RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to."); 02765 } 02766 02767 /* ******************** pin operator **************** */ 02768 02769 static int pin_exec(bContext *C, wmOperator *op) 02770 { 02771 Scene *scene= CTX_data_scene(C); 02772 Object *obedit= CTX_data_edit_object(C); 02773 Image *ima= CTX_data_edit_image(C); 02774 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02775 EditFace *efa; 02776 MTFace *tface; 02777 int clear= RNA_boolean_get(op->ptr, "clear"); 02778 02779 for(efa= em->faces.first; efa; efa= efa->next) { 02780 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02781 02782 if(uvedit_face_visible(scene, ima, efa, tface)) { 02783 if(!clear) { 02784 if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap |= TF_PIN1; 02785 if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap |= TF_PIN2; 02786 if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap |= TF_PIN3; 02787 if(efa->v4) 02788 if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap |= TF_PIN4; 02789 } 02790 else { 02791 if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap &= ~TF_PIN1; 02792 if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap &= ~TF_PIN2; 02793 if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap &= ~TF_PIN3; 02794 if(efa->v4) 02795 if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap &= ~TF_PIN4; 02796 } 02797 } 02798 } 02799 02800 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 02801 02802 BKE_mesh_end_editmesh(obedit->data, em); 02803 return OPERATOR_FINISHED; 02804 } 02805 02806 static void UV_OT_pin(wmOperatorType *ot) 02807 { 02808 /* identifiers */ 02809 ot->name= "Pin"; 02810 ot->description= "Set/clear selected UV vertices as anchored between multiple unwrap operations"; 02811 ot->idname= "UV_OT_pin"; 02812 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02813 02814 /* api callbacks */ 02815 ot->exec= pin_exec; 02816 ot->poll= ED_operator_uvedit; 02817 02818 /* properties */ 02819 RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear pinning for the selection instead of setting it."); 02820 } 02821 02822 /******************* select pinned operator ***************/ 02823 02824 static int select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) 02825 { 02826 Scene *scene= CTX_data_scene(C); 02827 Object *obedit= CTX_data_edit_object(C); 02828 Image *ima= CTX_data_edit_image(C); 02829 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02830 EditFace *efa; 02831 MTFace *tface; 02832 02833 for(efa= em->faces.first; efa; efa= efa->next) { 02834 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02835 02836 if(uvedit_face_visible(scene, ima, efa, tface)) { 02837 if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa, tface, 0); 02838 if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa, tface, 1); 02839 if(tface->unwrap & TF_PIN3) uvedit_uv_select(scene, efa, tface, 2); 02840 if(efa->v4) { 02841 if(tface->unwrap & TF_PIN4) uvedit_uv_select(scene, efa, tface, 3); 02842 } 02843 } 02844 } 02845 02846 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02847 02848 BKE_mesh_end_editmesh(obedit->data, em); 02849 return OPERATOR_FINISHED; 02850 } 02851 02852 static void UV_OT_select_pinned(wmOperatorType *ot) 02853 { 02854 /* identifiers */ 02855 ot->name= "Selected Pinned"; 02856 ot->description= "Select all pinned UV vertices"; 02857 ot->idname= "UV_OT_select_pinned"; 02858 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02859 02860 /* api callbacks */ 02861 ot->exec= select_pinned_exec; 02862 ot->poll= ED_operator_uvedit; 02863 } 02864 02865 /********************** hide operator *********************/ 02866 02867 static int hide_exec(bContext *C, wmOperator *op) 02868 { 02869 SpaceImage *sima= CTX_wm_space_image(C); 02870 ToolSettings *ts= CTX_data_tool_settings(C); 02871 Object *obedit= CTX_data_edit_object(C); 02872 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 02873 EditFace *efa; 02874 MTFace *tf; 02875 int swap= RNA_boolean_get(op->ptr, "unselected"); 02876 int facemode= sima ? sima->flag & SI_SELACTFACE : 0; 02877 02878 if(ts->uv_flag & UV_SYNC_SELECTION) { 02879 EM_hide_mesh(em, swap); 02880 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02881 02882 BKE_mesh_end_editmesh(obedit->data, em); 02883 return OPERATOR_FINISHED; 02884 } 02885 02886 if(swap) { 02887 for(efa= em->faces.first; efa; efa= efa->next) { 02888 if(efa->f & SELECT) { 02889 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02890 if(facemode) { 02891 /* Pretend face mode */ 02892 if(( (efa->v4==NULL && 02893 ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) || 02894 ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) == 0) { 02895 02896 if(em->selectmode == SCE_SELECT_FACE) { 02897 efa->f &= ~SELECT; 02898 /* must re-select after */ 02899 efa->e1->f &= ~SELECT; 02900 efa->e2->f &= ~SELECT; 02901 efa->e3->f &= ~SELECT; 02902 if(efa->e4) efa->e4->f &= ~SELECT; 02903 } 02904 else 02905 EM_select_face(efa, 0); 02906 } 02907 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 02908 } 02909 else if(em->selectmode == SCE_SELECT_FACE) { 02910 const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); 02911 if((tf->flag & select_flag)==0) { 02912 EM_select_face(efa, 0); 02913 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 02914 } 02915 } 02916 else { 02917 /* EM_deselect_flush will deselect the face */ 02918 if((tf->flag & TF_SEL1)==0) efa->v1->f &= ~SELECT; 02919 if((tf->flag & TF_SEL2)==0) efa->v2->f &= ~SELECT; 02920 if((tf->flag & TF_SEL3)==0) efa->v3->f &= ~SELECT; 02921 if((efa->v4) && (tf->flag & TF_SEL4)==0) efa->v4->f &= ~SELECT; 02922 02923 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 02924 } 02925 } 02926 } 02927 } 02928 else { 02929 for(efa= em->faces.first; efa; efa= efa->next) { 02930 if(efa->f & SELECT) { 02931 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02932 02933 if(facemode) { 02934 if( (efa->v4==NULL && 02935 ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) || 02936 ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) { 02937 02938 if(em->selectmode == SCE_SELECT_FACE) { 02939 efa->f &= ~SELECT; 02940 /* must re-select after */ 02941 efa->e1->f &= ~SELECT; 02942 efa->e2->f &= ~SELECT; 02943 efa->e3->f &= ~SELECT; 02944 if(efa->e4) efa->e4->f &= ~SELECT; 02945 } 02946 else 02947 EM_select_face(efa, 0); 02948 } 02949 02950 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 02951 } 02952 else if(em->selectmode == SCE_SELECT_FACE) { 02953 const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3); 02954 if(tf->flag & select_flag) 02955 EM_select_face(efa, 0); 02956 02957 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 02958 } 02959 else { 02960 /* EM_deselect_flush will deselect the face */ 02961 if(tf->flag & TF_SEL1) efa->v1->f &= ~SELECT; 02962 if(tf->flag & TF_SEL2) efa->v2->f &= ~SELECT; 02963 if(tf->flag & TF_SEL3) efa->v3->f &= ~SELECT; 02964 if((efa->v4) && tf->flag & TF_SEL4) efa->v4->f &= ~SELECT; 02965 02966 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); 02967 } 02968 } 02969 } 02970 } 02971 02972 /*deselects too many but ok for now*/ 02973 if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)) 02974 EM_deselect_flush(em); 02975 02976 if(em->selectmode==SCE_SELECT_FACE) { 02977 /* de-selected all edges from faces that were de-selected. 02978 * now make sure all faces that are selected also have selected edges */ 02979 for(efa= em->faces.first; efa; efa= efa->next) 02980 if(efa->f & SELECT) 02981 EM_select_face(efa, 1); 02982 } 02983 02984 EM_validate_selections(em); 02985 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 02986 02987 BKE_mesh_end_editmesh(obedit->data, em); 02988 return OPERATOR_FINISHED; 02989 } 02990 02991 static void UV_OT_hide(wmOperatorType *ot) 02992 { 02993 /* identifiers */ 02994 ot->name= "Hide Selected"; 02995 ot->description= "Hide (un)selected UV vertices"; 02996 ot->idname= "UV_OT_hide"; 02997 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 02998 02999 /* api callbacks */ 03000 ot->exec= hide_exec; 03001 ot->poll= ED_operator_uvedit; 03002 03003 /* props */ 03004 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected."); 03005 } 03006 03007 /****************** reveal operator ******************/ 03008 03009 static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) 03010 { 03011 SpaceImage *sima= CTX_wm_space_image(C); 03012 ToolSettings *ts= CTX_data_tool_settings(C); 03013 Object *obedit= CTX_data_edit_object(C); 03014 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); 03015 EditFace *efa; 03016 MTFace *tf; 03017 int facemode= sima ? sima->flag & SI_SELACTFACE : 0; 03018 int stickymode= sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; 03019 03020 /* call the mesh function if we are in mesh sync sel */ 03021 if(ts->uv_flag & UV_SYNC_SELECTION) { 03022 EM_reveal_mesh(em); 03023 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 03024 03025 BKE_mesh_end_editmesh(obedit->data, em); 03026 return OPERATOR_FINISHED; 03027 } 03028 03029 if(facemode) { 03030 if(em->selectmode == SCE_SELECT_FACE) { 03031 for(efa= em->faces.first; efa; efa= efa->next) { 03032 if(!(efa->h) && !(efa->f & SELECT)) { 03033 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 03034 EM_select_face(efa, 1); 03035 tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4; 03036 } 03037 } 03038 } 03039 else { 03040 /* enable adjacent faces to have disconnected UV selections if sticky is disabled */ 03041 if(!stickymode) { 03042 for(efa= em->faces.first; efa; efa= efa->next) { 03043 if(!(efa->h) && !(efa->f & SELECT)) { 03044 /* All verts must be unselected for the face to be selected in the UV view */ 03045 if((efa->v1->f&SELECT)==0 && (efa->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==NULL || (efa->v4->f&SELECT)==0)) { 03046 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 03047 03048 tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4; 03049 /* Cant use EM_select_face here because it unselects the verts 03050 * and we cant tell if the face was totally unselected or not */ 03051 /*EM_select_face(efa, 1); 03052 * 03053 * See Loop with EM_select_face() below... */ 03054 efa->f |= SELECT; 03055 } 03056 } 03057 } 03058 } 03059 else { 03060 for(efa= em->faces.first; efa; efa= efa->next) { 03061 if(!(efa->h) && !(efa->f & SELECT)) { 03062 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 03063 03064 if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;} 03065 if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;} 03066 if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;} 03067 if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;} 03068 03069 efa->f |= SELECT; 03070 } 03071 } 03072 } 03073 03074 /* Select all edges and verts now */ 03075 for(efa= em->faces.first; efa; efa= efa->next) 03076 /* we only selected the face flags, and didnt changes edges or verts, fix this now */ 03077 if(!(efa->h) && (efa->f & SELECT)) 03078 EM_select_face(efa, 1); 03079 03080 EM_select_flush(em); 03081 } 03082 } 03083 else if(em->selectmode == SCE_SELECT_FACE) { 03084 for(efa= em->faces.first; efa; efa= efa->next) { 03085 if(!(efa->h) && !(efa->f & SELECT)) { 03086 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 03087 efa->f |= SELECT; 03088 tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4; 03089 } 03090 } 03091 03092 /* Select all edges and verts now */ 03093 for(efa= em->faces.first; efa; efa= efa->next) 03094 /* we only selected the face flags, and didnt changes edges or verts, fix this now */ 03095 if(!(efa->h) && (efa->f & SELECT)) 03096 EM_select_face(efa, 1); 03097 } 03098 else { 03099 for(efa= em->faces.first; efa; efa= efa->next) { 03100 if(!(efa->h) && !(efa->f & SELECT)) { 03101 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 03102 03103 if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;} 03104 if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;} 03105 if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;} 03106 if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;} 03107 03108 efa->f |= SELECT; 03109 } 03110 } 03111 03112 /* Select all edges and verts now */ 03113 for(efa= em->faces.first; efa; efa= efa->next) 03114 /* we only selected the face flags, and didnt changes edges or verts, fix this now */ 03115 if(!(efa->h) && (efa->f & SELECT)) 03116 EM_select_face(efa, 1); 03117 } 03118 03119 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); 03120 03121 BKE_mesh_end_editmesh(obedit->data, em); 03122 return OPERATOR_FINISHED; 03123 } 03124 03125 static void UV_OT_reveal(wmOperatorType *ot) 03126 { 03127 /* identifiers */ 03128 ot->name= "Reveal Hidden"; 03129 ot->description= "Reveal all hidden UV vertices"; 03130 ot->idname= "UV_OT_reveal"; 03131 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03132 03133 /* api callbacks */ 03134 ot->exec= reveal_exec; 03135 ot->poll= ED_operator_uvedit; 03136 } 03137 03138 /******************** set 3d cursor operator ********************/ 03139 03140 static int set_2d_cursor_exec(bContext *C, wmOperator *op) 03141 { 03142 SpaceImage *sima = CTX_wm_space_image(C); 03143 float location[2]; 03144 03145 if(!sima) 03146 return OPERATOR_CANCELLED; 03147 03148 RNA_float_get_array(op->ptr, "location", location); 03149 sima->cursor[0]= location[0]; 03150 sima->cursor[1]= location[1]; 03151 03152 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_IMAGE, NULL); 03153 03154 return OPERATOR_FINISHED; 03155 } 03156 03157 static int set_2d_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event) 03158 { 03159 ARegion *ar= CTX_wm_region(C); 03160 float location[2]; 03161 03162 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]); 03163 RNA_float_set_array(op->ptr, "location", location); 03164 03165 return set_2d_cursor_exec(C, op); 03166 } 03167 03168 static void UV_OT_cursor_set(wmOperatorType *ot) 03169 { 03170 /* identifiers */ 03171 ot->name= "Set 2D Cursor"; 03172 ot->description= "Set 2D cursor location"; 03173 ot->idname= "UV_OT_cursor_set"; 03174 03175 /* api callbacks */ 03176 ot->exec= set_2d_cursor_exec; 03177 ot->invoke= set_2d_cursor_invoke; 03178 ot->poll= ED_operator_image_active; /* requires space image */; 03179 03180 /* flags */ 03181 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03182 03183 /* properties */ 03184 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in 0.0-1.0 coordinates.", -10.0f, 10.0f); 03185 } 03186 03187 /********************** set tile operator **********************/ 03188 03189 static int set_tile_exec(bContext *C, wmOperator *op) 03190 { 03191 Image *ima= CTX_data_edit_image(C); 03192 int tile[2]; 03193 Object *obedit= CTX_data_edit_object(C); 03194 03195 RNA_int_get_array(op->ptr, "tile", tile); 03196 03197 if(uvedit_set_tile(obedit, ima, tile[0] + ima->xrep*tile[1])) { 03198 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 03199 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_IMAGE, NULL); 03200 03201 return OPERATOR_FINISHED; 03202 } 03203 03204 return OPERATOR_CANCELLED; 03205 } 03206 03207 static int set_tile_invoke(bContext *C, wmOperator *op, wmEvent *event) 03208 { 03209 SpaceImage *sima= CTX_wm_space_image(C); 03210 Image *ima= CTX_data_edit_image(C); 03211 ARegion *ar= CTX_wm_region(C); 03212 float fx, fy; 03213 int tile[2]; 03214 03215 if(!ima || !(ima->tpageflag & IMA_TILES)) 03216 return OPERATOR_CANCELLED; 03217 03218 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy); 03219 03220 if(fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) { 03221 fx= fx*ima->xrep; 03222 fy= fy*ima->yrep; 03223 03224 tile[0]= fx; 03225 tile[1]= fy; 03226 03227 sima->curtile= tile[1]*ima->xrep + tile[0]; 03228 RNA_int_set_array(op->ptr, "tile", tile); 03229 } 03230 03231 return set_tile_exec(C, op); 03232 } 03233 03234 static void UV_OT_tile_set(wmOperatorType *ot) 03235 { 03236 /* identifiers */ 03237 ot->name= "Set Tile"; 03238 ot->description= "Set UV image tile coordinates"; 03239 ot->idname= "UV_OT_tile_set"; 03240 03241 /* api callbacks */ 03242 ot->exec= set_tile_exec; 03243 ot->invoke= set_tile_invoke; 03244 ot->poll= ED_operator_image_active; /* requires space image */; 03245 03246 /* flags */ 03247 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03248 03249 /* properties */ 03250 RNA_def_int_vector(ot->srna, "tile", 2, NULL, 0, INT_MAX, "Tile", "Tile coordinate.", 0, 10); 03251 } 03252 03253 /* ************************** registration **********************************/ 03254 03255 void ED_operatortypes_uvedit(void) 03256 { 03257 WM_operatortype_append(UV_OT_select_all); 03258 WM_operatortype_append(UV_OT_select); 03259 WM_operatortype_append(UV_OT_select_loop); 03260 WM_operatortype_append(UV_OT_select_linked); 03261 WM_operatortype_append(UV_OT_select_linked_pick); 03262 WM_operatortype_append(UV_OT_unlink_selected); 03263 WM_operatortype_append(UV_OT_select_pinned); 03264 WM_operatortype_append(UV_OT_select_border); 03265 WM_operatortype_append(UV_OT_circle_select); 03266 03267 WM_operatortype_append(UV_OT_snap_cursor); 03268 WM_operatortype_append(UV_OT_snap_selected); 03269 03270 WM_operatortype_append(UV_OT_align); 03271 WM_operatortype_append(UV_OT_stitch); 03272 WM_operatortype_append(UV_OT_weld); 03273 WM_operatortype_append(UV_OT_pin); 03274 03275 WM_operatortype_append(UV_OT_average_islands_scale); 03276 WM_operatortype_append(UV_OT_cube_project); 03277 WM_operatortype_append(UV_OT_cylinder_project); 03278 WM_operatortype_append(UV_OT_from_view); 03279 WM_operatortype_append(UV_OT_minimize_stretch); 03280 WM_operatortype_append(UV_OT_pack_islands); 03281 WM_operatortype_append(UV_OT_reset); 03282 WM_operatortype_append(UV_OT_sphere_project); 03283 WM_operatortype_append(UV_OT_unwrap); 03284 03285 WM_operatortype_append(UV_OT_reveal); 03286 WM_operatortype_append(UV_OT_hide); 03287 03288 WM_operatortype_append(UV_OT_cursor_set); 03289 WM_operatortype_append(UV_OT_tile_set); 03290 } 03291 03292 void ED_keymap_uvedit(wmKeyConfig *keyconf) 03293 { 03294 wmKeyMap *keymap; 03295 wmKeyMapItem *kmi; 03296 03297 keymap= WM_keymap_find(keyconf, "UV Editor", 0, 0); 03298 keymap->poll= ED_operator_uvedit; 03299 03300 /* pick selection */ 03301 WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); 03302 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1); 03303 WM_keymap_add_item(keymap, "UV_OT_select_loop", SELECTMOUSE, KM_PRESS, KM_ALT, 0); 03304 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_loop", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_ALT, 0)->ptr, "extend", 1); 03305 03306 /* border/circle selection */ 03307 WM_keymap_add_item(keymap, "UV_OT_select_border", BKEY, KM_PRESS, 0, 0); 03308 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_border", BKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "pinned", 1); 03309 WM_keymap_add_item(keymap, "UV_OT_circle_select", CKEY, KM_PRESS, 0, 0); 03310 03311 /* selection manipulation */ 03312 WM_keymap_add_item(keymap, "UV_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0); 03313 WM_keymap_add_item(keymap, "UV_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0); 03314 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_linked", LKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "extend", TRUE); 03315 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", TRUE); 03316 03317 WM_keymap_add_item(keymap, "UV_OT_unlink_selected", LKEY, KM_PRESS, KM_ALT, 0); 03318 WM_keymap_add_item(keymap, "UV_OT_select_all", AKEY, KM_PRESS, 0, 0); 03319 RNA_enum_set(WM_keymap_add_item(keymap, "UV_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "action", SEL_INVERT); 03320 WM_keymap_add_item(keymap, "UV_OT_select_pinned", PKEY, KM_PRESS, KM_SHIFT, 0); 03321 03322 WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_weldalign", WKEY, KM_PRESS, 0, 0); 03323 03324 /* uv operations */ 03325 WM_keymap_add_item(keymap, "UV_OT_stitch", VKEY, KM_PRESS, 0, 0); 03326 WM_keymap_add_item(keymap, "UV_OT_pin", PKEY, KM_PRESS, 0, 0); 03327 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_pin", PKEY, KM_PRESS, KM_ALT, 0)->ptr, "clear", 1); 03328 03329 /* unwrap */ 03330 WM_keymap_add_item(keymap, "UV_OT_unwrap", EKEY, KM_PRESS, 0, 0); 03331 WM_keymap_add_item(keymap, "UV_OT_minimize_stretch", VKEY, KM_PRESS, KM_CTRL, 0); 03332 WM_keymap_add_item(keymap, "UV_OT_pack_islands", PKEY, KM_PRESS, KM_CTRL, 0); 03333 WM_keymap_add_item(keymap, "UV_OT_average_islands_scale", AKEY, KM_PRESS, KM_CTRL, 0); 03334 03335 /* hide */ 03336 WM_keymap_add_item(keymap, "UV_OT_hide", HKEY, KM_PRESS, 0, 0); 03337 RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1); 03338 WM_keymap_add_item(keymap, "UV_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0); 03339 03340 /* cursor */ 03341 WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0); 03342 WM_keymap_add_item(keymap, "UV_OT_tile_set", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0); 03343 03344 /* menus */ 03345 WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_snap", SKEY, KM_PRESS, KM_SHIFT, 0); 03346 WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_select_mode", TABKEY, KM_PRESS, KM_CTRL, 0); 03347 03348 /* pivot */ 03349 kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0); 03350 RNA_string_set(kmi->ptr, "data_path", "space_data.uv_editor.pivot_point"); 03351 RNA_string_set(kmi->ptr, "value", "CENTER"); 03352 03353 kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, KM_CTRL, 0); 03354 RNA_string_set(kmi->ptr, "data_path", "space_data.uv_editor.pivot_point"); 03355 RNA_string_set(kmi->ptr, "value", "MEDIAN"); 03356 03357 kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0); 03358 RNA_string_set(kmi->ptr, "data_path", "space_data.uv_editor.pivot_point"); 03359 RNA_string_set(kmi->ptr, "value", "CURSOR"); 03360 03361 ED_object_generic_keymap(keyconf, keymap, 2); 03362 03363 transform_keymap_for_space(keyconf, keymap, SPACE_IMAGE); 03364 } 03365