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