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