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