quiet some -Wshadow warnings
[blender.git] / source / blender / editors / uvedit / uvedit_unwrap_ops.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/uvedit/uvedit_unwrap_ops.c
29  *  \ingroup eduv
30  */
31
32
33 #include <string.h>
34 #include <stdlib.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_camera_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_meshdata_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_modifier_types.h"
45
46 #include "BLI_utildefines.h"
47 #include "BLI_math.h"
48 #include "BLI_edgehash.h"
49 #include "BLI_uvproject.h"
50 #include "BLI_utildefines.h"
51 #include "BLI_rand.h"
52 #include "BLI_string.h"
53
54 #include "BKE_cdderivedmesh.h"
55 #include "BKE_subsurf.h"
56 #include "BKE_context.h"
57 #include "BKE_customdata.h"
58 #include "BKE_depsgraph.h"
59 #include "BKE_image.h"
60 #include "BKE_main.h"
61 #include "BKE_mesh.h"
62 #include "BKE_report.h"
63 #include "BKE_tessmesh.h"
64
65 #include "BLI_math.h"
66 #include "BLI_edgehash.h"
67 #include "BLI_scanfill.h"
68 #include "BLI_array.h"
69 #include "BLI_uvproject.h"
70
71 #include "PIL_time.h"
72
73 #include "ED_image.h"
74 #include "ED_mesh.h"
75 #include "ED_screen.h"
76 #include "ED_uvedit.h"
77 #include "ED_view3d.h"
78
79 #include "RNA_access.h"
80 #include "RNA_define.h"
81
82
83 #include "WM_api.h"
84 #include "WM_types.h"
85
86 #include "uvedit_intern.h"
87 #include "uvedit_parametrizer.h"
88
89 static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
90 {
91         Main *bmain = CTX_data_main(C);
92         BMEditMesh *em = BMEdit_FromObject(obedit);
93         BMFace *efa;
94         BMIter iter;
95         Image *ima;
96         bScreen *sc;
97         ScrArea *sa;
98         SpaceLink *slink;
99         SpaceImage *sima;
100
101         if (ED_uvedit_test(obedit))
102                 return 1;
103
104         if (em && em->bm->totface && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY))
105                 ED_mesh_uv_texture_add(C, obedit->data, NULL, TRUE);
106
107         if (!ED_uvedit_test(obedit))
108                 return 0;
109
110         ima = CTX_data_edit_image(C);
111
112         if (!ima) {
113                 /* no image in context in the 3d view, we find first image window .. */
114                 sc = CTX_wm_screen(C);
115
116                 for (sa = sc->areabase.first; sa; sa = sa->next) {
117                         slink = sa->spacedata.first;
118                         if (slink->spacetype == SPACE_IMAGE) {
119                                 sima = (SpaceImage *)slink;
120
121                                 ima = sima->image;
122                                 if (ima) {
123                                         if (ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE)
124                                                 ima = NULL;
125                                         else
126                                                 break;
127                                 }
128                         }
129                 }
130         }
131         
132         if (ima)
133                 ED_uvedit_assign_image(bmain, scene, obedit, ima, NULL);
134         
135         /* select new UV's */
136         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
137                 uvedit_face_select_enable(scene, em, efa, FALSE);
138         }
139
140         return 1;
141 }
142
143 /****************** Parametrizer Conversion ***************/
144
145 static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
146 {
147         BMFace *efa;
148         BMLoop *l;
149         BMIter iter, liter;
150         MLoopUV *luv;
151         
152         /* verify if we have any selected uv's before unwrapping,
153          * so we can cancel the operator early */
154         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
155                 if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
156                         if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
157                                 continue;
158                 }
159                 else if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))
160                         continue;
161         
162                 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
163                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
164                         if (!luv)
165                                 return 1;
166                         
167                         if (uvedit_uv_select_test(em, scene, l))
168                                 break;
169                 }
170                 
171                 if (implicit && !l)
172                         continue;
173                 
174                 return 1;
175         }
176
177         return 0;
178 }
179
180 static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, 
181                                            short implicit, short fill, short sel,
182                                            short correct_aspect)
183 {
184         ScanFillContext sf_ctx;
185         ParamHandle *handle;
186         BMFace *efa;
187         BMLoop *l;
188         BMEdge *eed;
189         BMIter iter, liter;
190         MTexPoly *tf;
191         
192         handle = param_construct_begin();
193
194         if (correct_aspect) {
195                 int sloppy = TRUE;
196                 int selected = FALSE;
197
198                 efa = BM_active_face_get(em->bm, sloppy, selected);
199
200                 if (efa) {
201                         float aspx, aspy;
202                         tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
203
204                         ED_image_get_uv_aspect(tf->tpage, NULL, &aspx, &aspy);
205                 
206                         if (aspx != aspy)
207                                 param_aspect_ratio(handle, aspx, aspy);
208                         else
209                                 param_aspect_ratio(handle, 1.0, 1.0);
210                 }
211         }
212         
213         /* we need the vert indices */
214         BM_mesh_elem_index_ensure(em->bm, BM_VERT);
215
216         BLI_srand(0);
217         
218         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
219                 ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first;
220                 ScanFillFace *sf_tri;
221                 ParamKey key, vkeys[4];
222                 ParamBool pin[4], select[4];
223                 BMLoop *ls[3];
224                 float *co[4];
225                 float *uv[4];
226                 int lsel;
227
228                 if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || (sel && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0))
229                         continue;
230
231                 lsel = 0;
232
233                 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
234                         if (uvedit_uv_select_test(em, scene, l)) {
235                                 lsel = 1;
236                                 break;
237                         }
238                 }
239
240                 if (implicit && !lsel)
241                         continue;
242
243                 key = (ParamKey)efa;
244
245                 // tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);  // UNUSED
246
247                 if (efa->len == 3 || efa->len == 4) {
248                         int i;
249                         /* for quads let parametrize split, it can make better decisions
250                          * about which split is best for unwrapping than scanfill */
251                         i = 0;
252                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
253                                 MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
254                                 vkeys[i] = (ParamKey)BM_elem_index_get(l->v);
255                                 co[i] = l->v->co;
256                                 uv[i] = luv->uv;
257                                 pin[i] = (luv->flag & MLOOPUV_PINNED) != 0;
258                                 select[i] = uvedit_uv_select_test(em, scene, l) != 0;
259
260                                 i++;
261                         }
262
263                         param_face_add(handle, key, i, vkeys, co, uv, pin, select);
264                 }
265                 else {
266                         /* ngon - scanfill time! */
267                         BLI_scanfill_begin(&sf_ctx);
268                         
269                         sf_vert_first = sf_vert_last = NULL;
270                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
271                                 int i;
272                                 
273                                 sf_vert = BLI_scanfill_vert_add(&sf_ctx, l->v->co);
274                                 
275                                 /* add small random offset */
276                                 for (i = 0; i < 3; i++) {
277                                         sf_vert->co[i] += (BLI_frand() - 0.5f) * FLT_EPSILON * 50;
278                                 }
279                                 
280                                 sf_vert->tmp.p = l;
281
282                                 if (sf_vert_last) {
283                                         BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
284                                 }
285
286                                 sf_vert_last = sf_vert;
287                                 if (!sf_vert_first)
288                                         sf_vert_first = sf_vert;
289                         }
290
291                         BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
292
293                         BLI_scanfill_calc_ex(&sf_ctx, TRUE, efa->no);
294                         for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
295                                 int i;
296                                 ls[0] = sf_tri->v1->tmp.p;
297                                 ls[1] = sf_tri->v2->tmp.p;
298                                 ls[2] = sf_tri->v3->tmp.p;
299
300                                 for (i = 0; i < 3; i++) {
301                                         MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, ls[i]->head.data, CD_MLOOPUV);
302                                         vkeys[i] = (ParamKey)BM_elem_index_get(ls[i]->v);
303                                         co[i] = ls[i]->v->co;
304                                         uv[i] = luv->uv;
305                                         pin[i] = (luv->flag & MLOOPUV_PINNED) != 0;
306                                         select[i] = uvedit_uv_select_test(em, scene, ls[i]) != 0;
307                                 }
308
309                                 param_face_add(handle, key, 3, vkeys, co, uv, pin, select);
310                         }
311
312                         BLI_scanfill_end(&sf_ctx);
313                 }
314         }
315
316         if (!implicit) {
317                 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
318                         if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
319                                 ParamKey vkeys[2];
320                                 vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
321                                 vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
322                                 param_edge_set_seam(handle, vkeys);
323                         }
324                 }
325         }
326
327         param_construct_end(handle, fill, implicit);
328
329         return handle;
330 }
331
332
333 static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, Scene *scene, BMEditMesh *em)
334 {
335         BMLoop *l;
336         BMIter liter;
337         MLoopUV *luv;
338
339         *uv = NULL;
340         *pin = 0;
341         *select = 1;
342
343         if (index == ORIGINDEX_NONE)
344                 return;
345
346         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
347                 if (BM_elem_index_get(l->v) == index) {
348                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
349                         *uv = luv->uv;
350                         *pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0;
351                         *select = (uvedit_uv_select_test(em, scene, l) != 0);
352                 }
353         }
354 }
355
356 /* unwrap handle initialization for subsurf aware-unwrapper. The many modifications required to make the original function(see above)
357  * work justified the existence of a new function. */
358 static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *em, short fill, short sel, short correct_aspect)
359 {
360         ParamHandle *handle;
361         /* index pointers */
362         MFace *face;
363         MEdge *edge;
364         BMFace *editFace;
365         int i;
366
367         /* modifier initialization data, will  control what type of subdivision will happen*/
368         SubsurfModifierData smd = {{0}};
369         /* Used to hold subsurfed Mesh */
370         DerivedMesh *derivedMesh, *initialDerived;
371         /* holds original indices for subsurfed mesh */
372         int *origVertIndices, *origFaceIndices, *origEdgeIndices;
373         /* Holds vertices of subsurfed mesh */
374         MVert *subsurfedVerts;
375         MEdge *subsurfedEdges;
376         MFace *subsurfedFaces;
377         /* number of vertices and faces for subsurfed mesh*/
378         int numOfEdges, numOfFaces;
379
380         /* holds a map to editfaces for every subsurfed MFace. These will be used to get hidden/ selected flags etc. */
381         BMFace **faceMap;
382         /* similar to the above, we need a way to map edges to their original ones */
383         BMEdge **edgeMap;
384
385         handle = param_construct_begin();
386
387         if (correct_aspect) {
388                 int sloppy = TRUE;
389                 int selected = FALSE;
390
391                 editFace = BM_active_face_get(em->bm, sloppy, selected);
392
393                 if (editFace) {
394                         MTexPoly *tf;
395                         float aspx, aspy;
396                         tf = CustomData_bmesh_get(&em->bm->pdata, editFace->head.data, CD_MTEXPOLY);
397
398                         ED_image_get_uv_aspect(tf->tpage, NULL, &aspx, &aspy);
399
400                         if (aspx != aspy)
401                                 param_aspect_ratio(handle, aspx, aspy);
402                         else
403                                 param_aspect_ratio(handle, 1.0, 1.0);
404                 }
405         }
406
407         /* number of subdivisions to perform */
408         smd.levels = scene->toolsettings->uv_subsurf_level;
409         smd.subdivType = ME_CC_SUBSURF;
410                 
411         initialDerived = CDDM_from_BMEditMesh(em, NULL, 0, 0);
412         derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd,
413                                                         NULL, SUBSURF_IN_EDIT_MODE);
414
415         initialDerived->release(initialDerived);
416
417         /* get the derived data */
418         subsurfedVerts = derivedMesh->getVertArray(derivedMesh);
419         subsurfedEdges = derivedMesh->getEdgeArray(derivedMesh);
420         subsurfedFaces = derivedMesh->getTessFaceArray(derivedMesh);
421
422         origVertIndices = derivedMesh->getVertDataArray(derivedMesh, CD_ORIGINDEX);
423         origEdgeIndices = derivedMesh->getEdgeDataArray(derivedMesh, CD_ORIGINDEX);
424         origFaceIndices = derivedMesh->getTessFaceDataArray(derivedMesh, CD_ORIGINDEX);
425
426         numOfEdges = derivedMesh->getNumEdges(derivedMesh);
427         numOfFaces = derivedMesh->getNumTessFaces(derivedMesh);
428
429         faceMap = MEM_mallocN(numOfFaces * sizeof(BMFace *), "unwrap_edit_face_map");
430
431         BM_mesh_elem_index_ensure(em->bm, BM_VERT);
432         EDBM_index_arrays_init(em, 0, 1, 1);
433
434         /* map subsurfed faces to original editFaces */
435         for (i = 0; i < numOfFaces; i++)
436                 faceMap[i] = EDBM_face_at_index(em, origFaceIndices[i]);
437
438         edgeMap = MEM_mallocN(numOfEdges * sizeof(BMEdge *), "unwrap_edit_edge_map");
439
440         /* map subsurfed edges to original editEdges */
441         for (i = 0; i < numOfEdges; i++) {
442                 /* not all edges correspond to an old edge */
443                 edgeMap[i] = (origEdgeIndices[i] != -1) ?
444                              EDBM_edge_at_index(em, origEdgeIndices[i]) : NULL;
445         }
446
447         EDBM_index_arrays_free(em);
448
449         /* Prepare and feed faces to the solver */
450         for (i = 0; i < numOfFaces; i++) {
451                 ParamKey key, vkeys[4];
452                 ParamBool pin[4], select[4];
453                 float *co[4];
454                 float *uv[4];
455                 BMFace *origFace = faceMap[i];
456
457                 face = subsurfedFaces + i;
458
459                 if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
460                         if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN))
461                                 continue;
462                 }
463                 else {
464                         if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN) || (sel && !BM_elem_flag_test(origFace, BM_ELEM_SELECT)))
465                                 continue;
466                 }
467
468                 /* We will not check for v4 here. Subsurfed mfaces always have 4 vertices. */
469                 key = (ParamKey)face;
470                 vkeys[0] = (ParamKey)face->v1;
471                 vkeys[1] = (ParamKey)face->v2;
472                 vkeys[2] = (ParamKey)face->v3;
473                 vkeys[3] = (ParamKey)face->v4;
474
475                 co[0] = subsurfedVerts[face->v1].co;
476                 co[1] = subsurfedVerts[face->v2].co;
477                 co[2] = subsurfedVerts[face->v3].co;
478                 co[3] = subsurfedVerts[face->v4].co;
479                 
480                 /* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus
481                  * flushing the solution to the edit mesh. */
482                 texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em);
483                 texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em);
484                 texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em);
485                 texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em);
486
487                 param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
488         }
489
490         /* these are calculated from original mesh too */
491         for (edge = subsurfedEdges, i = 0; i < numOfEdges; i++, edge++) {
492                 if ((edgeMap[i] != NULL) && BM_elem_flag_test(edgeMap[i], BM_ELEM_SEAM)) {
493                         ParamKey vkeys[2];
494                         vkeys[0] = (ParamKey)edge->v1;
495                         vkeys[1] = (ParamKey)edge->v2;
496                         param_edge_set_seam(handle, vkeys);
497                 }
498         }
499
500         param_construct_end(handle, fill, 0);
501
502         /* cleanup */
503         MEM_freeN(faceMap);
504         MEM_freeN(edgeMap);
505         derivedMesh->release(derivedMesh);
506
507         return handle;
508 }
509
510 /* ******************** Minimize Stretch operator **************** */
511
512 typedef struct MinStretch {
513         Scene *scene;
514         Object *obedit;
515         BMEditMesh *em;
516         ParamHandle *handle;
517         float blend;
518         double lasttime;
519         int i, iterations;
520         wmTimer *timer;
521 } MinStretch;
522
523 static int minimize_stretch_init(bContext *C, wmOperator *op)
524 {
525         Scene *scene = CTX_data_scene(C);
526         Object *obedit = CTX_data_edit_object(C);
527         BMEditMesh *em = BMEdit_FromObject(obedit);
528         MinStretch *ms;
529         int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
530         short implicit = 1;
531
532         if (!uvedit_have_selection(scene, em, implicit)) {
533                 return 0;
534         }
535
536         ms = MEM_callocN(sizeof(MinStretch), "MinStretch");
537         ms->scene = scene;
538         ms->obedit = obedit;
539         ms->em = em;
540         ms->blend = RNA_float_get(op->ptr, "blend");
541         ms->iterations = RNA_int_get(op->ptr, "iterations");
542         ms->i = 0;
543         ms->handle = construct_param_handle(scene, em, implicit, fill_holes, 1, 1);
544         ms->lasttime = PIL_check_seconds_timer();
545
546         param_stretch_begin(ms->handle);
547         if (ms->blend != 0.0f)
548                 param_stretch_blend(ms->handle, ms->blend);
549
550         op->customdata = ms;
551
552         return 1;
553 }
554
555 static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interactive)
556 {
557         MinStretch *ms = op->customdata;
558         ScrArea *sa = CTX_wm_area(C);
559
560         param_stretch_blend(ms->handle, ms->blend);
561         param_stretch_iter(ms->handle);
562
563         ms->i++;
564         RNA_int_set(op->ptr, "iterations", ms->i);
565
566         if (interactive && (PIL_check_seconds_timer() - ms->lasttime > 0.5)) {
567                 char str[100];
568
569                 param_flush(ms->handle);
570
571                 if (sa) {
572                         BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f", ms->blend);
573                         ED_area_headerprint(sa, str);
574                 }
575
576                 ms->lasttime = PIL_check_seconds_timer();
577
578                 DAG_id_tag_update(ms->obedit->data, 0);
579                 WM_event_add_notifier(C, NC_GEOM | ND_DATA, ms->obedit->data);
580         }
581 }
582
583 static void minimize_stretch_exit(bContext *C, wmOperator *op, int cancel)
584 {
585         MinStretch *ms = op->customdata;
586         ScrArea *sa = CTX_wm_area(C);
587
588         if (sa)
589                 ED_area_headerprint(sa, NULL);
590         if (ms->timer)
591                 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ms->timer);
592
593         if (cancel)
594                 param_flush_restore(ms->handle);
595         else
596                 param_flush(ms->handle);
597
598         param_stretch_end(ms->handle);
599         param_delete(ms->handle);
600
601         DAG_id_tag_update(ms->obedit->data, 0);
602         WM_event_add_notifier(C, NC_GEOM | ND_DATA, ms->obedit->data);
603
604         MEM_freeN(ms);
605         op->customdata = NULL;
606 }
607
608 static int minimize_stretch_exec(bContext *C, wmOperator *op)
609 {
610         int i, iterations;
611
612         if (!minimize_stretch_init(C, op))
613                 return OPERATOR_CANCELLED;
614
615         iterations = RNA_int_get(op->ptr, "iterations");
616         for (i = 0; i < iterations; i++)
617                 minimize_stretch_iteration(C, op, 0);
618         minimize_stretch_exit(C, op, 0);
619
620         return OPERATOR_FINISHED;
621 }
622
623 static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
624 {
625         MinStretch *ms;
626
627         if (!minimize_stretch_init(C, op))
628                 return OPERATOR_CANCELLED;
629
630         minimize_stretch_iteration(C, op, 1);
631
632         ms = op->customdata;
633         WM_event_add_modal_handler(C, op);
634         ms->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
635
636         return OPERATOR_RUNNING_MODAL;
637 }
638
639 static int minimize_stretch_modal(bContext *C, wmOperator *op, wmEvent *event)
640 {
641         MinStretch *ms = op->customdata;
642
643         switch (event->type) {
644                 case ESCKEY:
645                 case RIGHTMOUSE:
646                         minimize_stretch_exit(C, op, 1);
647                         return OPERATOR_CANCELLED;
648                 case RETKEY:
649                 case PADENTER:
650                 case LEFTMOUSE:
651                         minimize_stretch_exit(C, op, 0);
652                         return OPERATOR_FINISHED;
653                 case PADPLUSKEY:
654                 case WHEELUPMOUSE:
655                         if (ms->blend < 0.95f) {
656                                 ms->blend += 0.1f;
657                                 ms->lasttime = 0.0f;
658                                 RNA_float_set(op->ptr, "blend", ms->blend);
659                                 minimize_stretch_iteration(C, op, 1);
660                         }
661                         break;
662                 case PADMINUS:
663                 case WHEELDOWNMOUSE:
664                         if (ms->blend > 0.05f) {
665                                 ms->blend -= 0.1f;
666                                 ms->lasttime = 0.0f;
667                                 RNA_float_set(op->ptr, "blend", ms->blend);
668                                 minimize_stretch_iteration(C, op, 1);
669                         }
670                         break;
671                 case TIMER:
672                         if (ms->timer == event->customdata) {
673                                 double start = PIL_check_seconds_timer();
674
675                                 do {
676                                         minimize_stretch_iteration(C, op, 1);
677                                 } while (PIL_check_seconds_timer() - start < 0.01);
678                         }
679                         break;
680         }
681
682         if (ms->iterations && ms->i >= ms->iterations) {
683                 minimize_stretch_exit(C, op, 0);
684                 return OPERATOR_FINISHED;
685         }
686
687         return OPERATOR_RUNNING_MODAL;
688 }
689
690 static int minimize_stretch_cancel(bContext *C, wmOperator *op)
691 {
692         minimize_stretch_exit(C, op, 1);
693
694         return OPERATOR_CANCELLED;
695 }
696
697 void UV_OT_minimize_stretch(wmOperatorType *ot)
698 {
699         /* identifiers */
700         ot->name = "Minimize Stretch";
701         ot->idname = "UV_OT_minimize_stretch";
702         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
703         ot->description = "Reduce UV stretching by relaxing angles";
704         
705         /* api callbacks */
706         ot->exec = minimize_stretch_exec;
707         ot->invoke = minimize_stretch_invoke;
708         ot->modal = minimize_stretch_modal;
709         ot->cancel = minimize_stretch_cancel;
710         ot->poll = ED_operator_uvedit;
711
712         /* properties */
713         RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
714         RNA_def_float_factor(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original", 0.0f, 1.0f);
715         RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively", 0, 100);
716 }
717
718 /* ******************** Pack Islands operator **************** */
719
720 static int pack_islands_exec(bContext *C, wmOperator *op)
721 {
722         Scene *scene = CTX_data_scene(C);
723         Object *obedit = CTX_data_edit_object(C);
724         BMEditMesh *em = BMEdit_FromObject(obedit);
725         ParamHandle *handle;
726         short implicit = 1;
727
728         if (!uvedit_have_selection(scene, em, implicit)) {
729                 return OPERATOR_CANCELLED;
730         }
731
732         if (RNA_struct_property_is_set(op->ptr, "margin")) {
733                 scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
734         }
735         else {
736                 RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
737         }
738
739         handle = construct_param_handle(scene, em, implicit, 0, 1, 1);
740         param_pack(handle, scene->toolsettings->uvcalc_margin);
741         param_flush(handle);
742         param_delete(handle);
743         
744         DAG_id_tag_update(obedit->data, 0);
745         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
746
747         return OPERATOR_FINISHED;
748 }
749
750 void UV_OT_pack_islands(wmOperatorType *ot)
751 {
752         /* identifiers */
753         ot->name = "Pack Islands";
754         ot->idname = "UV_OT_pack_islands";
755         ot->description = "Transform all islands so that they fill up the UV space as much as possible";
756
757         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
758         
759         /* api callbacks */
760         ot->exec = pack_islands_exec;
761         ot->poll = ED_operator_uvedit;
762
763         /* properties */
764         RNA_def_float_factor(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
765 }
766
767 /* ******************** Average Islands Scale operator **************** */
768
769 static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
770 {
771         Scene *scene = CTX_data_scene(C);
772         Object *obedit = CTX_data_edit_object(C);
773         BMEditMesh *em = BMEdit_FromObject(obedit);
774         ParamHandle *handle;
775         short implicit = 1;
776
777         if (!uvedit_have_selection(scene, em, implicit)) {
778                 return OPERATOR_CANCELLED;
779         }
780
781         handle = construct_param_handle(scene, em, implicit, 0, 1, 1);
782         param_average(handle);
783         param_flush(handle);
784         param_delete(handle);
785         
786         DAG_id_tag_update(obedit->data, 0);
787         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
788
789         return OPERATOR_FINISHED;
790 }
791
792 void UV_OT_average_islands_scale(wmOperatorType *ot)
793 {
794         /* identifiers */
795         ot->name = "Average Islands Scale";
796         ot->idname = "UV_OT_average_islands_scale";
797         ot->description = "Average the size of separate UV islands, based on their area in 3D space";
798
799         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
800         
801         /* api callbacks */
802         ot->exec = average_islands_scale_exec;
803         ot->poll = ED_operator_uvedit;
804 }
805
806 /**************** Live Unwrap *****************/
807
808 static ParamHandle *liveHandle = NULL;
809
810 void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
811 {
812         BMEditMesh *em = BMEdit_FromObject(obedit);
813         short abf = scene->toolsettings->unwrapper == 0;
814         short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
815         short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
816
817         if (!ED_uvedit_test(obedit)) {
818                 return;
819         }
820
821         if (use_subsurf)
822                 liveHandle = construct_param_handle_subsurfed(scene, em, fillholes, 0, 1);
823         else
824                 liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1);
825
826         param_lscm_begin(liveHandle, PARAM_TRUE, abf);
827 }
828
829 void ED_uvedit_live_unwrap_re_solve(void)
830 {
831         if (liveHandle) {
832                 param_lscm_solve(liveHandle);
833                 param_flush(liveHandle);
834         }
835 }
836         
837 void ED_uvedit_live_unwrap_end(short cancel)
838 {
839         if (liveHandle) {
840                 param_lscm_end(liveHandle);
841                 if (cancel)
842                         param_flush_restore(liveHandle);
843                 param_delete(liveHandle);
844                 liveHandle = NULL;
845         }
846 }
847
848 void ED_uvedit_live_unwrap(Scene *scene, Object *obedit)
849 {
850         BMEditMesh *em = BMEdit_FromObject(obedit);
851
852         if (scene->toolsettings->edge_mode_live_unwrap &&
853             CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV))
854         {
855                 ED_unwrap_lscm(scene, obedit, FALSE); /* unwrap all not just sel */
856         }
857 }
858
859 /*************** UV Map Common Transforms *****************/
860
861 #define VIEW_ON_EQUATOR 0
862 #define VIEW_ON_POLES   1
863 #define ALIGN_TO_OBJECT 2
864
865 #define POLAR_ZX    0
866 #define POLAR_ZY    1
867
868 static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, 
869                                     Object *ob, BMEditMesh *em)
870 {
871         BMFace *efa;
872         BMLoop *l;
873         BMIter iter, liter;
874         float min[3], max[3], *cursx;
875         int around = (v3d) ? v3d->around : V3D_CENTER;
876
877         /* only operates on the edit object - this is all that's needed now */
878
879         switch (around) {
880                 case V3D_CENTER: /* bounding box center */
881                         INIT_MINMAX(min, max);
882                         
883                         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
884                                 if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
885                                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
886                                                 minmax_v3v3_v3(min, max, l->v->co);
887                                         }
888                                 }
889                         }
890                         mid_v3_v3v3(result, min, max);
891                         break;
892
893                 case V3D_CURSOR:  /* cursor center */
894                         cursx = give_cursor(scene, v3d);
895                         /* shift to objects world */
896                         sub_v3_v3v3(result, cursx, ob->obmat[3]);
897                         break;
898
899                 case V3D_LOCAL:     /* object center */
900                 case V3D_CENTROID:  /* multiple objects centers, only one object here*/
901                 default:
902                         result[0] = result[1] = result[2] = 0.0;
903                         break;
904         }
905 }
906
907 static void uv_map_rotation_matrix(float result[][4], RegionView3D *rv3d, Object *ob,
908                                    float upangledeg, float sideangledeg, float radius)
909 {
910         float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
911         float sideangle = 0.0f, upangle = 0.0f;
912         int k;
913
914         /* get rotation of the current view matrix */
915         if (rv3d)
916                 copy_m4_m4(viewmatrix, rv3d->viewmat);
917         else
918                 unit_m4(viewmatrix);
919
920         /* but shifting */
921         for (k = 0; k < 4; k++)
922                 viewmatrix[3][k] = 0.0f;
923
924         /* get rotation of the current object matrix */
925         copy_m4_m4(rotobj, ob->obmat);
926
927         /* but shifting */
928         for (k = 0; k < 4; k++)
929                 rotobj[3][k] = 0.0f;
930
931         zero_m4(rotup);
932         zero_m4(rotside);
933
934         /* compensate front/side.. against opengl x,y,z world definition */
935         /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
936         /* i wanted to keep the reason here, so we're rotating*/
937         sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f;
938         rotside[0][0] = (float)cos(sideangle);
939         rotside[0][1] = -(float)sin(sideangle);
940         rotside[1][0] = (float)sin(sideangle);
941         rotside[1][1] = (float)cos(sideangle);
942         rotside[2][2] = 1.0f;
943
944         upangle = (float)M_PI * upangledeg / 180.0f;
945         rotup[1][1] = (float)cos(upangle) / radius;
946         rotup[1][2] = -(float)sin(upangle) / radius;
947         rotup[2][1] = (float)sin(upangle) / radius;
948         rotup[2][2] = (float)cos(upangle) / radius;
949         rotup[0][0] = (float)1.0f / radius;
950
951         /* calculate transforms*/
952         mul_serie_m4(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL);
953 }
954
955 static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float rotmat[4][4])
956 {
957         /* context checks are messy here, making it work in both 3d view and uv editor */
958         Scene *scene = CTX_data_scene(C);
959         Object *obedit = CTX_data_edit_object(C);
960         BMEditMesh *em = BMEdit_FromObject(obedit);
961         View3D *v3d = CTX_wm_view3d(C);
962         RegionView3D *rv3d = CTX_wm_region_view3d(C);
963         /* common operator properties */
964         int align = RNA_enum_get(op->ptr, "align");
965         int direction = RNA_enum_get(op->ptr, "direction");
966         float radius = RNA_struct_find_property(op->ptr, "radius") ? RNA_float_get(op->ptr, "radius") : 1.0f;
967         float upangledeg, sideangledeg;
968
969         uv_map_transform_center(scene, v3d, center, obedit, em);
970
971         if (direction == VIEW_ON_EQUATOR) {
972                 upangledeg = 90.0f;
973                 sideangledeg = 0.0f;
974         }
975         else {
976                 upangledeg = 0.0f;
977                 if (align == POLAR_ZY) sideangledeg = 0.0f;
978                 else sideangledeg = 90.0f;
979         }
980
981         /* be compatible to the "old" sphere/cylinder mode */
982         if (direction == ALIGN_TO_OBJECT)
983                 unit_m4(rotmat);
984         else 
985                 uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
986
987 }
988
989 static void uv_transform_properties(wmOperatorType *ot, int radius)
990 {
991         static EnumPropertyItem direction_items[] = {
992                 {VIEW_ON_EQUATOR, "VIEW_ON_EQUATOR", 0, "View on Equator", "3D view is on the equator"},
993                 {VIEW_ON_POLES, "VIEW_ON_POLES", 0, "View on Poles", "3D view is on the poles"},
994                 {ALIGN_TO_OBJECT, "ALIGN_TO_OBJECT", 0, "Align to Object", "Align according to object transform"},
995                 {0, NULL, 0, NULL, NULL}
996         };
997         static EnumPropertyItem align_items[] = {
998                 {POLAR_ZX, "POLAR_ZX", 0, "Polar ZX", "Polar 0 is X"},
999                 {POLAR_ZY, "POLAR_ZY", 0, "Polar ZY", "Polar 0 is Y"},
1000                 {0, NULL, 0, NULL, NULL}
1001         };
1002
1003         RNA_def_enum(ot->srna, "direction", direction_items, VIEW_ON_EQUATOR, "Direction",
1004                      "Direction of the sphere or cylinder");
1005         RNA_def_enum(ot->srna, "align", align_items, VIEW_ON_EQUATOR, "Align",
1006                      "How to determine rotation around the pole");
1007         if (radius)
1008                 RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius",
1009                               "Radius of the sphere or cylinder", 0.0001f, 100.0f);
1010 }
1011
1012 static void correct_uv_aspect(BMEditMesh *em)
1013 {
1014         int sloppy = TRUE;
1015         int selected = FALSE;
1016         BMFace *efa = BM_active_face_get(em->bm, sloppy, selected);
1017         BMLoop *l;
1018         BMIter iter, liter;
1019         MLoopUV *luv;
1020         float scale, aspx = 1.0f, aspy = 1.0f;
1021         
1022         if (efa) {
1023                 MTexPoly *tf;
1024
1025                 tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1026                 ED_image_get_uv_aspect(tf->tpage, NULL, &aspx, &aspy);
1027         }
1028         
1029         if (aspx == aspy)
1030                 return;
1031                 
1032         if (aspx > aspy) {
1033                 scale = aspy / aspx;
1034
1035                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1036                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
1037                                 continue;
1038                         
1039                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1040                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1041                                 luv->uv[0] = ((luv->uv[0] - 0.5f) * scale) + 0.5f;
1042                         }
1043                 }
1044         }
1045         else {
1046                 scale = aspx / aspy;
1047
1048                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1049                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
1050                                 continue;
1051                         
1052                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1053                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1054                                 luv->uv[1] = ((luv->uv[1] - 0.5f) * scale) + 0.5f;
1055                         }
1056                 }
1057         }
1058 }
1059
1060 /******************** Map Clip & Correct ******************/
1061
1062 static void uv_map_clip_correct_properties(wmOperatorType *ot)
1063 {
1064         RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
1065                         "Map UVs taking image aspect ratio into account");
1066         RNA_def_boolean(ot->srna, "clip_to_bounds", 0, "Clip to Bounds",
1067                         "Clip UV coordinates to bounds after unwrapping");
1068         RNA_def_boolean(ot->srna, "scale_to_bounds", 0, "Scale to Bounds",
1069                         "Scale UV coordinates to bounds after unwrapping");
1070 }
1071
1072 static void uv_map_clip_correct(BMEditMesh *em, wmOperator *op)
1073 {
1074         BMFace *efa;
1075         BMLoop *l;
1076         BMIter iter, liter;
1077         MLoopUV *luv;
1078         float dx, dy, min[2], max[2];
1079         int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
1080         int clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds");
1081         int scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds");
1082
1083         /* correct for image aspect ratio */
1084         if (correct_aspect)
1085                 correct_uv_aspect(em);
1086
1087         if (scale_to_bounds) {
1088                 INIT_MINMAX2(min, max);
1089                 
1090                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1091                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1092                                 continue;
1093
1094                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1095                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1096                                 DO_MINMAX2(luv->uv, min, max);
1097                         }
1098                 }
1099                 
1100                 /* rescale UV to be in 1/1 */
1101                 dx = (max[0] - min[0]);
1102                 dy = (max[1] - min[1]);
1103
1104                 if (dx > 0.0f)
1105                         dx = 1.0f / dx;
1106                 if (dy > 0.0f)
1107                         dy = 1.0f / dy;
1108
1109                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1110                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1111                                 continue;
1112
1113                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1114                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1115                                 
1116                                 luv->uv[0] = (luv->uv[0] - min[0]) * dx;
1117                                 luv->uv[1] = (luv->uv[1] - min[1]) * dy;
1118                         }
1119                 }
1120         }
1121         else if (clip_to_bounds) {
1122                 /* clipping and wrapping */
1123                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1124                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1125                                 continue;
1126
1127                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1128                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1129                                 CLAMP(luv->uv[0], 0.0f, 1.0f);
1130                                 CLAMP(luv->uv[1], 0.0f, 1.0f);
1131                         }
1132                 }
1133         }
1134 }
1135
1136 /* ******************** Unwrap operator **************** */
1137
1138 /* assumes UV Map is checked, doesn't run update funcs */
1139 void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
1140 {
1141         BMEditMesh *em = BMEdit_FromObject(obedit);
1142         ParamHandle *handle;
1143
1144         const short fill_holes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
1145         const short correct_aspect = !(scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT);
1146         const short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
1147
1148         if (use_subsurf)
1149                 handle = construct_param_handle_subsurfed(scene, em, fill_holes, sel, correct_aspect);
1150         else
1151                 handle = construct_param_handle(scene, em, 0, fill_holes, sel, correct_aspect);
1152
1153         param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
1154         param_lscm_solve(handle);
1155         param_lscm_end(handle);
1156
1157         param_average(handle);
1158         param_pack(handle, scene->toolsettings->uvcalc_margin);
1159
1160         param_flush(handle);
1161
1162         param_delete(handle);
1163 }
1164
1165 static int unwrap_exec(bContext *C, wmOperator *op)
1166 {
1167         Scene *scene = CTX_data_scene(C);
1168         Object *obedit = CTX_data_edit_object(C);
1169         BMEditMesh *em = BMEdit_FromObject(obedit);
1170         int method = RNA_enum_get(op->ptr, "method");
1171         int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
1172         int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
1173         int use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
1174         int subsurf_level = RNA_int_get(op->ptr, "uv_subsurf_level");
1175         float obsize[3], unitsize[3] = {1.0f, 1.0f, 1.0f};
1176         short implicit = 0;
1177
1178         if (!uvedit_have_selection(scene, em, implicit)) {
1179                 return OPERATOR_CANCELLED;
1180         }
1181         
1182         /* add uvs if they don't exist yet */
1183         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1184                 return OPERATOR_CANCELLED;
1185         }
1186
1187         mat4_to_size(obsize, obedit->obmat);
1188         if (!compare_v3v3(obsize, unitsize, 1e-4f))
1189                 BKE_report(op->reports, RPT_INFO, "Object scale is not 1.0. Unwrap will operate on a non-scaled version of the mesh.");
1190
1191         /* remember last method for live unwrap */
1192         if (RNA_struct_property_is_set(op->ptr, "method"))
1193                 scene->toolsettings->unwrapper = method;
1194         else
1195                 RNA_enum_set(op->ptr, "method", scene->toolsettings->unwrapper);
1196
1197         scene->toolsettings->uv_subsurf_level = subsurf_level;
1198
1199         if (fill_holes) scene->toolsettings->uvcalc_flag |=  UVCALC_FILLHOLES;
1200         else scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES;
1201
1202         if (correct_aspect) scene->toolsettings->uvcalc_flag &= ~UVCALC_NO_ASPECT_CORRECT;
1203         else scene->toolsettings->uvcalc_flag |=  UVCALC_NO_ASPECT_CORRECT;
1204
1205         if (use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
1206         else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
1207
1208         /* execute unwrap */
1209         ED_unwrap_lscm(scene, obedit, TRUE);
1210
1211         DAG_id_tag_update(obedit->data, 0);
1212         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1213
1214         return OPERATOR_FINISHED;
1215 }
1216
1217 void UV_OT_unwrap(wmOperatorType *ot)
1218 {
1219         static EnumPropertyItem method_items[] = {
1220                 {0, "ANGLE_BASED", 0, "Angle Based", ""},
1221                 {1, "CONFORMAL", 0, "Conformal", ""},
1222                 {0, NULL, 0, NULL, NULL}
1223         };
1224
1225         /* identifiers */
1226         ot->name = "Unwrap";
1227         ot->description = "Unwrap the mesh of the object being edited";
1228         ot->idname = "UV_OT_unwrap";
1229         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1230         
1231         /* api callbacks */
1232         ot->exec = unwrap_exec;
1233         ot->poll = ED_operator_uvmap;
1234
1235         /* properties */
1236         RNA_def_enum(ot->srna, "method", method_items, 0, "Method",
1237                      "Unwrapping method (Angle Based usually gives better results than Conformal, while being somewhat slower)");
1238         RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes",
1239                         "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
1240         RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
1241                         "Map UVs taking image aspect ratio into account");
1242         RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Data",
1243                         "Map UVs taking vertex position after subsurf into account");
1244         RNA_def_int(ot->srna, "uv_subsurf_level", 1, 1, 6, "SubSurf Target",
1245                     "Number of times to subdivide before calculating UVs", 1, 6);
1246 }
1247
1248 /**************** Project From View operator **************/
1249 static int uv_from_view_exec(bContext *C, wmOperator *op)
1250 {
1251         Scene *scene = CTX_data_scene(C);
1252         Object *obedit = CTX_data_edit_object(C);
1253         Camera *camera = NULL;
1254         BMEditMesh *em = BMEdit_FromObject(obedit);
1255         ARegion *ar = CTX_wm_region(C);
1256         View3D *v3d = CTX_wm_view3d(C);
1257         RegionView3D *rv3d = CTX_wm_region_view3d(C);
1258         BMFace *efa;
1259         BMLoop *l;
1260         BMIter iter, liter;
1261         MLoopUV *luv;
1262         float rotmat[4][4];
1263
1264         /* add uvs if they don't exist yet */
1265         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1266                 return OPERATOR_CANCELLED;
1267         }
1268
1269         /* establish the camera object, so we can default to view mapping if anything is wrong with it */
1270         if ((rv3d->persp == RV3D_CAMOB) && (v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
1271                 camera = v3d->camera->data;
1272         }
1273
1274         if (RNA_boolean_get(op->ptr, "orthographic")) {
1275                 uv_map_rotation_matrix(rotmat, rv3d, obedit, 90.0f, 0.0f, 1.0f);
1276                 
1277                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1278                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1279                                 continue;
1280
1281                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1282                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1283                                 BLI_uvproject_from_view_ortho(luv->uv, l->v->co, rotmat);
1284                         }
1285                 }
1286         }
1287         else if (camera) {
1288                 struct ProjCameraInfo *uci = BLI_uvproject_camera_info(v3d->camera, obedit->obmat, scene->r.xsch, scene->r.ysch);
1289                 
1290                 if (uci) {
1291                         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1292                                 if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1293                                         continue;
1294
1295                                 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1296                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1297                                         BLI_uvproject_from_camera(luv->uv, l->v->co, uci);
1298                                 }
1299                         }
1300                         
1301                         MEM_freeN(uci);
1302                 }
1303         }
1304         else {
1305                 copy_m4_m4(rotmat, obedit->obmat);
1306
1307                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1308                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1309                                 continue;
1310
1311                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1312                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1313                                 BLI_uvproject_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
1314                         }
1315                 }
1316         }
1317
1318         uv_map_clip_correct(em, op);
1319
1320         DAG_id_tag_update(obedit->data, 0);
1321         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1322
1323         return OPERATOR_FINISHED;
1324 }
1325
1326 static int uv_from_view_poll(bContext *C)
1327 {
1328         RegionView3D *rv3d = CTX_wm_region_view3d(C);
1329
1330         if (!ED_operator_uvmap(C))
1331                 return 0;
1332
1333         return (rv3d != NULL);
1334 }
1335
1336 void UV_OT_from_view(wmOperatorType *ot)
1337 {
1338         /* identifiers */
1339         ot->name = "Project From View";
1340         ot->idname = "UV_OT_project_from_view";
1341         ot->description = "Project the UV vertices of the mesh as seen in current 3D view";
1342
1343         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1344         
1345         /* api callbacks */
1346         ot->exec = uv_from_view_exec;
1347         ot->poll = uv_from_view_poll;
1348
1349         /* properties */
1350         RNA_def_boolean(ot->srna, "orthographic", 0, "Orthographic", "Use orthographic projection");
1351         uv_map_clip_correct_properties(ot);
1352 }
1353
1354 /********************** Reset operator ********************/
1355
1356 static int reset_exec(bContext *C, wmOperator *UNUSED(op))
1357 {
1358         Scene *scene = CTX_data_scene(C);
1359         Object *obedit = CTX_data_edit_object(C);
1360         Mesh *me = (Mesh *)obedit->data;
1361
1362         /* add uvs if they don't exist yet */
1363         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1364                 return OPERATOR_CANCELLED;
1365         }
1366
1367         if (!ED_mesh_uv_loop_reset(C, me)) {
1368                 return OPERATOR_CANCELLED;
1369         }
1370
1371         DAG_id_tag_update(obedit->data, 0);
1372         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1373         
1374         return OPERATOR_FINISHED;
1375 }
1376
1377 void UV_OT_reset(wmOperatorType *ot)
1378 {
1379         /* identifiers */
1380         ot->name = "Reset";
1381         ot->idname = "UV_OT_reset";
1382         ot->description = "Reset UV projection";
1383
1384         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1385         
1386         /* api callbacks */
1387         ot->exec = reset_exec;
1388         ot->poll = ED_operator_uvmap;
1389 }
1390
1391 /****************** Sphere Project operator ***************/
1392
1393 static void uv_sphere_project(float target[2], float source[3], float center[3], float rotmat[4][4])
1394 {
1395         float pv[3];
1396
1397         sub_v3_v3v3(pv, source, center);
1398         mul_m4_v3(rotmat, pv);
1399
1400         map_to_sphere(&target[0], &target[1], pv[0], pv[1], pv[2]);
1401
1402         /* split line is always zero */
1403         if (target[0] >= 1.0f)
1404                 target[0] -= 1.0f;  
1405 }
1406
1407 static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf))
1408 {
1409         BMLoop *l;
1410         BMIter liter;
1411         MLoopUV *luv;
1412         float **uvs = NULL;
1413         BLI_array_fixedstack_declare(uvs, BM_NGON_STACK_SIZE, efa->len, __func__);
1414         float dx;
1415         int i, mi;
1416
1417         i = 0;
1418         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1419                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1420                 uvs[i] = luv->uv;
1421                 i++;
1422         }
1423
1424         mi = 0;
1425         for (i = 1; i < efa->len; i++)
1426                 if (uvs[i][0] > uvs[mi][0])
1427                         mi = i;
1428
1429         for (i = 0; i < efa->len; i++) {
1430                 if (i != mi) {
1431                         dx = uvs[mi][0] - uvs[i][0];
1432                         if (dx > 0.5f) uvs[i][0] += 1.0f;
1433                 } 
1434         } 
1435
1436         BLI_array_fixedstack_free(uvs);
1437 }
1438
1439 static int sphere_project_exec(bContext *C, wmOperator *op)
1440 {
1441         Scene *scene = CTX_data_scene(C);
1442         Object *obedit = CTX_data_edit_object(C);
1443         BMEditMesh *em = BMEdit_FromObject(obedit);
1444         BMFace *efa;
1445         BMLoop *l;
1446         BMIter iter, liter;
1447         MTexPoly *tf;
1448         MLoopUV *luv;
1449         float center[3], rotmat[4][4];
1450
1451         /* add uvs if they don't exist yet */
1452         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1453                 return OPERATOR_CANCELLED;
1454         }
1455
1456         uv_map_transform(C, op, center, rotmat);
1457
1458         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1459                 if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1460                         continue;
1461
1462                 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1463                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1464
1465                         uv_sphere_project(luv->uv, l->v->co, center, rotmat);
1466                 }
1467
1468                 tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1469                 uv_map_mirror(em, efa, tf);
1470         }
1471
1472         uv_map_clip_correct(em, op);
1473
1474         DAG_id_tag_update(obedit->data, 0);
1475         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1476
1477         return OPERATOR_FINISHED;
1478 }
1479
1480 void UV_OT_sphere_project(wmOperatorType *ot)
1481 {
1482         /* identifiers */
1483         ot->name = "Sphere Projection";
1484         ot->idname = "UV_OT_sphere_project";
1485         ot->description = "Project the UV vertices of the mesh over the curved surface of a sphere";
1486
1487         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1488         
1489         /* api callbacks */
1490         ot->exec = sphere_project_exec;
1491         ot->poll = ED_operator_uvmap;
1492
1493         /* properties */
1494         uv_transform_properties(ot, 0);
1495         uv_map_clip_correct_properties(ot);
1496 }
1497
1498 /***************** Cylinder Project operator **************/
1499
1500 static void uv_cylinder_project(float target[2], float source[3], float center[3], float rotmat[4][4])
1501 {
1502         float pv[3];
1503
1504         sub_v3_v3v3(pv, source, center);
1505         mul_m4_v3(rotmat, pv);
1506
1507         map_to_tube(&target[0], &target[1], pv[0], pv[1], pv[2]);
1508
1509         /* split line is always zero */
1510         if (target[0] >= 1.0f)
1511                 target[0] -= 1.0f;  
1512 }
1513
1514 static int cylinder_project_exec(bContext *C, wmOperator *op)
1515 {
1516         Scene *scene = CTX_data_scene(C);
1517         Object *obedit = CTX_data_edit_object(C);
1518         BMEditMesh *em = BMEdit_FromObject(obedit);
1519         BMFace *efa;
1520         BMLoop *l;
1521         BMIter iter, liter;
1522         MTexPoly *tf;
1523         MLoopUV *luv;
1524         float center[3], rotmat[4][4];
1525
1526         /* add uvs if they don't exist yet */
1527         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1528                 return OPERATOR_CANCELLED;
1529         }
1530
1531         uv_map_transform(C, op, center, rotmat);
1532
1533         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1534                 tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1535                 if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1536                         continue;
1537                 
1538                 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1539                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1540
1541                         uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
1542                 }
1543
1544                 uv_map_mirror(em, efa, tf);
1545         }
1546
1547         uv_map_clip_correct(em, op);
1548
1549         DAG_id_tag_update(obedit->data, 0);
1550         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1551
1552         return OPERATOR_FINISHED;
1553 }
1554
1555 void UV_OT_cylinder_project(wmOperatorType *ot)
1556 {
1557         /* identifiers */
1558         ot->name = "Cylinder Projection";
1559         ot->idname = "UV_OT_cylinder_project";
1560         ot->description = "Project the UV vertices of the mesh over the curved wall of a cylinder";
1561
1562         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1563         
1564         /* api callbacks */
1565         ot->exec = cylinder_project_exec;
1566         ot->poll = ED_operator_uvmap;
1567
1568         /* properties */
1569         uv_transform_properties(ot, 1);
1570         uv_map_clip_correct_properties(ot);
1571 }
1572
1573 /******************* Cube Project operator ****************/
1574
1575 static int cube_project_exec(bContext *C, wmOperator *op)
1576 {
1577         Scene *scene = CTX_data_scene(C);
1578         Object *obedit = CTX_data_edit_object(C);
1579         BMEditMesh *em = BMEdit_FromObject(obedit);
1580         BMFace *efa;
1581         BMLoop *l;
1582         BMIter iter, liter;
1583         /* MTexPoly *tf; */ /* UNUSED */
1584         MLoopUV *luv;
1585         float cube_size, *loc, dx, dy;
1586         int cox, coy;
1587
1588         /* add uvs if they don't exist yet */
1589         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1590                 return OPERATOR_CANCELLED;
1591         }
1592
1593         loc = obedit->obmat[3];
1594         cube_size = RNA_float_get(op->ptr, "cube_size");
1595
1596         /* choose x,y,z axis for projection depending on the largest normal
1597          * component, but clusters all together around the center of map. */
1598
1599         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1600                 int first = 1;
1601
1602                 /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
1603                 if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1604                         continue;
1605
1606                 axis_dominant_v3(&cox, &coy, efa->no);
1607
1608                 dx = dy = 0;
1609                 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1610                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1611
1612                         luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]);
1613                         luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]);
1614                         
1615                         if (first) {
1616                                 dx = floor(luv->uv[0]);
1617                                 dy = floor(luv->uv[1]);
1618                                 first = 0;
1619                         }
1620                         
1621
1622                         luv->uv[0] -= dx;
1623                         luv->uv[1] -= dy;
1624                 }
1625         }
1626
1627         uv_map_clip_correct(em, op);
1628
1629         DAG_id_tag_update(obedit->data, 0);
1630         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1631
1632         return OPERATOR_FINISHED;
1633 }
1634
1635 void UV_OT_cube_project(wmOperatorType *ot)
1636 {
1637         /* identifiers */
1638         ot->name = "Cube Projection";
1639         ot->idname = "UV_OT_cube_project";
1640         ot->description = "Project the UV vertices of the mesh over the six faces of a cube";
1641
1642         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1643         
1644         /* api callbacks */
1645         ot->exec = cube_project_exec;
1646         ot->poll = ED_operator_uvmap;
1647
1648         /* properties */
1649         RNA_def_float(ot->srna, "cube_size", 1.0f, 0.0f, FLT_MAX, "Cube Size", "Size of the cube to project on", 0.001f, 100.0f);
1650         uv_map_clip_correct_properties(ot);
1651 }