4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
34 #include "MEM_guardedalloc.h"
36 #include "DNA_object_types.h"
37 #include "DNA_mesh_types.h"
38 #include "DNA_meshdata_types.h"
39 #include "DNA_space_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_windowmanager_types.h"
44 #include "BLI_arithb.h"
45 #include "BLI_blenlib.h"
46 #include "BLI_editVert.h"
48 #include "BKE_context.h"
49 #include "BKE_customdata.h"
50 #include "BKE_depsgraph.h"
51 #include "BKE_image.h"
52 #include "BKE_library.h"
54 #include "BKE_report.h"
55 #include "BKE_utildefines.h"
59 #include "ED_screen.h"
60 #include "ED_transform.h"
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64 #include "RNA_types.h"
69 #include "UI_view2d.h"
71 #include "uvedit_intern.h"
73 /************************* state testing ************************/
75 int ED_uvedit_test(Object *obedit)
80 if(!obedit || obedit->type != OB_MESH)
83 em = BKE_mesh_get_editmesh(obedit->data);
84 ret = EM_texFaceCheck(em);
85 BKE_mesh_end_editmesh(obedit->data, em);
90 /************************* assign image ************************/
92 void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *previma)
99 /* skip assigning these procedural images... */
100 if(ima && (ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE))
103 /* verify we have a mesh we can work with */
104 if(!obedit || (obedit->type != OB_MESH))
107 em= BKE_mesh_get_editmesh(((Mesh*)obedit->data));
108 if(!em || !em->faces.first) {
109 BKE_mesh_end_editmesh(obedit->data, em);
113 /* ensure we have a uv layer */
114 if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) {
115 EM_add_data_layer(em, &em->fdata, CD_MTFACE);
119 /* now assign to all visible faces */
120 for(efa= em->faces.first; efa; efa= efa->next) {
121 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
123 if(uvedit_face_visible(scene, previma, efa, tf)) {
128 if(ima->id.us==0) id_us_plus(&ima->id);
129 else id_lib_extern(&ima->id);
140 /* and update depdency graph */
142 DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
144 BKE_mesh_end_editmesh(obedit->data, em);
147 /* dotile - 1, set the tile flag (from the space image)
148 * 2, set the tile index for the faces. */
149 void ED_uvedit_set_tile(bContext *C, Scene *scene, Object *obedit, Image *ima, int curtile)
155 /* verify if we have something to do */
156 if(!ima || !ED_uvedit_test(obedit))
159 /* skip assigning these procedural images... */
160 if(ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
163 em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
165 for(efa= em->faces.first; efa; efa= efa->next) {
166 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
168 if(efa->h==0 && efa->f & SELECT)
169 tf->tile= curtile; /* set tile index */
172 DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
173 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
174 BKE_mesh_end_editmesh(obedit->data, em);
177 /*********************** space conversion *********************/
179 static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist)
184 ED_space_image_size(sima, &width, &height);
191 dist[0]= pixeldist/width;
192 dist[1]= pixeldist/height;
195 /*************** visibility and selection utilities **************/
197 int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
199 ToolSettings *ts= scene->toolsettings;
201 if(ts->uv_flag & UV_SYNC_SELECTION)
204 return (efa->h==0 && (efa->f & SELECT));
207 int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
209 ToolSettings *ts= scene->toolsettings;
211 if(ts->uv_flag & UV_SHOW_SAME_IMAGE)
212 return (tf->tpage==ima)? uvedit_face_visible_nolocal(scene, efa): 0;
214 return uvedit_face_visible_nolocal(scene, efa);
217 int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
219 ToolSettings *ts= scene->toolsettings;
221 if(ts->uv_flag & UV_SYNC_SELECTION)
222 return (efa->f & SELECT);
224 return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4));
227 void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
229 ToolSettings *ts= scene->toolsettings;
231 if(ts->uv_flag & UV_SYNC_SELECTION)
232 EM_select_face(efa, 1);
234 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
237 void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
239 ToolSettings *ts= scene->toolsettings;
241 if(ts->uv_flag & UV_SYNC_SELECTION)
242 EM_select_face(efa, 0);
244 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
247 int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
249 ToolSettings *ts= scene->toolsettings;
250 int nvert= (efa->v4)? 4: 3;
252 if(ts->uv_flag & UV_SYNC_SELECTION) {
253 if(ts->selectmode == SCE_SELECT_FACE)
254 return (efa->f & SELECT);
255 else if(ts->selectmode == SCE_SELECT_EDGE)
256 return (*(&efa->e1 + i))->f & SELECT;
258 return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT));
261 return (tf->flag & TF_SEL_MASK(i)) && (tf->flag & TF_SEL_MASK((i+1)%nvert));
264 void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
266 ToolSettings *ts= scene->toolsettings;
267 int nvert= (efa->v4)? 4: 3;
269 if(ts->uv_flag & UV_SYNC_SELECTION) {
270 if(ts->selectmode == SCE_SELECT_FACE)
271 EM_select_face(efa, 1);
272 else if(ts->selectmode == SCE_SELECT_EDGE)
273 EM_select_edge((*(&efa->e1 + i)), 1);
275 (efa->v1 + i)->f |= SELECT;
276 (efa->v1 + (i+1)%nvert)->f |= SELECT;
280 tf->flag |= TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert);
283 void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
285 ToolSettings *ts= scene->toolsettings;
286 int nvert= (efa->v4)? 4: 3;
288 if(ts->uv_flag & UV_SYNC_SELECTION) {
289 if(ts->selectmode == SCE_SELECT_FACE)
290 EM_select_face(efa, 0);
291 else if(ts->selectmode == SCE_SELECT_EDGE)
292 EM_select_edge((*(&efa->e1 + i)), 0);
294 (efa->v1 + i)->f &= ~SELECT;
295 (efa->v1 + (i+1)%nvert)->f &= ~SELECT;
299 tf->flag &= ~(TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert));
302 int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
304 ToolSettings *ts= scene->toolsettings;
306 if(ts->uv_flag & UV_SYNC_SELECTION) {
307 if(ts->selectmode == SCE_SELECT_FACE)
308 return (efa->f & SELECT);
310 return (*(&efa->v1 + i))->f & SELECT;
313 return tf->flag & TF_SEL_MASK(i);
316 void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
318 ToolSettings *ts= scene->toolsettings;
320 if(ts->uv_flag & UV_SYNC_SELECTION) {
321 if(ts->selectmode == SCE_SELECT_FACE)
322 EM_select_face(efa, 1);
324 (*(&efa->v1 + i))->f |= SELECT;
327 tf->flag |= TF_SEL_MASK(i);
330 void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
332 ToolSettings *ts= scene->toolsettings;
334 if(ts->uv_flag & UV_SYNC_SELECTION) {
335 if(ts->selectmode == SCE_SELECT_FACE)
336 EM_select_face(efa, 0);
338 (*(&efa->v1 + i))->f &= ~SELECT;
341 tf->flag &= ~TF_SEL_MASK(i);
344 /*********************** geometric utilities ***********************/
346 void uv_center(float uv[][2], float cent[2], int quad)
349 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0] + uv[3][0]) / 4.0;
350 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1] + uv[3][1]) / 4.0;
353 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0]) / 3.0;
354 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1]) / 3.0;
358 float uv_area(float uv[][2], int quad)
361 return AreaF2Dfl(uv[0], uv[1], uv[2]) + AreaF2Dfl(uv[0], uv[2], uv[3]);
363 return AreaF2Dfl(uv[0], uv[1], uv[2]);
366 void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy)
368 uv[0][0] = uv_orig[0][0]*aspx;
369 uv[0][1] = uv_orig[0][1]*aspy;
371 uv[1][0] = uv_orig[1][0]*aspx;
372 uv[1][1] = uv_orig[1][1]*aspy;
374 uv[2][0] = uv_orig[2][0]*aspx;
375 uv[2][1] = uv_orig[2][1]*aspy;
377 uv[3][0] = uv_orig[3][0]*aspx;
378 uv[3][1] = uv_orig[3][1]*aspy;
381 int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float *max)
383 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
388 INIT_MINMAX2(min, max);
391 for(efa= em->faces.first; efa; efa= efa->next) {
392 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
393 if(uvedit_face_visible(scene, ima, efa, tf)) {
394 if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); sel = 1; }
395 if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); sel = 1; }
396 if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); sel = 1; }
397 if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); sel = 1; }
401 BKE_mesh_end_editmesh(obedit->data, em);
405 int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, int mode)
407 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
410 float min[2], max[2];
414 if(ED_uvedit_minmax(scene, ima, obedit, min, max))
418 INIT_MINMAX2(min, max);
420 for(efa= em->faces.first; efa; efa= efa->next) {
421 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
423 if(uvedit_face_visible(scene, ima, efa, tf)) {
424 if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); change= 1;}
425 if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); change= 1;}
426 if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); change= 1;}
427 if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); change= 1;}
433 cent[0]= (min[0]+max[0])/2.0;
434 cent[1]= (min[1]+max[1])/2.0;
436 BKE_mesh_end_editmesh(obedit->data, em);
440 BKE_mesh_end_editmesh(obedit->data, em);
444 /************************** find nearest ****************************/
446 typedef struct NearestHit {
454 static void find_nearest_uv_edge(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
463 memset(hit, 0, sizeof(*hit));
465 for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
468 for(efa= em->faces.first; efa; efa= efa->next) {
469 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
471 if(uvedit_face_visible(scene, ima, efa, tf)) {
472 nverts= efa->v4? 4: 3;
474 for(i=0; i<nverts; i++) {
475 dist= PdistVL2Dfl(co, tf->uv[i], tf->uv[(i+1)%nverts]);
483 hit->vert= (*(&efa->v1 + i))->tmp.l;
484 hit->vert2= (*(&efa->v1 + ((i+1)%nverts)))->tmp.l;
491 static void find_nearest_uv_face(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
495 float mindist, dist, cent[2];
499 memset(hit, 0, sizeof(*hit));
501 for(efa= em->faces.first; efa; efa= efa->next) {
502 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
504 if(uvedit_face_visible(scene, ima, efa, tf)) {
505 nverts= efa->v4? 4: 3;
506 cent[0]= cent[1]= 0.0f;
508 for(i=0; i<nverts; i++) {
509 cent[0] += tf->uv[i][0];
510 cent[1] += tf->uv[i][1];
515 dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]);
526 static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float uv[2])
528 float m[3], v1[3], v2[3], c1, c2;
531 id1= (id+nverts-1)%nverts;
532 id2= (id+nverts+1)%nverts;
536 Vec2Subf(v1, tf->uv[id1], tf->uv[id]);
537 Vec2Subf(v2, tf->uv[id2], tf->uv[id]);
539 /* m and v2 on same side of v-v1? */
540 c1= v1[0]*m[1] - v1[1]*m[0];
541 c2= v1[0]*v2[1] - v1[1]*v2[0];
546 /* m and v1 on same side of v-v2? */
547 c1= v2[0]*m[1] - v2[1]*m[0];
548 c2= v2[0]*v1[1] - v2[1]*v1[0];
550 return (c1*c2 >= 0.0f);
553 static void find_nearest_uv_vert(Scene *scene, Image *ima, EditMesh *em, float co[2], float penalty[2], NearestHit *hit)
562 memset(hit, 0, sizeof(*hit));
564 for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
567 for(efa= em->faces.first; efa; efa= efa->next) {
568 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
570 if(uvedit_face_visible(scene, ima, efa, tf)) {
571 nverts= efa->v4? 4: 3;
573 for(i=0; i<nverts; i++) {
574 if(penalty && uvedit_uv_selected(scene, efa, tf, i))
575 dist= fabs(co[0]-tf->uv[i][0])+penalty[0] + fabs(co[1]-tf->uv[i][1])+penalty[1];
577 dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
581 if(!nearest_uv_between(tf, nverts, i, co, tf->uv[i]))
590 hit->vert= (*(&efa->v1 + i))->tmp.l;
597 int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2], float uv[2])
599 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
603 int i, nverts, found= 0;
609 for(efa= em->faces.first; efa; efa= efa->next) {
610 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
612 if(uvedit_face_visible(scene, ima, efa, tf)) {
613 nverts= efa->v4? 4: 3;
615 for(i=0; i<nverts; i++) {
616 dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
629 BKE_mesh_end_editmesh(obedit->data, em);
633 /*********************** loop select ***********************/
635 static void uv_vertex_loop_flag(UvMapVert *first)
640 for(iterv=first; iterv; iterv=iterv->next) {
641 if(iterv->separate && iterv!=first)
651 static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a)
653 UvMapVert *iterv, *first;
655 first= EM_get_uv_map_vert(vmap, (*(&efa->v1 + a))->tmp.l);
657 for(iterv=first; iterv; iterv=iterv->next) {
660 if(iterv->f == efa->tmp.l)
667 static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
669 UvMapVert *iterv1, *iterv2;
673 /* count number of faces this edge has */
674 for(iterv1=first1; iterv1; iterv1=iterv1->next) {
675 if(iterv1->separate && iterv1 != first1)
678 for(iterv2=first2; iterv2; iterv2=iterv2->next) {
679 if(iterv2->separate && iterv2 != first2)
682 if(iterv1->f == iterv2->f) {
683 /* if face already tagged, don't do this edge */
684 efa= EM_get_face_for_index(iterv1->f);
694 if(*totface == 0) /* start edge */
696 else if(tot != *totface) /* check for same number of faces as start edge */
700 for(iterv1=first1; iterv1; iterv1=iterv1->next) {
701 if(iterv1->separate && iterv1 != first1)
704 for(iterv2=first2; iterv2; iterv2=iterv2->next) {
705 if(iterv2->separate && iterv2 != first2)
708 if(iterv1->f == iterv2->f) {
709 efa= EM_get_face_for_index(iterv1->f);
719 static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *hit, float limit[2], int extend)
725 UvMapVert *iterv1, *iterv2;
726 int a, count, looking, nverts, starttotf, select;
729 EM_init_index_arrays(em, 0, 0, 1);
730 vmap= EM_make_uv_vert_map(em, 0, 0, limit);
732 for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
735 for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) {
737 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
738 uvedit_face_deselect(scene, efa, tf);
745 /* set flags for first face and verts */
746 nverts= (hit->efa->v4)? 4: 3;
747 iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
748 iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
749 uv_vertex_loop_flag(iterv1);
750 uv_vertex_loop_flag(iterv2);
753 uv_edge_tag_faces(iterv1, iterv2, &starttotf);
755 /* sorry, first edge isnt even ok */
756 if(iterv1->flag==0 && iterv2->flag==0) looking= 0;
763 /* find correct valence edges which are not tagged yet, but connect to tagged one */
764 for(efa= em->faces.first; efa; efa=efa->next) {
765 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
767 if(!efa->f1 && uvedit_face_visible(scene, ima, efa, tf)) {
768 nverts= (efa->v4)? 4: 3;
769 for(a=0; a<nverts; a++) {
770 /* check face not hidden and not tagged */
771 iterv1= uv_vertex_map_get(vmap, efa, a);
772 iterv2= uv_vertex_map_get(vmap, efa, (a+1)%nverts);
774 /* check if vertex is tagged and has right valence */
775 if(iterv1->flag || iterv2->flag) {
776 if(uv_edge_tag_faces(iterv1, iterv2, &starttotf)) {
780 uv_vertex_loop_flag(iterv1);
781 uv_vertex_loop_flag(iterv2);
790 /* do the actual select/deselect */
791 nverts= (hit->efa->v4)? 4: 3;
792 iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
793 iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
798 tf= CustomData_em_get(&em->fdata, hit->efa->data, CD_MTFACE);
800 if(uvedit_uv_selected(scene, hit->efa, tf, hit->edge) && uvedit_uv_selected(scene, hit->efa, tf, hit->edge))
808 for(efa= em->faces.first; efa; efa=efa->next) {
809 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
811 nverts= (efa->v4)? 4: 3;
812 for(a=0; a<nverts; a++) {
813 iterv1= uv_vertex_map_get(vmap, efa, a);
816 if(select) uvedit_uv_select(scene, efa, tf, a);
817 else uvedit_uv_deselect(scene, efa, tf, a);
823 EM_free_uv_vert_map(vmap);
824 EM_free_index_arrays();
826 return (select)? 1: -1;
829 /*********************** linked select ***********************/
831 static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2], NearestHit *hit, int extend)
836 UvMapVert *vlist, *iterv, *startv;
837 int a, i, nverts, j, stacksize= 0, *stack;
840 vmap= EM_make_uv_vert_map(em, 1, 1, limit);
844 stack= MEM_mallocN(sizeof(*stack)* BLI_countlist(&em->faces), "UvLinkStack");
845 flag= MEM_callocN(sizeof(*flag)*BLI_countlist(&em->faces), "UvLinkFlag");
848 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
849 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
851 if(uvedit_face_visible(scene, ima, efa, tf)) {
852 if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
861 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
862 if(efa == hit->efa) {
871 while(stacksize > 0) {
875 for(j=0, efa= em->faces.first; efa; efa= efa->next, j++)
879 nverts= efa->v4? 4: 3;
881 for(i=0; i<nverts; i++) {
882 /* make_uv_vert_map_EM sets verts tmp.l to the indicies */
883 vlist= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
887 for(iterv=vlist; iterv; iterv=iterv->next) {
894 for(iterv=startv; iterv; iterv=iterv->next) {
895 if((startv != iterv) && (iterv->separate))
897 else if(!flag[iterv->f]) {
899 stack[stacksize]= iterv->f;;
907 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
908 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
910 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
912 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
915 else if(extend && hit) {
916 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
918 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
920 if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
923 else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
929 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
931 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
932 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
937 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
939 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
940 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
948 EM_free_uv_vert_map(vmap);
951 /* ******************** align operator **************** */
953 static void weld_align_uv(bContext *C, int tool)
961 float cent[2], min[2], max[2];
963 scene= CTX_data_scene(C);
964 obedit= CTX_data_edit_object(C);
965 em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
966 ima= CTX_data_edit_image(C);
968 INIT_MINMAX2(min, max);
971 for(efa= em->faces.first; efa; efa= efa->next) {
972 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
974 if(uvedit_face_visible(scene, ima, efa, tf)) {
975 if(uvedit_uv_selected(scene, efa, tf, 0))
976 DO_MINMAX2(tf->uv[0], min, max)
977 if(uvedit_uv_selected(scene, efa, tf, 1))
978 DO_MINMAX2(tf->uv[1], min, max)
979 if(uvedit_uv_selected(scene, efa, tf, 2))
980 DO_MINMAX2(tf->uv[2], min, max)
981 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
982 DO_MINMAX2(tf->uv[3], min, max)
986 tool= (max[0]-min[0] >= max[1]-min[1])? 'y': 'x';
989 uvedit_center(scene, ima, obedit, cent, 0);
991 if(tool == 'x' || tool == 'w') {
992 for(efa= em->faces.first; efa; efa= efa->next) {
993 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
994 if(uvedit_face_visible(scene, ima, efa, tf)) {
995 if(uvedit_uv_selected(scene, efa, tf, 0))
996 tf->uv[0][0]= cent[0];
997 if(uvedit_uv_selected(scene, efa, tf, 1))
998 tf->uv[1][0]= cent[0];
999 if(uvedit_uv_selected(scene, efa, tf, 2))
1000 tf->uv[2][0]= cent[0];
1001 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
1002 tf->uv[3][0]= cent[0];
1007 if(tool == 'y' || tool == 'w') {
1008 for(efa= em->faces.first; efa; efa= efa->next) {
1009 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1010 if(uvedit_face_visible(scene, ima, efa, tf)) {
1011 if(uvedit_uv_selected(scene, efa, tf, 0))
1012 tf->uv[0][1]= cent[1];
1013 if(uvedit_uv_selected(scene, efa, tf, 1))
1014 tf->uv[1][1]= cent[1];
1015 if(uvedit_uv_selected(scene, efa, tf, 2))
1016 tf->uv[2][1]= cent[1];
1017 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
1018 tf->uv[3][1]= cent[1];
1023 DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1024 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
1026 BKE_mesh_end_editmesh(obedit->data, em);
1029 static int align_exec(bContext *C, wmOperator *op)
1031 weld_align_uv(C, RNA_enum_get(op->ptr, "axis"));
1033 return OPERATOR_FINISHED;
1036 void UV_OT_align(wmOperatorType *ot)
1038 static EnumPropertyItem axis_items[] = {
1039 {'a', "ALIGN_AUTO", 0, "Align Auto", "Automatically choose the axis on which there is most alignment already."},
1040 {'x', "ALIGN_X", 0, "Align X", "Align UVs on X axis."},
1041 {'y', "ALIGN_Y", 0, "Align Y", "Align UVs on Y axis."},
1042 {0, NULL, 0, NULL, NULL}};
1046 ot->idname= "UV_OT_align";
1047 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1050 ot->exec= align_exec;
1051 ot->poll= ED_operator_uvedit;
1054 RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on.");
1057 /* ******************** weld operator **************** */
1059 static int weld_exec(bContext *C, wmOperator *op)
1061 weld_align_uv(C, 'w');
1063 return OPERATOR_FINISHED;
1066 void UV_OT_weld(wmOperatorType *ot)
1070 ot->idname= "UV_OT_weld";
1071 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1074 ot->exec= weld_exec;
1075 ot->poll= ED_operator_uvedit;
1078 /* ******************** stitch operator **************** */
1080 /* just for averaging UVs */
1081 typedef struct UVVertAverage {
1086 static int stitch_exec(bContext *C, wmOperator *op)
1097 sima= CTX_wm_space_image(C);
1098 scene= CTX_data_scene(C);
1099 obedit= CTX_data_edit_object(C);
1100 em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1101 ima= CTX_data_edit_image(C);
1103 if(RNA_boolean_get(op->ptr, "use_limit")) {
1105 UvMapVert *vlist, *iterv;
1106 float newuv[2], limit[2];
1109 limit[0]= RNA_float_get(op->ptr, "limit");
1112 EM_init_index_arrays(em, 0, 0, 1);
1113 vmap= EM_make_uv_vert_map(em, 1, 0, limit);
1116 BKE_mesh_end_editmesh(obedit->data, em);
1117 return OPERATOR_CANCELLED;
1120 for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) {
1121 vlist= EM_get_uv_map_vert(vmap, a);
1124 newuv[0]= 0; newuv[1]= 0;
1127 for(iterv=vlist; iterv; iterv=iterv->next) {
1128 if((iterv != vlist) && iterv->separate)
1131 efa = EM_get_face_for_index(iterv->f);
1132 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1134 if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
1135 newuv[0] += tf->uv[iterv->tfindex][0];
1136 newuv[1] += tf->uv[iterv->tfindex][1];
1142 newuv[0] /= vtot; newuv[1] /= vtot;
1144 for(iterv=vlist; iterv; iterv=iterv->next) {
1145 if((iterv != vlist) && iterv->separate)
1148 efa = EM_get_face_for_index(iterv->f);
1149 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1151 if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
1152 tf->uv[iterv->tfindex][0]= newuv[0];
1153 tf->uv[iterv->tfindex][1]= newuv[1];
1162 EM_free_uv_vert_map(vmap);
1163 EM_free_index_arrays();
1166 UVVertAverage *uv_average, *uvav;
1169 // index and count verts
1170 for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
1173 uv_average= MEM_callocN(sizeof(UVVertAverage)*count, "Stitch");
1175 // gather uv averages per vert
1176 for(efa= em->faces.first; efa; efa= efa->next) {
1177 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1179 if(uvedit_face_visible(scene, ima, efa, tf)) {
1180 if(uvedit_uv_selected(scene, efa, tf, 0)) {
1181 uvav = uv_average + efa->v1->tmp.l;
1183 uvav->uv[0] += tf->uv[0][0];
1184 uvav->uv[1] += tf->uv[0][1];
1187 if(uvedit_uv_selected(scene, efa, tf, 1)) {
1188 uvav = uv_average + efa->v2->tmp.l;
1190 uvav->uv[0] += tf->uv[1][0];
1191 uvav->uv[1] += tf->uv[1][1];
1194 if(uvedit_uv_selected(scene, efa, tf, 2)) {
1195 uvav = uv_average + efa->v3->tmp.l;
1197 uvav->uv[0] += tf->uv[2][0];
1198 uvav->uv[1] += tf->uv[2][1];
1201 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
1202 uvav = uv_average + efa->v4->tmp.l;
1204 uvav->uv[0] += tf->uv[3][0];
1205 uvav->uv[1] += tf->uv[3][1];
1211 for(efa= em->faces.first; efa; efa= efa->next) {
1212 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1214 if(uvedit_face_visible(scene, ima, efa, tf)) {
1215 if(uvedit_uv_selected(scene, efa, tf, 0)) {
1216 uvav = uv_average + efa->v1->tmp.l;
1217 tf->uv[0][0] = uvav->uv[0]/uvav->count;
1218 tf->uv[0][1] = uvav->uv[1]/uvav->count;
1221 if(uvedit_uv_selected(scene, efa, tf, 1)) {
1222 uvav = uv_average + efa->v2->tmp.l;
1223 tf->uv[1][0] = uvav->uv[0]/uvav->count;
1224 tf->uv[1][1] = uvav->uv[1]/uvav->count;
1227 if(uvedit_uv_selected(scene, efa, tf, 2)) {
1228 uvav = uv_average + efa->v3->tmp.l;
1229 tf->uv[2][0] = uvav->uv[0]/uvav->count;
1230 tf->uv[2][1] = uvav->uv[1]/uvav->count;
1233 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
1234 uvav = uv_average + efa->v4->tmp.l;
1235 tf->uv[3][0] = uvav->uv[0]/uvav->count;
1236 tf->uv[3][1] = uvav->uv[1]/uvav->count;
1241 MEM_freeN(uv_average);
1244 DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1245 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
1247 BKE_mesh_end_editmesh(obedit->data, em);
1248 return OPERATOR_FINISHED;
1251 void UV_OT_stitch(wmOperatorType *ot)
1255 ot->idname= "UV_OT_stitch";
1256 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1259 ot->exec= stitch_exec;
1260 ot->poll= ED_operator_uvedit;
1263 RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs within a specified limit distance.");
1264 RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit distance in normalized coordinates.", -FLT_MAX, FLT_MAX);
1267 /* ******************** (de)select all operator **************** */
1269 static int select_inverse_exec(bContext *C, wmOperator *op)
1279 scene= CTX_data_scene(C);
1280 ts= CTX_data_tool_settings(C);
1281 obedit= CTX_data_edit_object(C);
1282 em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1283 ima= CTX_data_edit_image(C);
1285 if(ts->uv_flag & UV_SYNC_SELECTION) {
1289 for(efa= em->faces.first; efa; efa= efa->next) {
1290 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1292 if(uvedit_face_visible(scene, ima, efa, tf)) {
1293 tf->flag ^= TF_SEL1;
1294 tf->flag ^= TF_SEL2;
1295 tf->flag ^= TF_SEL3;
1296 if(efa->v4) tf->flag ^= TF_SEL4;
1301 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
1303 BKE_mesh_end_editmesh(obedit->data, em);
1304 return OPERATOR_FINISHED;
1307 void UV_OT_select_inverse(wmOperatorType *ot)
1310 ot->name= "Select Inverse";
1311 ot->idname= "UV_OT_select_inverse";
1312 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1315 ot->exec= select_inverse_exec;
1316 ot->poll= ED_operator_uvedit;
1319 /* ******************** (de)select all operator **************** */
1321 static int de_select_all_exec(bContext *C, wmOperator *op)
1332 scene= CTX_data_scene(C);
1333 ts= CTX_data_tool_settings(C);
1334 obedit= CTX_data_edit_object(C);
1335 em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1336 ima= CTX_data_edit_image(C);
1338 if(ts->uv_flag & UV_SYNC_SELECTION) {
1339 EM_toggle_select_all(em);
1344 for(efa= em->faces.first; efa; efa= efa->next) {
1345 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1347 if(uvedit_face_visible(scene, ima, efa, tf)) {
1348 if(tf->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
1355 for(efa= em->faces.first; efa; efa= efa->next) {
1356 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1358 if(uvedit_face_visible(scene, ima, efa, tf)) {
1360 if(sel) tf->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
1361 else tf->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
1364 if(sel) tf->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
1365 else tf->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
1371 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
1373 BKE_mesh_end_editmesh(obedit->data, em);
1374 return OPERATOR_FINISHED;
1377 void UV_OT_select_all_toggle(wmOperatorType *ot)
1380 ot->name= "Select or Deselect All";
1381 ot->idname= "UV_OT_select_all_toggle";
1382 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1385 ot->exec= de_select_all_exec;
1386 ot->poll= ED_operator_uvedit;
1389 /* ******************** mouse select operator **************** */
1391 static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky)
1395 /* this function test if some vertex needs to selected
1396 * in addition to the existing ones due to sticky select */
1397 if(sticky == SI_STICKY_DISABLE)
1400 for(i=0; i<4; i++) {
1402 if(sticky == SI_STICKY_LOC) {
1403 if(fabs(hituv[i][0]-uv[0]) < limit[0] && fabs(hituv[i][1]-uv[1]) < limit[1])
1406 else if(sticky == SI_STICKY_VERTEX)
1414 static int mouse_select(bContext *C, float co[2], int extend, int loop)
1416 SpaceImage *sima= CTX_wm_space_image(C);
1417 Scene *scene= CTX_data_scene(C);
1418 ToolSettings *ts= CTX_data_tool_settings(C);
1419 Object *obedit= CTX_data_edit_object(C);
1420 Image *ima= CTX_data_edit_image(C);
1421 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1425 int a, i, select = 1, selectmode, sticky, sync, hitv[4], nvert;
1426 int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
1427 float limit[2], *hituv[4], penalty[2];
1429 uvedit_pixel_to_float(sima, limit, 0.05f);
1430 uvedit_pixel_to_float(sima, penalty, 5.0f);
1432 /* retrieve operation mode */
1433 if(ts->uv_flag & UV_SYNC_SELECTION) {
1436 if(ts->selectmode & SCE_SELECT_FACE)
1437 selectmode= UV_SELECT_FACE;
1438 else if(ts->selectmode & SCE_SELECT_EDGE)
1439 selectmode= UV_SELECT_EDGE;
1441 selectmode= UV_SELECT_VERTEX;
1443 sticky= SI_STICKY_DISABLE;
1447 selectmode= ts->uv_selectmode;
1448 sticky= (sima)? sima->sticky: 1;
1451 /* find nearest element */
1454 find_nearest_uv_edge(scene, ima, em, co, &hit);
1455 if(hit.efa == NULL) {
1456 BKE_mesh_end_editmesh(obedit->data, em);
1457 return OPERATOR_CANCELLED;
1460 else if(selectmode == UV_SELECT_VERTEX) {
1462 find_nearest_uv_vert(scene, ima, em, co, penalty, &hit);
1463 if(hit.efa == NULL) {
1464 BKE_mesh_end_editmesh(obedit->data, em);
1465 return OPERATOR_CANCELLED;
1468 /* mark 1 vertex as being hit */
1470 hitv[i]= 0xFFFFFFFF;
1472 hitv[hit.uv]= hit.vert;
1473 hituv[hit.uv]= hit.tf->uv[hit.uv];
1475 else if(selectmode == UV_SELECT_EDGE) {
1477 find_nearest_uv_edge(scene, ima, em, co, &hit);
1478 if(hit.efa == NULL) {
1479 BKE_mesh_end_editmesh(obedit->data, em);
1480 return OPERATOR_CANCELLED;
1483 /* mark 2 edge vertices as being hit */
1485 hitv[i]= 0xFFFFFFFF;
1487 nvert= (hit.efa->v4)? 4: 3;
1489 hitv[hit.edge]= hit.vert;
1490 hitv[(hit.edge+1)%nvert]= hit.vert2;
1491 hituv[hit.edge]= hit.tf->uv[hit.edge];
1492 hituv[(hit.edge+1)%nvert]= hit.tf->uv[(hit.edge+1)%nvert];
1494 else if(selectmode == UV_SELECT_FACE) {
1496 find_nearest_uv_face(scene, ima, em, co, &hit);
1497 if(hit.efa == NULL) {
1498 BKE_mesh_end_editmesh(obedit->data, em);
1499 return OPERATOR_CANCELLED;
1503 EM_set_actFace(em, hit.efa);
1505 /* mark all face vertices as being hit */
1507 hituv[i]= hit.tf->uv[i];
1509 hitv[0]= hit.efa->v1->tmp.l;
1510 hitv[1]= hit.efa->v2->tmp.l;
1511 hitv[2]= hit.efa->v3->tmp.l;
1513 if(hit.efa->v4) hitv[3]= hit.efa->v4->tmp.l;
1514 else hitv[3]= 0xFFFFFFFF;
1516 else if(selectmode == UV_SELECT_ISLAND) {
1517 find_nearest_uv_vert(scene, ima, em, co, NULL, &hit);
1520 BKE_mesh_end_editmesh(obedit->data, em);
1521 return OPERATOR_CANCELLED;
1525 BKE_mesh_end_editmesh(obedit->data, em);
1526 return OPERATOR_CANCELLED;
1531 flush= select_edgeloop(scene, ima, em, &hit, limit, extend);
1533 else if(selectmode == UV_SELECT_ISLAND) {
1534 select_linked(scene, ima, em, limit, &hit, extend);
1537 if(selectmode == UV_SELECT_VERTEX) {
1538 /* (de)select uv vertex */
1539 if(uvedit_uv_selected(scene, hit.efa, hit.tf, hit.uv)) {
1540 uvedit_uv_deselect(scene, hit.efa, hit.tf, hit.uv);
1544 uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
1549 else if(selectmode == UV_SELECT_EDGE) {
1550 /* (de)select edge */
1551 if(uvedit_edge_selected(scene, hit.efa, hit.tf, hit.edge)) {
1552 uvedit_edge_deselect(scene, hit.efa, hit.tf, hit.edge);
1556 uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
1561 else if(selectmode == UV_SELECT_FACE) {
1562 /* (de)select face */
1563 if(uvedit_face_selected(scene, hit.efa, hit.tf)) {
1564 uvedit_face_deselect(scene, hit.efa, hit.tf);
1568 uvedit_face_select(scene, hit.efa, hit.tf);
1574 /* (de)select sticky uv nodes */
1575 if(sticky != SI_STICKY_DISABLE) {
1578 for(a=0, ev=em->verts.first; ev; ev = ev->next, a++)
1583 for(efa= em->faces.first; efa; efa= efa->next) {
1584 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1586 if(uvedit_face_visible(scene, ima, efa, tf)) {
1587 if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
1588 uvedit_uv_deselect(scene, efa, tf, 0);
1589 if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
1590 uvedit_uv_deselect(scene, efa, tf, 1);
1591 if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
1592 uvedit_uv_deselect(scene, efa, tf, 2);
1594 if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
1595 uvedit_uv_deselect(scene, efa, tf, 3);
1602 for(efa= em->faces.first; efa; efa= efa->next) {
1603 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1605 if(uvedit_face_visible(scene, ima, efa, tf)) {
1606 if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
1607 uvedit_uv_select(scene, efa, tf, 0);
1608 if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
1609 uvedit_uv_select(scene, efa, tf, 1);
1610 if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
1611 uvedit_uv_select(scene, efa, tf, 2);
1613 if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
1614 uvedit_uv_select(scene, efa, tf, 3);
1624 for(efa= em->faces.first; efa; efa= efa->next) {
1625 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1626 uvedit_face_deselect(scene, efa, tf);
1629 if(selectmode == UV_SELECT_VERTEX) {
1631 uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
1634 else if(selectmode == UV_SELECT_EDGE) {
1636 uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
1639 else if(selectmode == UV_SELECT_FACE) {
1641 uvedit_face_select(scene, hit.efa, hit.tf);
1644 /* select sticky uvs */
1645 if(sticky != SI_STICKY_DISABLE) {
1646 for(efa= em->faces.first; efa; efa= efa->next) {
1647 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1648 if(uvedit_face_visible(scene, ima, efa, tf)) {
1649 if(sticky == SI_STICKY_DISABLE) continue;
1651 if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
1652 uvedit_uv_select(scene, efa, tf, 0);
1653 if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
1654 uvedit_uv_select(scene, efa, tf, 1);
1655 if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
1656 uvedit_uv_select(scene, efa, tf, 2);
1658 if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
1659 uvedit_uv_select(scene, efa, tf, 3);
1668 /* flush for mesh selection */
1669 if(ts->selectmode != SCE_SELECT_FACE) {
1670 if(flush==1) EM_select_flush(em);
1671 else if(flush==-1) EM_deselect_flush(em);
1675 DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1676 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
1678 BKE_mesh_end_editmesh(obedit->data, em);
1679 return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
1682 static int select_exec(bContext *C, wmOperator *op)
1687 RNA_float_get_array(op->ptr, "location", co);
1688 extend= RNA_boolean_get(op->ptr, "extend");
1691 return mouse_select(C, co, extend, loop);
1694 static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
1696 ARegion *ar= CTX_wm_region(C);
1700 x= event->x - ar->winrct.xmin;
1701 y= event->y - ar->winrct.ymin;
1703 UI_view2d_region_to_view(&ar->v2d, x, y, &co[0], &co[1]);
1704 RNA_float_set_array(op->ptr, "location", co);
1706 return select_exec(C, op);
1709 void UV_OT_select(wmOperatorType *ot)
1713 ot->idname= "UV_OT_select";
1714 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1717 ot->exec= select_exec;
1718 ot->invoke= select_invoke;
1719 ot->poll= ED_operator_uvedit;
1722 RNA_def_boolean(ot->srna, "extend", 0,
1723 "Extend", "Extend selection rather than clearing the existing selection.");
1724 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
1725 "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f);
1728 /* ******************** loop select operator **************** */
1730 static int select_loop_exec(bContext *C, wmOperator *op)
1735 RNA_float_get_array(op->ptr, "location", co);
1736 extend= RNA_boolean_get(op->ptr, "extend");
1739 return mouse_select(C, co, extend, loop);
1742 static int select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
1744 ARegion *ar= CTX_wm_region(C);
1748 x= event->x - ar->winrct.xmin;
1749 y= event->y - ar->winrct.ymin;
1751 UI_view2d_region_to_view(&ar->v2d, x, y, &co[0], &co[1]);
1752 RNA_float_set_array(op->ptr, "location", co);
1754 return select_loop_exec(C, op);
1757 void UV_OT_select_loop(wmOperatorType *ot)
1760 ot->name= "Loop Select";
1761 ot->idname= "UV_OT_select_loop";
1762 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1765 ot->exec= select_loop_exec;
1766 ot->invoke= select_loop_invoke;
1767 ot->poll= ED_operator_uvedit;
1770 RNA_def_boolean(ot->srna, "extend", 0,
1771 "Extend", "Extend selection rather than clearing the existing selection.");
1772 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
1773 "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f);
1776 /* ******************** linked select operator **************** */
1778 static int select_linked_exec(bContext *C, wmOperator *op)
1780 SpaceImage *sima= CTX_wm_space_image(C);
1781 Scene *scene= CTX_data_scene(C);
1782 ToolSettings *ts= CTX_data_tool_settings(C);
1783 Object *obedit= CTX_data_edit_object(C);
1784 Image *ima= CTX_data_edit_image(C);
1785 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1789 if(ts->uv_flag & UV_SYNC_SELECTION) {
1790 BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled.");
1791 BKE_mesh_end_editmesh(obedit->data, em);
1792 return OPERATOR_CANCELLED;
1795 extend= RNA_boolean_get(op->ptr, "extend");
1796 uvedit_pixel_to_float(sima, limit, 0.05f);
1797 select_linked(scene, ima, em, limit, NULL, extend);
1799 DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1800 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
1802 BKE_mesh_end_editmesh(obedit->data, em);
1803 return OPERATOR_FINISHED;
1806 void UV_OT_select_linked(wmOperatorType *ot)
1809 ot->name= "Select Linked";
1810 ot->idname= "UV_OT_select_linked";
1811 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1814 ot->exec= select_linked_exec;
1815 ot->poll= ED_operator_uvedit;
1818 RNA_def_boolean(ot->srna, "extend", 0,
1819 "Extend", "Extend selection rather than clearing the existing selection.");
1822 /* ******************** unlink selection operator **************** */
1824 static int unlink_selection_exec(bContext *C, wmOperator *op)
1826 Scene *scene= CTX_data_scene(C);
1827 ToolSettings *ts= CTX_data_tool_settings(C);
1828 Object *obedit= CTX_data_edit_object(C);
1829 Image *ima= CTX_data_edit_image(C);
1830 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1834 if(ts->uv_flag & UV_SYNC_SELECTION) {
1835 BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled.");
1836 BKE_mesh_end_editmesh(obedit->data, em);
1837 return OPERATOR_CANCELLED;
1840 for(efa= em->faces.first; efa; efa= efa->next) {
1841 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1843 if(uvedit_face_visible(scene, ima, efa, tf)) {
1845 if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))
1846 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1849 if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1850 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3);
1855 DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1856 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
1858 BKE_mesh_end_editmesh(obedit->data, em);
1859 return OPERATOR_FINISHED;
1862 void UV_OT_unlink_selection(wmOperatorType *ot)
1865 ot->name= "Unlink Selection";
1866 ot->idname= "UV_OT_unlink_selection";
1867 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1870 ot->exec= unlink_selection_exec;
1871 ot->poll= ED_operator_uvedit;
1874 /* ******************** border select operator **************** */
1876 /* This function sets the selection on tagged faces, need because settings the
1877 * selection a face is done in a number of places but it also needs to respect
1878 * the sticky modes for the UV verts, so dealing with the sticky modes is best
1879 * done in a seperate function.
1881 * De-selects faces that have been tagged on efa->tmp.l. */
1883 static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, short select)
1885 /* Selecting UV Faces with some modes requires us to change
1886 * the selection in other faces (depending on the sticky mode).
1888 * This only needs to be done when the Mesh is not used for
1889 * selection (so for sticky modes, vertex or location based). */
1891 ToolSettings *ts= CTX_data_tool_settings(C);
1892 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1897 if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
1898 /* Tag all verts as untouched, then touch the ones that have a face center
1899 * in the loop and select all MTFace UV's that use a touched vert. */
1902 for(eve= em->verts.first; eve; eve= eve->next)
1905 for(efa= em->faces.first; efa; efa= efa->next) {
1908 efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1;
1910 efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1;
1914 /* now select tagged verts */
1915 for(efa= em->faces.first; efa; efa= efa->next) {
1916 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1917 nverts= efa->v4? 4: 3;
1918 for(i=0; i<nverts; i++) {
1919 if((*(&efa->v1 + i))->tmp.l) {
1921 uvedit_uv_select(scene, efa, tf, i);
1923 uvedit_uv_deselect(scene, efa, tf, i);
1928 else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
1929 EditFace *efa_vlist;
1931 UvMapVert *start_vlist=NULL, *vlist_iter;
1932 struct UvVertMap *vmap;
1935 //EditVert *eve; /* removed vert counting for now */
1938 uvedit_pixel_to_float(sima, limit, 0.05);
1940 EM_init_index_arrays(em, 0, 0, 1);
1941 vmap= EM_make_uv_vert_map(em, 0, 0, limit);
1943 /* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */
1944 /*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next)
1948 BKE_mesh_end_editmesh(obedit->data, em);
1952 for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) {
1954 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1955 nverts= efa->v4? 4: 3;
1957 for(i=0; i<nverts; i++) {
1959 uvedit_uv_select(scene, efa, tf, i);
1961 uvedit_uv_deselect(scene, efa, tf, i);
1963 vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
1965 while (vlist_iter) {
1966 if(vlist_iter->separate)
1967 start_vlist = vlist_iter;
1969 if(efa_index == vlist_iter->f)
1972 vlist_iter = vlist_iter->next;
1975 vlist_iter = start_vlist;
1976 while (vlist_iter) {
1978 if(vlist_iter != start_vlist && vlist_iter->separate)
1981 if(efa_index != vlist_iter->f) {
1982 efa_vlist = EM_get_face_for_index(vlist_iter->f);
1983 tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE);
1986 uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
1988 uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
1990 vlist_iter = vlist_iter->next;
1995 EM_free_index_arrays();
1996 EM_free_uv_vert_map(vmap);
1999 else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
2000 for(efa= em->faces.first; efa; efa= efa->next) {
2002 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2004 uvedit_face_select(scene, efa, tf);
2006 uvedit_face_deselect(scene, efa, tf);
2010 BKE_mesh_end_editmesh(obedit->data, em);
2013 static int border_select_exec(bContext *C, wmOperator *op)
2015 SpaceImage *sima= CTX_wm_space_image(C);
2016 Scene *scene= CTX_data_scene(C);
2017 ToolSettings *ts= CTX_data_tool_settings(C);
2018 Object *obedit= CTX_data_edit_object(C);
2019 Image *ima= CTX_data_edit_image(C);
2020 ARegion *ar= CTX_wm_region(C);
2021 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2026 int change, pinned, select, faces;
2028 /* get rectangle from operator */
2029 rect.xmin= RNA_int_get(op->ptr, "xmin");
2030 rect.ymin= RNA_int_get(op->ptr, "ymin");
2031 rect.xmax= RNA_int_get(op->ptr, "xmax");
2032 rect.ymax= RNA_int_get(op->ptr, "ymax");
2034 UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
2035 UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
2037 /* figure out what to select/deselect */
2038 select= (RNA_int_get(op->ptr, "event_type") == LEFTMOUSE); // XXX hardcoded
2039 pinned= RNA_boolean_get(op->ptr, "pinned");
2041 if(ts->uv_flag & UV_SYNC_SELECTION)
2042 faces= (ts->selectmode == SCE_SELECT_FACE);
2044 faces= (ts->uv_selectmode == UV_SELECT_FACE);
2046 /* do actual selection */
2047 if(faces && !pinned) {
2048 /* handle face selection mode */
2053 for(efa= em->faces.first; efa; efa= efa->next) {
2054 /* assume not touched */
2056 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2057 if(uvedit_face_visible(scene, ima, efa, tface)) {
2058 uv_center(tface->uv, cent, efa->v4 != NULL);
2059 if(BLI_in_rctf(&rectf, cent[0], cent[1])) {
2060 efa->tmp.l = change = 1;
2065 /* (de)selects all tagged faces and deals with sticky modes */
2067 uv_faces_do_sticky(C, sima, scene, obedit, select);
2070 /* other selection modes */
2073 for(efa= em->faces.first; efa; efa= efa->next) {
2074 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2075 if(uvedit_face_visible(scene, ima, efa, tface)) {
2076 if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) {
2077 /* UV_SYNC_SELECTION - can't do pinned selection */
2078 if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
2079 if(select) uvedit_uv_select(scene, efa, tface, 0);
2080 else uvedit_uv_deselect(scene, efa, tface, 0);
2082 if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
2083 if(select) uvedit_uv_select(scene, efa, tface, 1);
2084 else uvedit_uv_deselect(scene, efa, tface, 1);
2086 if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
2087 if(select) uvedit_uv_select(scene, efa, tface, 2);
2088 else uvedit_uv_deselect(scene, efa, tface, 2);
2090 if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
2091 if(select) uvedit_uv_select(scene, efa, tface, 3);
2092 else uvedit_uv_deselect(scene, efa, tface, 3);
2096 if((tface->unwrap & TF_PIN1) &&
2097 BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
2099 if(select) uvedit_uv_select(scene, efa, tface, 0);
2100 else uvedit_uv_deselect(scene, efa, tface, 0);
2102 if((tface->unwrap & TF_PIN2) &&
2103 BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
2105 if(select) uvedit_uv_select(scene, efa, tface, 1);
2106 else uvedit_uv_deselect(scene, efa, tface, 1);
2108 if((tface->unwrap & TF_PIN3) &&
2109 BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
2111 if(select) uvedit_uv_select(scene, efa, tface, 2);
2112 else uvedit_uv_deselect(scene, efa, tface, 2);
2114 if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
2115 if(select) uvedit_uv_select(scene, efa, tface, 3);
2116 else uvedit_uv_deselect(scene, efa, tface, 3);
2124 /* make sure newly selected vert selection is updated*/
2125 if(ts->uv_flag & UV_SYNC_SELECTION) {
2126 if(ts->selectmode != SCE_SELECT_FACE) {
2127 if(select) EM_select_flush(em);
2128 else EM_deselect_flush(em);
2132 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2134 BKE_mesh_end_editmesh(obedit->data, em);
2135 return OPERATOR_FINISHED;
2138 BKE_mesh_end_editmesh(obedit->data, em);
2139 return OPERATOR_CANCELLED;
2142 void UV_OT_select_border(wmOperatorType *ot)
2145 ot->name= "Border Select";
2146 ot->idname= "UV_OT_select_border";
2149 ot->invoke= WM_border_select_invoke;
2150 ot->exec= border_select_exec;
2151 ot->modal= WM_border_select_modal;
2152 ot->poll= ED_operator_uvedit;
2155 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2158 RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only.");
2160 RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
2161 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
2162 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
2163 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
2164 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
2167 /* ******************** circle select operator **************** */
2169 static void select_uv_inside_ellipse(SpaceImage *sima, Scene *scene, int select, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, int select_index)
2171 /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
2172 float x, y, r2, *uv;
2174 uv= tface->uv[index];
2176 x= (uv[0] - offset[0])*ell[0];
2177 y= (uv[1] - offset[1])*ell[1];
2181 if(select) uvedit_uv_select(scene, efa, tface, select_index);
2182 else uvedit_uv_deselect(scene, efa, tface, select_index);
2186 int circle_select_exec(bContext *C, wmOperator *op)
2188 SpaceImage *sima= CTX_wm_space_image(C);
2189 Scene *scene= CTX_data_scene(C);
2190 Object *obedit= CTX_data_edit_object(C);
2191 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2192 ARegion *ar= CTX_wm_region(C);
2195 int x, y, radius, width, height, select;
2196 float zoomx, zoomy, offset[2], ellipse[2];
2198 /* get operator properties */
2199 select= (RNA_int_get(op->ptr, "event_type") == LEFTMOUSE); // XXX hardcoded
2200 x= RNA_int_get(op->ptr, "x");
2201 y= RNA_int_get(op->ptr, "y");
2202 radius= RNA_int_get(op->ptr, "radius");
2204 /* compute ellipse size and location, not a circle since we deal
2205 * with non square image. ellipse is normalized, r = 1.0. */
2206 ED_space_image_size(sima, &width, &height);
2207 ED_space_image_zoom(sima, ar, &zoomx, &zoomy);
2209 ellipse[0]= width*zoomx/radius;
2210 ellipse[1]= height*zoomy/radius;
2212 UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
2215 for(efa= em->faces.first; efa; efa= efa->next) {
2216 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2217 select_uv_inside_ellipse(sima, scene, select, efa, tface, 0, offset, ellipse, 0);
2218 select_uv_inside_ellipse(sima, scene, select, efa, tface, 1, offset, ellipse, 1);
2219 select_uv_inside_ellipse(sima, scene, select, efa, tface, 2, offset, ellipse, 2);
2221 select_uv_inside_ellipse(sima, scene, select, efa, tface, 3, offset, ellipse, 3);
2224 if(select) EM_select_flush(em);
2225 else EM_deselect_flush(em);
2227 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2229 BKE_mesh_end_editmesh(obedit->data, em);
2230 return OPERATOR_FINISHED;
2233 void UV_OT_circle_select(wmOperatorType *ot)
2236 ot->name= "Circle Select";
2237 ot->idname= "UV_OT_circle_select";
2240 ot->invoke= WM_gesture_circle_invoke;
2241 ot->modal= WM_gesture_circle_modal;
2242 ot->exec= circle_select_exec;
2243 ot->poll= ED_operator_uvedit;
2246 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2249 RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
2250 RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
2251 RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX);
2252 RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
2255 /* ******************** snap cursor operator **************** */
2257 static void snap_uv_to_pixel(float *uvco, float w, float h)
2259 uvco[0] = ((float)((int)((uvco[0]*w) + 0.5f)))/w;
2260 uvco[1] = ((float)((int)((uvco[1]*h) + 0.5f)))/h;
2263 static void snap_cursor_to_pixels(SpaceImage *sima, View2D *v2d)
2265 int width= 0, height= 0;
2267 ED_space_image_size(sima, &width, &height);
2268 snap_uv_to_pixel(v2d->cursor, width, height);
2271 static int snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, View2D *v2d)
2273 return uvedit_center(scene, ima, obedit, v2d->cursor, 0);
2276 static int snap_cursor_exec(bContext *C, wmOperator *op)
2278 SpaceImage *sima= CTX_wm_space_image(C);
2279 Scene *scene= CTX_data_scene(C);
2280 Object *obedit= CTX_data_edit_object(C);
2281 Image *ima= CTX_data_edit_image(C);
2282 ARegion *ar= CTX_wm_region(C);
2285 switch(RNA_boolean_get(op->ptr, "target")) {
2287 snap_cursor_to_pixels(sima, &ar->v2d);
2291 change= snap_cursor_to_selection(scene, ima, obedit, &ar->v2d);
2296 return OPERATOR_CANCELLED;
2298 ED_region_tag_redraw(ar);
2300 return OPERATOR_FINISHED;
2303 void UV_OT_snap_cursor(wmOperatorType *ot)
2305 static EnumPropertyItem target_items[] = {
2306 {0, "PIXELS", 0, "Pixels", ""},
2307 {1, "SELECTION", 0, "Selection", ""},
2308 {0, NULL, 0, NULL, NULL}};
2311 ot->name= "Snap Cursor";
2312 ot->idname= "UV_OT_snap_cursor";
2313 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2316 ot->exec= snap_cursor_exec;
2317 ot->poll= ED_operator_uvedit;
2320 RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to.");
2323 /* ******************** snap selection operator **************** */
2325 static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, View2D *v2d)
2327 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2332 for(efa= em->faces.first; efa; efa= efa->next) {
2333 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2334 if(uvedit_face_visible(scene, ima, efa, tface)) {
2335 if(uvedit_uv_selected(scene, efa, tface, 0)) VECCOPY2D(tface->uv[0], v2d->cursor);
2336 if(uvedit_uv_selected(scene, efa, tface, 1)) VECCOPY2D(tface->uv[1], v2d->cursor);
2337 if(uvedit_uv_selected(scene, efa, tface, 2)) VECCOPY2D(tface->uv[2], v2d->cursor);
2339 if(uvedit_uv_selected(scene, efa, tface, 3)) VECCOPY2D(tface->uv[3], v2d->cursor);
2345 BKE_mesh_end_editmesh(obedit->data, em);
2349 static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
2351 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2358 short *usercount, users;
2360 /* set all verts to -1 : an unused index*/
2361 for(eve= em->verts.first; eve; eve= eve->next)
2364 /* index every vert that has a selected UV using it, but only once so as to
2365 * get unique indicies and to count how much to malloc */
2366 for(efa= em->faces.first; efa; efa= efa->next) {
2367 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2369 if(uvedit_face_visible(scene, ima, efa, tface)) {
2370 if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->tmp.l==-1) efa->v1->tmp.l= count++;
2371 if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->tmp.l==-1) efa->v2->tmp.l= count++;
2372 if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->tmp.l==-1) efa->v3->tmp.l= count++;
2374 if(uvedit_uv_selected(scene, efa, tface, 3) && efa->v4->tmp.l==-1) efa->v4->tmp.l= count++;
2378 /* optional speedup */
2385 coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords");
2386 usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts");
2388 /* add all UV coords from visible, unselected UV coords as well as counting them to average later */
2389 for(efa= em->faces.first; efa; efa= efa->next) {
2390 if((tface=(MTFace *)efa->tmp.p)) {
2391 /* is this an unselected UV we can snap to? */
2392 if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 0))) {
2393 coords[efa->v1->tmp.l*2] += tface->uv[0][0];
2394 coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1];
2395 usercount[efa->v1->tmp.l]++;
2398 if(efa->v2->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 1))) {
2399 coords[efa->v2->tmp.l*2] += tface->uv[1][0];
2400 coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1];
2401 usercount[efa->v2->tmp.l]++;
2404 if(efa->v3->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 2))) {
2405 coords[efa->v3->tmp.l*2] += tface->uv[2][0];
2406 coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1];
2407 usercount[efa->v3->tmp.l]++;
2412 if(efa->v4->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 3))) {
2413 coords[efa->v4->tmp.l*2] += tface->uv[3][0];
2414 coords[(efa->v4->tmp.l*2)+1] += tface->uv[3][1];
2415 usercount[efa->v4->tmp.l]++;
2422 /* no other verts selected, bail out */
2425 MEM_freeN(usercount);
2426 BKE_mesh_end_editmesh(obedit->data, em);
2430 /* copy the averaged unselected UVs back to the selected UVs */
2431 for(efa= em->faces.first; efa; efa= efa->next) {
2432 if((tface=(MTFace *)efa->tmp.p)) {
2434 if( uvedit_uv_selected(scene, efa, tface, 0) &&
2435 efa->v1->tmp.l >= 0 &&
2436 (users = usercount[efa->v1->tmp.l])
2438 tface->uv[0][0] = coords[efa->v1->tmp.l*2] / users;
2439 tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1] / users;
2442 if( uvedit_uv_selected(scene, efa, tface, 1) &&
2443 efa->v2->tmp.l >= 0 &&
2444 (users = usercount[efa->v2->tmp.l])
2446 tface->uv[1][0] = coords[efa->v2->tmp.l*2] / users;
2447 tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1] / users;
2450 if( uvedit_uv_selected(scene, efa, tface, 2) &&
2451 efa->v3->tmp.l >= 0 &&
2452 (users = usercount[efa->v3->tmp.l])
2454 tface->uv[2][0] = coords[efa->v3->tmp.l*2] / users;
2455 tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1] / users;
2459 if( uvedit_uv_selected(scene, efa, tface, 3) &&
2460 efa->v4->tmp.l >= 0 &&
2461 (users = usercount[efa->v4->tmp.l])
2463 tface->uv[3][0] = coords[efa->v4->tmp.l*2] / users;
2464 tface->uv[3][1] = coords[(efa->v4->tmp.l*2)+1] / users;
2471 MEM_freeN(usercount);
2473 BKE_mesh_end_editmesh(obedit->data, em);
2477 static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
2479 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2483 int width= 0, height= 0;
2492 ED_space_image_size(sima, &width, &height);
2496 for(efa= em->faces.first; efa; efa= efa->next) {
2497 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2498 if(uvedit_face_visible(scene, ima, efa, tface)) {
2499 if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_pixel(tface->uv[0], w, h);
2500 if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_pixel(tface->uv[1], w, h);
2501 if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_pixel(tface->uv[2], w, h);
2503 if(uvedit_uv_selected(scene, efa, tface, 3)) snap_uv_to_pixel(tface->uv[3], w, h);
2509 BKE_mesh_end_editmesh(obedit->data, em);
2513 static int snap_selection_exec(bContext *C, wmOperator *op)
2515 SpaceImage *sima= CTX_wm_space_image(C);
2516 Scene *scene= CTX_data_scene(C);
2517 Object *obedit= CTX_data_edit_object(C);
2518 Image *ima= CTX_data_edit_image(C);
2519 ARegion *ar= CTX_wm_region(C);
2522 switch(RNA_boolean_get(op->ptr, "target")) {
2524 change= snap_uvs_to_pixels(sima, scene, obedit);
2527 change= snap_uvs_to_cursor(scene, ima, obedit, &ar->v2d);
2530 change= snap_uvs_to_adjacent_unselected(scene, ima, obedit);
2535 return OPERATOR_CANCELLED;
2537 DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
2538 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
2540 return OPERATOR_FINISHED;
2543 void UV_OT_snap_selection(wmOperatorType *ot)
2545 static EnumPropertyItem target_items[] = {
2546 {0, "PIXELS", 0, "Pixels", ""},
2547 {1, "CURSOR", 0, "Cursor", ""},
2548 {2, "ADJACENT_UNSELECTED", 0, "Adjacent Unselected", ""},
2549 {0, NULL, 0, NULL, NULL}};
2552 ot->name= "Snap Selection";
2553 ot->idname= "UV_OT_snap_selection";
2554 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2557 ot->exec= snap_selection_exec;
2558 ot->poll= ED_operator_uvedit;
2561 RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to.");
2564 /* ******************** pin operator **************** */
2566 static int pin_exec(bContext *C, wmOperator *op)
2568 Scene *scene= CTX_data_scene(C);
2569 Object *obedit= CTX_data_edit_object(C);
2570 Image *ima= CTX_data_edit_image(C);
2571 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2574 int clear= RNA_boolean_get(op->ptr, "clear");
2576 for(efa= em->faces.first; efa; efa= efa->next) {
2577 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2579 if(uvedit_face_visible(scene, ima, efa, tface)) {
2581 if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap |= TF_PIN1;
2582 if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap |= TF_PIN2;
2583 if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap |= TF_PIN3;
2585 if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap |= TF_PIN4;
2588 if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap &= ~TF_PIN1;
2589 if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap &= ~TF_PIN2;
2590 if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap &= ~TF_PIN3;
2592 if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap &= ~TF_PIN4;
2597 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
2599 BKE_mesh_end_editmesh(obedit->data, em);
2600 return OPERATOR_FINISHED;
2603 void UV_OT_pin(wmOperatorType *ot)
2607 ot->idname= "UV_OT_pin";
2608 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2612 ot->poll= ED_operator_uvedit;
2615 RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear pinning for the selection instead of setting it.");
2618 /******************* select pinned operator ***************/
2620 static int select_pinned_exec(bContext *C, wmOperator *op)
2622 Scene *scene= CTX_data_scene(C);
2623 Object *obedit= CTX_data_edit_object(C);
2624 Image *ima= CTX_data_edit_image(C);
2625 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2629 for(efa= em->faces.first; efa; efa= efa->next) {
2630 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2632 if(uvedit_face_visible(scene, ima, efa, tface)) {
2633 if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa, tface, 0);
2634 if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa, tface, 1);
2635 if(tface->unwrap & TF_PIN3) uvedit_uv_select(scene, efa, tface, 2);
2637 if(tface->unwrap & TF_PIN4) uvedit_uv_select(scene, efa, tface, 3);
2642 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2644 BKE_mesh_end_editmesh(obedit->data, em);
2645 return OPERATOR_FINISHED;
2648 void UV_OT_select_pinned(wmOperatorType *ot)
2651 ot->name= "Selected Pinned";
2652 ot->idname= "UV_OT_select_pinned";
2653 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2656 ot->exec= select_pinned_exec;
2657 ot->poll= ED_operator_uvedit;
2660 /********************** hide operator *********************/
2662 static int hide_exec(bContext *C, wmOperator *op)
2664 SpaceImage *sima= CTX_wm_space_image(C);
2665 ToolSettings *ts= CTX_data_tool_settings(C);
2666 Object *obedit= CTX_data_edit_object(C);
2667 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2670 int swap= RNA_boolean_get(op->ptr, "unselected");
2671 int facemode= sima ? sima->flag & SI_SELACTFACE : 0;
2673 if(ts->uv_flag & UV_SYNC_SELECTION) {
2674 EM_hide_mesh(em, swap);
2675 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2677 BKE_mesh_end_editmesh(obedit->data, em);
2678 return OPERATOR_FINISHED;
2682 for(efa= em->faces.first; efa; efa= efa->next) {
2683 if(efa->f & SELECT) {
2684 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2686 /* Pretend face mode */
2687 if(( (efa->v4==NULL &&
2688 ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) ||
2689 ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) == 0) {
2691 if(em->selectmode == SCE_SELECT_FACE) {
2693 /* must re-select after */
2694 efa->e1->f &= ~SELECT;
2695 efa->e2->f &= ~SELECT;
2696 efa->e3->f &= ~SELECT;
2697 if(efa->e4) efa->e4->f &= ~SELECT;
2700 EM_select_face(efa, 0);
2702 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2704 else if(em->selectmode == SCE_SELECT_FACE) {
2705 if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) {
2707 EM_select_face(efa, 0);
2708 else if(!(tf->flag & TF_SEL4))
2709 EM_select_face(efa, 0);
2710 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2714 /* EM_deselect_flush will deselect the face */
2715 if((tf->flag & TF_SEL1)==0) efa->v1->f &= ~SELECT;
2716 if((tf->flag & TF_SEL2)==0) efa->v2->f &= ~SELECT;
2717 if((tf->flag & TF_SEL3)==0) efa->v3->f &= ~SELECT;
2718 if((efa->v4) && (tf->flag & TF_SEL4)==0) efa->v4->f &= ~SELECT;
2720 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2726 for(efa= em->faces.first; efa; efa= efa->next) {
2727 if(efa->f & SELECT) {
2728 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2731 if( (efa->v4==NULL &&
2732 ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) ||
2733 ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) {
2735 if(em->selectmode == SCE_SELECT_FACE) {
2737 /* must re-select after */
2738 efa->e1->f &= ~SELECT;
2739 efa->e2->f &= ~SELECT;
2740 efa->e3->f &= ~SELECT;
2741 if(efa->e4) efa->e4->f &= ~SELECT;
2744 EM_select_face(efa, 0);
2747 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2749 else if(em->selectmode == SCE_SELECT_FACE) {
2750 if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
2751 EM_select_face(efa, 0);
2752 else if(efa->v4 && tf->flag & TF_SEL4)
2753 EM_select_face(efa, 0);
2755 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2758 /* EM_deselect_flush will deselect the face */
2759 if(tf->flag & TF_SEL1) efa->v1->f &= ~SELECT;
2760 if(tf->flag & TF_SEL2) efa->v2->f &= ~SELECT;
2761 if(tf->flag & TF_SEL3) efa->v3->f &= ~SELECT;
2762 if((efa->v4) && tf->flag & TF_SEL4) efa->v4->f &= ~SELECT;
2764 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2770 /*deselects too many but ok for now*/
2771 if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX))
2772 EM_deselect_flush(em);
2774 if(em->selectmode==SCE_SELECT_FACE) {
2775 /* de-selected all edges from faces that were de-selected.
2776 * now make sure all faces that are selected also have selected edges */
2777 for(efa= em->faces.first; efa; efa= efa->next)
2779 EM_select_face(efa, 1);
2782 EM_validate_selections(em);
2783 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2785 BKE_mesh_end_editmesh(obedit->data, em);
2786 return OPERATOR_FINISHED;
2789 void UV_OT_hide(wmOperatorType *ot)
2792 ot->name= "Hide Selected";
2793 ot->idname= "UV_OT_hide";
2794 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2797 ot->exec= hide_exec;
2798 ot->poll= ED_operator_uvedit;
2801 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
2804 /****************** reveal operator ******************/
2806 static int reveal_exec(bContext *C, wmOperator *op)
2808 SpaceImage *sima= CTX_wm_space_image(C);
2809 ToolSettings *ts= CTX_data_tool_settings(C);
2810 Object *obedit= CTX_data_edit_object(C);
2811 EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2814 int facemode= sima ? sima->flag & SI_SELACTFACE : 0;
2815 int stickymode= sima ? (sima->sticky != SI_STICKY_DISABLE) : 1;
2817 /* call the mesh function if we are in mesh sync sel */
2818 if(ts->uv_flag & UV_SYNC_SELECTION) {
2820 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2822 BKE_mesh_end_editmesh(obedit->data, em);
2823 return OPERATOR_FINISHED;
2827 if(em->selectmode == SCE_SELECT_FACE) {
2828 for(efa= em->faces.first; efa; efa= efa->next) {
2829 if(!(efa->h) && !(efa->f & SELECT)) {
2830 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2831 EM_select_face(efa, 1);
2832 tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2837 /* enable adjacent faces to have disconnected UV selections if sticky is disabled */
2839 for(efa= em->faces.first; efa; efa= efa->next) {
2840 if(!(efa->h) && !(efa->f & SELECT)) {
2841 /* All verts must be unselected for the face to be selected in the UV view */
2842 if((efa->v1->f&SELECT)==0 && (efa->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==0 || (efa->v4->f&SELECT)==0)) {
2843 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2845 tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2846 /* Cant use EM_select_face here because it unselects the verts
2847 * and we cant tell if the face was totally unselected or not */
2848 /*EM_select_face(efa, 1);
2850 * See Loop with EM_select_face() below... */
2857 for(efa= em->faces.first; efa; efa= efa->next) {
2858 if(!(efa->h) && !(efa->f & SELECT)) {
2859 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2861 if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;}
2862 if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;}
2863 if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;}
2864 if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;}
2871 /* Select all edges and verts now */
2872 for(efa= em->faces.first; efa; efa= efa->next)
2873 /* we only selected the face flags, and didnt changes edges or verts, fix this now */
2874 if(!(efa->h) && (efa->f & SELECT))
2875 EM_select_face(efa, 1);
2877 EM_select_flush(em);
2880 else if(em->selectmode == SCE_SELECT_FACE) {
2881 for(efa= em->faces.first; efa; efa= efa->next) {
2882 if(!(efa->h) && !(efa->f & SELECT)) {
2883 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2885 tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2889 /* Select all edges and verts now */
2890 for(efa= em->faces.first; efa; efa= efa->next)
2891 /* we only selected the face flags, and didnt changes edges or verts, fix this now */
2892 if(!(efa->h) && (efa->f & SELECT))
2893 EM_select_face(efa, 1);
2896 for(efa= em->faces.first; efa; efa= efa->next) {
2897 if(!(efa->h) && !(efa->f & SELECT)) {
2898 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2900 if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;}
2901 if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;}
2902 if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;}
2903 if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;}
2909 /* Select all edges and verts now */
2910 for(efa= em->faces.first; efa; efa= efa->next)
2911 /* we only selected the face flags, and didnt changes edges or verts, fix this now */
2912 if(!(efa->h) && (efa->f & SELECT))
2913 EM_select_face(efa, 1);
2916 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2918 BKE_mesh_end_editmesh(obedit->data, em);
2919 return OPERATOR_FINISHED;
2922 void UV_OT_reveal(wmOperatorType *ot)
2925 ot->name= "Reveal Hidden";
2926 ot->idname= "UV_OT_reveal";
2927 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2930 ot->exec= reveal_exec;
2931 ot->poll= ED_operator_uvedit;
2934 /******************** set 3d cursor operator ********************/
2936 static int set_2d_cursor_exec(bContext *C, wmOperator *op)
2938 ARegion *ar= CTX_wm_region(C);
2941 RNA_float_get_array(op->ptr, "location", location);
2942 ar->v2d.cursor[0]= location[0];
2943 ar->v2d.cursor[1]= location[1];
2945 ED_area_tag_redraw(CTX_wm_area(C));
2947 return OPERATOR_FINISHED;
2950 static int set_2d_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
2952 ARegion *ar= CTX_wm_region(C);
2956 x= event->x - ar->winrct.xmin;
2957 y= event->y - ar->winrct.ymin;
2958 UI_view2d_region_to_view(&ar->v2d, x, y, &location[0], &location[1]);
2959 RNA_float_set_array(op->ptr, "location", location);
2961 return set_2d_cursor_exec(C, op);
2964 void UV_OT_cursor_set(wmOperatorType *ot)
2967 ot->name= "Set 3D Cursor";
2968 ot->idname= "UV_OT_cursor_set";
2971 ot->exec= set_2d_cursor_exec;
2972 ot->invoke= set_2d_cursor_invoke;
2973 ot->poll= ED_operator_uvedit;
2976 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2979 RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in 0.0-1.0 coordinates.", -10.0f, 10.0f);
2982 /********************** set tile operator **********************/
2984 static int set_tile_exec(bContext *C, wmOperator *op)
2986 Image *ima= CTX_data_edit_image(C);
2989 if(!ima || !(ima->tpageflag & IMA_TILES))
2990 return OPERATOR_CANCELLED;
2992 RNA_int_get_array(op->ptr, "tile", tile);
2993 ED_uvedit_set_tile(C, CTX_data_scene(C), CTX_data_edit_object(C), ima, tile[0] + ima->xrep*tile[1]);
2995 ED_area_tag_redraw(CTX_wm_area(C));
2997 return OPERATOR_FINISHED;
3000 static int set_tile_invoke(bContext *C, wmOperator *op, wmEvent *event)
3002 SpaceImage *sima= CTX_wm_space_image(C);
3003 Image *ima= CTX_data_edit_image(C);
3004 ARegion *ar= CTX_wm_region(C);
3008 if(!ima || !(ima->tpageflag & IMA_TILES))
3009 return OPERATOR_CANCELLED;
3011 x= event->x - ar->winrct.xmin;
3012 y= event->y - ar->winrct.ymin;
3013 UI_view2d_region_to_view(&ar->v2d, x, y, &fx, &fy);
3015 if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
3022 sima->curtile= tile[1]*ima->xrep + tile[0];
3023 RNA_int_set_array(op->ptr, "tile", tile);