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