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