Fix #30952: uv unwrapper not working as well as 2.62 on some topologies, let the
[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(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
142                 uvedit_face_select(scene, em, efa);
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(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
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(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
168                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
169                         if (!luv)
170                                 return 1;
171                         
172                         if (uvedit_uv_selected(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         ParamHandle *handle;
190         BMFace *efa;
191         BMLoop *l;
192         BMEdge *eed;
193         BMIter iter, liter;
194         MTexPoly *tf;
195         
196         handle = param_construct_begin();
197
198         if (correct_aspect) {
199                 efa = BM_active_face_get(em->bm, TRUE);
200
201                 if (efa) {
202                         float aspx, aspy;
203                         tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
204
205                         ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
206                 
207                         if (aspx != aspy)
208                                 param_aspect_ratio(handle, aspx, aspy);
209                 }
210         }
211         
212         /* we need the vert indices */
213         BM_mesh_elem_index_ensure(em->bm, BM_VERT);
214
215         BLI_srand(0);
216         
217         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
218                 ScanFillVert *v, *lastv, *firstv;
219                 ScanFillFace *sefa;
220                 ParamKey key, vkeys[4];
221                 ParamBool pin[4], select[4];
222                 BMLoop *ls[3];
223                 float *co[4];
224                 float *uv[4];
225                 int i, lsel;
226
227                 if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || (sel && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0))
228                         continue;
229
230                 lsel = 0;
231
232                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
233                         if (uvedit_uv_selected(em, scene, l)) {
234                                 lsel = 1;
235                                 break;
236                         }
237                 }
238
239                 if (implicit && !lsel)
240                         continue;
241
242                 key = (ParamKey)efa;
243
244
245                 if(efa->len == 3 || efa->len == 4) {
246                         /* for quads let parametrize split, it can make better decisions
247                            about which split is best for unwrapping than scanfill */
248                         i = 0;
249                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
250                                 MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
251                                 vkeys[i] = (ParamKey)BM_elem_index_get(l->v);
252                                 co[i] = l->v->co;
253                                 uv[i] = luv->uv;
254                                 pin[i] = (luv->flag & MLOOPUV_PINNED) != 0;
255                                 select[i] = uvedit_uv_selected(em, scene, l) != 0;
256
257                                 i++;
258                         }
259
260                         param_face_add(handle, key, i, vkeys, co, uv, pin, select);
261                 }
262                 else {
263                         /* ngon - scanfill time! */
264                         BLI_begin_edgefill();
265                         
266                         firstv = lastv = NULL;
267                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
268                                 int i;
269                                 
270                                 v = BLI_addfillvert(l->v->co);
271                                 
272                                 /* add small random offset */
273                                 for (i = 0; i < 3; i++) {
274                                         v->co[i] += (BLI_frand() - 0.5f) * FLT_EPSILON * 50;
275                                 }
276                                 
277                                 v->tmp.p = l;
278
279                                 if (lastv) {
280                                         BLI_addfilledge(lastv, v);
281                                 }
282
283                                 lastv = v;
284                                 if (!firstv) 
285                                         firstv = v;
286                         }
287
288                         BLI_addfilledge(firstv, v);
289                         
290                         /* mode 2 enables faster handling of tri/quads */
291                         BLI_edgefill(2);
292                         for (sefa = fillfacebase.first; sefa; sefa = sefa->next) {
293                                 ls[0] = sefa->v1->tmp.p;
294                                 ls[1] = sefa->v2->tmp.p;
295                                 ls[2] = sefa->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_selected(em, scene, ls[i]) != 0;
304                                 }
305
306                                 param_face_add(handle, key, 3, vkeys, co, uv, pin, select);
307                         }
308
309                         BLI_end_edgefill();
310                 }
311         }
312
313         if (!implicit) {
314                 BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
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(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
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_selected(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                                                         0, NULL, 0, 0, 1);
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->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
748         
749         /* api callbacks */
750         ot->exec = pack_islands_exec;
751         ot->poll = ED_operator_uvedit;
752
753         /* properties */
754         RNA_def_float_factor(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
755 }
756
757 /* ******************** Average Islands Scale operator **************** */
758
759 static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
760 {
761         Scene *scene = CTX_data_scene(C);
762         Object *obedit = CTX_data_edit_object(C);
763         BMEditMesh *em = BMEdit_FromObject(obedit);
764         ParamHandle *handle;
765         short implicit = 1;
766
767         if (!uvedit_have_selection(scene, em, implicit)) {
768                 return OPERATOR_CANCELLED;
769         }
770
771         handle = construct_param_handle(scene, em, implicit, 0, 1, 1);
772         param_average(handle);
773         param_flush(handle);
774         param_delete(handle);
775         
776         DAG_id_tag_update(obedit->data, 0);
777         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
778
779         return OPERATOR_FINISHED;
780 }
781
782 void UV_OT_average_islands_scale(wmOperatorType *ot)
783 {
784         /* identifiers */
785         ot->name = "Average Islands Scale";
786         ot->idname = "UV_OT_average_islands_scale";
787         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
788         
789         /* api callbacks */
790         ot->exec = average_islands_scale_exec;
791         ot->poll = ED_operator_uvedit;
792 }
793
794 /**************** Live Unwrap *****************/
795
796 static ParamHandle *liveHandle = NULL;
797
798 void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
799 {
800         BMEditMesh *em = BMEdit_FromObject(obedit);
801         short abf = scene->toolsettings->unwrapper == 0;
802         short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
803         short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
804
805         if (!ED_uvedit_test(obedit)) {
806                 return;
807         }
808
809         if (use_subsurf)
810                 liveHandle = construct_param_handle_subsurfed(scene, em, fillholes, 0, 1);
811         else
812                 liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1);
813
814         param_lscm_begin(liveHandle, PARAM_TRUE, abf);
815 }
816
817 void ED_uvedit_live_unwrap_re_solve(void)
818 {
819         if (liveHandle) {
820                 param_lscm_solve(liveHandle);
821                 param_flush(liveHandle);
822         }
823 }
824         
825 void ED_uvedit_live_unwrap_end(short cancel)
826 {
827         if (liveHandle) {
828                 param_lscm_end(liveHandle);
829                 if (cancel)
830                         param_flush_restore(liveHandle);
831                 param_delete(liveHandle);
832                 liveHandle = NULL;
833         }
834 }
835
836 void ED_uvedit_live_unwrap(Scene *scene, Object *obedit)
837 {
838         BMEditMesh *em = BMEdit_FromObject(obedit);
839
840     if (scene->toolsettings->edge_mode_live_unwrap &&
841         CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
842         ED_unwrap_lscm(scene, obedit, FALSE); /* unwrap all not just sel */
843     }
844 }
845
846 /*************** UV Map Common Transforms *****************/
847
848 #define VIEW_ON_EQUATOR 0
849 #define VIEW_ON_POLES   1
850 #define ALIGN_TO_OBJECT 2
851
852 #define POLAR_ZX    0
853 #define POLAR_ZY    1
854
855 static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, 
856                                     Object *ob, BMEditMesh *em)
857 {
858         BMFace *efa;
859         BMLoop *l;
860         BMIter iter, liter;
861         float min[3], max[3], *cursx;
862         int around = (v3d) ? v3d->around : V3D_CENTER;
863
864         /* only operates on the edit object - this is all that's needed now */
865
866         switch (around) {
867                 case V3D_CENTER: /* bounding box center */
868                         min[0] = min[1] = min[2] = 1e20f;
869                         max[0] = max[1] = max[2] = -1e20f;
870                         
871                         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
872                                 if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
873                                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
874                                                 DO_MINMAX(l->v->co, min, max);
875                                         }
876                                 }
877                         }
878                         mid_v3_v3v3(result, min, max);
879                         break;
880
881                 case V3D_CURSOR: /*cursor center*/ 
882                         cursx = give_cursor(scene, v3d);
883                         /* shift to objects world */
884                         result[0] = cursx[0] - ob->obmat[3][0];
885                         result[1] = cursx[1] - ob->obmat[3][1];
886                         result[2] = cursx[2] - ob->obmat[3][2];
887                         break;
888
889                 case V3D_LOCAL: /*object center*/
890                 case V3D_CENTROID: /* multiple objects centers, only one object here*/
891                 default:
892                         result[0] = result[1] = result[2] = 0.0;
893                         break;
894         }
895 }
896
897 static void uv_map_rotation_matrix(float result[][4], RegionView3D *rv3d, Object *ob,
898                                    float upangledeg, float sideangledeg, float radius)
899 {
900         float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
901         float sideangle = 0.0f, upangle = 0.0f;
902         int k;
903
904         /* get rotation of the current view matrix */
905         if (rv3d)
906                 copy_m4_m4(viewmatrix, rv3d->viewmat);
907         else
908                 unit_m4(viewmatrix);
909
910         /* but shifting */
911         for (k = 0; k < 4; k++)
912                 viewmatrix[3][k] = 0.0f;
913
914         /* get rotation of the current object matrix */
915         copy_m4_m4(rotobj, ob->obmat);
916
917         /* but shifting */
918         for (k = 0; k < 4; k++)
919                 rotobj[3][k] = 0.0f;
920
921         zero_m4(rotup);
922         zero_m4(rotside);
923
924         /* compensate front/side.. against opengl x,y,z world definition */
925         /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
926         /* i wanted to keep the reason here, so we're rotating*/
927         sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f;
928         rotside[0][0] = (float)cos(sideangle);
929         rotside[0][1] = -(float)sin(sideangle);
930         rotside[1][0] = (float)sin(sideangle);
931         rotside[1][1] = (float)cos(sideangle);
932         rotside[2][2] = 1.0f;
933
934         upangle = (float)M_PI * upangledeg / 180.0f;
935         rotup[1][1] = (float)cos(upangle) / radius;
936         rotup[1][2] = -(float)sin(upangle) / radius;
937         rotup[2][1] = (float)sin(upangle) / radius;
938         rotup[2][2] = (float)cos(upangle) / radius;
939         rotup[0][0] = (float)1.0f / radius;
940
941         /* calculate transforms*/
942         mul_serie_m4(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL);
943 }
944
945 static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float rotmat[4][4])
946 {
947         /* context checks are messy here, making it work in both 3d view and uv editor */
948         Scene *scene = CTX_data_scene(C);
949         Object *obedit = CTX_data_edit_object(C);
950         BMEditMesh *em = BMEdit_FromObject(obedit);
951         View3D *v3d = CTX_wm_view3d(C);
952         RegionView3D *rv3d = CTX_wm_region_view3d(C);
953         /* common operator properties */
954         int align = RNA_enum_get(op->ptr, "align");
955         int direction = RNA_enum_get(op->ptr, "direction");
956         float radius = RNA_struct_find_property(op->ptr, "radius") ? RNA_float_get(op->ptr, "radius") : 1.0f;
957         float upangledeg, sideangledeg;
958
959         uv_map_transform_center(scene, v3d, center, obedit, em);
960
961         if (direction == VIEW_ON_EQUATOR) {
962                 upangledeg = 90.0f;
963                 sideangledeg = 0.0f;
964         }
965         else {
966                 upangledeg = 0.0f;
967                 if (align == POLAR_ZY) sideangledeg = 0.0f;
968                 else sideangledeg = 90.0f;
969         }
970
971         /* be compatible to the "old" sphere/cylinder mode */
972         if (direction == ALIGN_TO_OBJECT)
973                 unit_m4(rotmat);
974         else 
975                 uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
976
977 }
978
979 static void uv_transform_properties(wmOperatorType *ot, int radius)
980 {
981         static EnumPropertyItem direction_items[] = {
982                 {VIEW_ON_EQUATOR, "VIEW_ON_EQUATOR", 0, "View on Equator", "3D view is on the equator"},
983                 {VIEW_ON_POLES, "VIEW_ON_POLES", 0, "View on Poles", "3D view is on the poles"},
984                 {ALIGN_TO_OBJECT, "ALIGN_TO_OBJECT", 0, "Align to Object", "Align according to object transform"},
985                 {0, NULL, 0, NULL, NULL}
986         };
987         static EnumPropertyItem align_items[] = {
988                 {POLAR_ZX, "POLAR_ZX", 0, "Polar ZX", "Polar 0 is X"},
989                 {POLAR_ZY, "POLAR_ZY", 0, "Polar ZY", "Polar 0 is Y"},
990                 {0, NULL, 0, NULL, NULL}
991         };
992
993         RNA_def_enum(ot->srna, "direction", direction_items, VIEW_ON_EQUATOR, "Direction",
994                      "Direction of the sphere or cylinder");
995         RNA_def_enum(ot->srna, "align", align_items, VIEW_ON_EQUATOR, "Align",
996                      "How to determine rotation around the pole");
997         if (radius)
998                 RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius",
999                               "Radius of the sphere or cylinder", 0.0001f, 100.0f);
1000 }
1001
1002 static void correct_uv_aspect(BMEditMesh *em)
1003 {
1004         BMFace *efa = BM_active_face_get(em->bm, TRUE);
1005         BMLoop *l;
1006         BMIter iter, liter;
1007         MLoopUV *luv;
1008         float scale, aspx = 1.0f, aspy = 1.0f;
1009         
1010         if (efa) {
1011                 MTexPoly *tf;
1012
1013                 tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1014                 ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
1015         }
1016         
1017         if (aspx == aspy)
1018                 return;
1019                 
1020         if (aspx > aspy) {
1021                 scale = aspy / aspx;
1022
1023                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1024                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
1025                                 continue;
1026                         
1027                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1028                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1029                                 luv->uv[0] = ((luv->uv[0] - 0.5) * scale) + 0.5;
1030                         }
1031                 }
1032         }
1033         else {
1034                 scale = aspx / aspy;
1035
1036                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1037                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
1038                                 continue;
1039                         
1040                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1041                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1042                                 luv->uv[1] = ((luv->uv[1] - 0.5) * scale) + 0.5;
1043                         }
1044                 }
1045         }
1046 }
1047
1048 /******************** Map Clip & Correct ******************/
1049
1050 static void uv_map_clip_correct_properties(wmOperatorType *ot)
1051 {
1052         RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
1053                         "Map UVs taking image aspect ratio into account");
1054         RNA_def_boolean(ot->srna, "clip_to_bounds", 0, "Clip to Bounds",
1055                         "Clip UV coordinates to bounds after unwrapping");
1056         RNA_def_boolean(ot->srna, "scale_to_bounds", 0, "Scale to Bounds",
1057                         "Scale UV coordinates to bounds after unwrapping");
1058 }
1059
1060 static void uv_map_clip_correct(BMEditMesh *em, wmOperator *op)
1061 {
1062         BMFace *efa;
1063         BMLoop *l;
1064         BMIter iter, liter;
1065         MLoopUV *luv;
1066         float dx, dy, min[2], max[2];
1067         int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
1068         int clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds");
1069         int scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds");
1070
1071         /* correct for image aspect ratio */
1072         if (correct_aspect)
1073                 correct_uv_aspect(em);
1074
1075         if (scale_to_bounds) {
1076                 INIT_MINMAX2(min, max);
1077                 
1078                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1079                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1080                                 continue;
1081
1082                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1083                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1084                                 DO_MINMAX2(luv->uv, min, max);
1085                         }
1086                 }
1087                 
1088                 /* rescale UV to be in 1/1 */
1089                 dx = (max[0] - min[0]);
1090                 dy = (max[1] - min[1]);
1091
1092                 if (dx > 0.0f)
1093                         dx = 1.0f / dx;
1094                 if (dy > 0.0f)
1095                         dy = 1.0f / dy;
1096
1097                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1098                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1099                                 continue;
1100
1101                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1102                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1103                                 
1104                                 luv->uv[0] = (luv->uv[0] - min[0]) * dx;
1105                                 luv->uv[1] = (luv->uv[1] - min[1]) * dy;
1106                         }
1107                 }
1108         }
1109         else if (clip_to_bounds) {
1110                 /* clipping and wrapping */
1111                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1112                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1113                                 continue;
1114
1115                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1116                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1117                                 CLAMP(luv->uv[0], 0.0f, 1.0f);
1118                                 CLAMP(luv->uv[1], 0.0f, 1.0f);
1119                         }
1120                 }
1121         }
1122 }
1123
1124 /* ******************** Unwrap operator **************** */
1125
1126 /* assumes UV Map is checked, doesn't run update funcs */
1127 void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
1128 {
1129         BMEditMesh *em = BMEdit_FromObject(obedit);
1130         ParamHandle *handle;
1131
1132         const short fill_holes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
1133         const short correct_aspect = !(scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT);
1134         const short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
1135
1136         if (use_subsurf)
1137                 handle = construct_param_handle_subsurfed(scene, em, fill_holes, sel, correct_aspect);
1138         else
1139                 handle = construct_param_handle(scene, em, 0, fill_holes, sel, correct_aspect);
1140
1141         param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
1142         param_lscm_solve(handle);
1143         param_lscm_end(handle);
1144
1145         param_pack(handle, scene->toolsettings->uvcalc_margin);
1146
1147         param_flush(handle);
1148
1149         param_delete(handle);
1150 }
1151
1152 static int unwrap_exec(bContext *C, wmOperator *op)
1153 {
1154         Scene *scene = CTX_data_scene(C);
1155         Object *obedit = CTX_data_edit_object(C);
1156         BMEditMesh *em = BMEdit_FromObject(obedit);
1157         int method = RNA_enum_get(op->ptr, "method");
1158         int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
1159         int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
1160         int use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
1161         int subsurf_level = RNA_int_get(op->ptr, "uv_subsurf_level");
1162         float obsize[3], unitsize[3] = {1.0f, 1.0f, 1.0f};
1163         short implicit = 0;
1164
1165         if (!uvedit_have_selection(scene, em, implicit)) {
1166                 return OPERATOR_CANCELLED;
1167         }
1168         
1169         /* add uvs if they don't exist yet */
1170         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1171                 return OPERATOR_CANCELLED;
1172         }
1173
1174         mat4_to_size(obsize, obedit->obmat);
1175         if (!compare_v3v3(obsize, unitsize, 1e-4f))
1176                 BKE_report(op->reports, RPT_INFO, "Object scale is not 1.0. Unwrap will operate on a non-scaled version of the mesh.");
1177
1178         /* remember last method for live unwrap */
1179         scene->toolsettings->unwrapper = method;
1180         
1181         scene->toolsettings->uv_subsurf_level = subsurf_level;
1182
1183         if (fill_holes) scene->toolsettings->uvcalc_flag |=  UVCALC_FILLHOLES;
1184         else scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES;
1185
1186         if (correct_aspect) scene->toolsettings->uvcalc_flag &= ~UVCALC_NO_ASPECT_CORRECT;
1187         else scene->toolsettings->uvcalc_flag |=  UVCALC_NO_ASPECT_CORRECT;
1188
1189         if (use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
1190         else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
1191
1192         /* execute unwrap */
1193         ED_unwrap_lscm(scene, obedit, TRUE);
1194
1195         DAG_id_tag_update(obedit->data, 0);
1196         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1197
1198         return OPERATOR_FINISHED;
1199 }
1200
1201 void UV_OT_unwrap(wmOperatorType *ot)
1202 {
1203         static EnumPropertyItem method_items[] = {
1204                 {0, "ANGLE_BASED", 0, "Angle Based", ""},
1205                 {1, "CONFORMAL", 0, "Conformal", ""},
1206                 {0, NULL, 0, NULL, NULL}};
1207
1208         /* identifiers */
1209         ot->name = "Unwrap";
1210         ot->description = "Unwrap the mesh of the object being edited";
1211         ot->idname = "UV_OT_unwrap";
1212         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1213         
1214         /* api callbacks */
1215         ot->exec = unwrap_exec;
1216         ot->poll = ED_operator_uvmap;
1217
1218         /* properties */
1219         RNA_def_enum(ot->srna, "method", method_items, 0, "Method",
1220                      "Unwrapping method (Angle Based usually gives better results than Conformal, while being somewhat slower)");
1221         RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes",
1222                         "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
1223         RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
1224                         "Map UVs taking image aspect ratio into account");
1225         RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Data",
1226                         "Map UVs taking vertex position after subsurf into account");
1227         RNA_def_int(ot->srna, "uv_subsurf_level", 1, 1, 6, "SubSurf Target",
1228                     "Number of times to subdivide before calculating UVs", 1, 6);
1229 }
1230
1231 /**************** Project From View operator **************/
1232 static int uv_from_view_exec(bContext *C, wmOperator *op)
1233 {
1234         Scene *scene = CTX_data_scene(C);
1235         Object *obedit = CTX_data_edit_object(C);
1236         Camera *camera = NULL;
1237         BMEditMesh *em = BMEdit_FromObject(obedit);
1238         ARegion *ar = CTX_wm_region(C);
1239         View3D *v3d = CTX_wm_view3d(C);
1240         RegionView3D *rv3d = CTX_wm_region_view3d(C);
1241         BMFace *efa;
1242         BMLoop *l;
1243         BMIter iter, liter;
1244         MLoopUV *luv;
1245         float rotmat[4][4];
1246
1247         /* add uvs if they don't exist yet */
1248         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1249                 return OPERATOR_CANCELLED;
1250         }
1251
1252         /* establish the camera object, so we can default to view mapping if anything is wrong with it */
1253         if ((rv3d->persp == RV3D_CAMOB) && (v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
1254                 camera = v3d->camera->data;
1255         }
1256
1257         if (RNA_boolean_get(op->ptr, "orthographic")) {
1258                 uv_map_rotation_matrix(rotmat, rv3d, obedit, 90.0f, 0.0f, 1.0f);
1259                 
1260                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1261                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1262                                 continue;
1263
1264                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1265                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1266                                 project_from_view_ortho(luv->uv, l->v->co, rotmat);
1267                         }
1268                 }
1269         }
1270         else if (camera) {
1271                 struct UvCameraInfo *uci = project_camera_info(v3d->camera, obedit->obmat, scene->r.xsch, scene->r.ysch);
1272                 
1273                 if (uci) {
1274                         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1275                                 if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1276                                         continue;
1277
1278                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1279                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1280                                         project_from_camera(luv->uv, l->v->co, uci);
1281                                 }
1282                         }
1283                         
1284                         MEM_freeN(uci);
1285                 }
1286         }
1287         else {
1288                 copy_m4_m4(rotmat, obedit->obmat);
1289
1290                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1291                         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1292                                 continue;
1293
1294                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1295                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1296                                 project_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
1297                         }
1298                 }
1299         }
1300
1301         uv_map_clip_correct(em, op);
1302
1303         DAG_id_tag_update(obedit->data, 0);
1304         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1305
1306         return OPERATOR_FINISHED;
1307 }
1308
1309 static int uv_from_view_poll(bContext *C)
1310 {
1311         RegionView3D *rv3d = CTX_wm_region_view3d(C);
1312
1313         if (!ED_operator_uvmap(C))
1314                 return 0;
1315
1316         return (rv3d != NULL);
1317 }
1318
1319 void UV_OT_from_view(wmOperatorType *ot)
1320 {
1321         /* identifiers */
1322         ot->name = "Project From View";
1323         ot->idname = "UV_OT_project_from_view";
1324         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1325         
1326         /* api callbacks */
1327         ot->exec = uv_from_view_exec;
1328         ot->poll = uv_from_view_poll;
1329
1330         /* properties */
1331         RNA_def_boolean(ot->srna, "orthographic", 0, "Orthographic", "Use orthographic projection");
1332         uv_map_clip_correct_properties(ot);
1333 }
1334
1335 /********************** Reset operator ********************/
1336
1337 static int reset_exec(bContext *C, wmOperator *UNUSED(op))
1338 {
1339         Scene *scene = CTX_data_scene(C);
1340         Object *obedit = CTX_data_edit_object(C);
1341         Mesh *me = (Mesh *)obedit->data;
1342
1343         /* add uvs if they don't exist yet */
1344         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1345                 return OPERATOR_CANCELLED;
1346         }
1347
1348         if (!ED_mesh_uv_loop_reset(C, me)) {
1349                 return OPERATOR_CANCELLED;
1350         }
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 void UV_OT_reset(wmOperatorType *ot)
1359 {
1360         /* identifiers */
1361         ot->name = "Reset";
1362         ot->idname = "UV_OT_reset";
1363         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1364         
1365         /* api callbacks */
1366         ot->exec = reset_exec;
1367         ot->poll = ED_operator_uvmap;
1368 }
1369
1370 /****************** Sphere Project operator ***************/
1371
1372 static void uv_sphere_project(float target[2], float source[3], float center[3], float rotmat[4][4])
1373 {
1374         float pv[3];
1375
1376         sub_v3_v3v3(pv, source, center);
1377         mul_m4_v3(rotmat, pv);
1378
1379         map_to_sphere(&target[0], &target[1], pv[0], pv[1], pv[2]);
1380
1381         /* split line is always zero */
1382         if (target[0] >= 1.0f)
1383                 target[0] -= 1.0f;  
1384 }
1385
1386 static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf))
1387 {
1388         BMLoop *l;
1389         BMIter liter;
1390         MLoopUV *luv;
1391         float **uvs = NULL;
1392         BLI_array_fixedstack_declare(uvs, BM_NGON_STACK_SIZE, efa->len, __func__);
1393         float dx;
1394         int i, mi;
1395
1396         i = 0;
1397         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1398                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1399                 uvs[i] = luv->uv;
1400                 i++;
1401         }
1402
1403         mi = 0;
1404         for (i = 1; i < efa->len; i++)
1405                 if (uvs[i][0] > uvs[mi][0])
1406                         mi = i;
1407
1408         for (i = 0; i < efa->len; i++) {
1409                 if (i != mi) {
1410                         dx = uvs[mi][0] - uvs[i][0];
1411                         if (dx > 0.5f) uvs[i][0] += 1.0f;
1412                 } 
1413         } 
1414
1415         BLI_array_fixedstack_free(uvs);
1416 }
1417
1418 static int sphere_project_exec(bContext *C, wmOperator *op)
1419 {
1420         Scene *scene = CTX_data_scene(C);
1421         Object *obedit = CTX_data_edit_object(C);
1422         BMEditMesh *em = BMEdit_FromObject(obedit);
1423         BMFace *efa;
1424         BMLoop *l;
1425         BMIter iter, liter;
1426         MTexPoly *tf;
1427         MLoopUV *luv;
1428         float center[3], rotmat[4][4];
1429
1430         /* add uvs if they don't exist yet */
1431         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1432                 return OPERATOR_CANCELLED;
1433         }
1434
1435         uv_map_transform(C, op, center, rotmat);
1436
1437         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1438                 if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1439                         continue;
1440
1441                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1442                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1443
1444                         uv_sphere_project(luv->uv, l->v->co, center, rotmat);
1445                 }
1446
1447                 tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1448                 uv_map_mirror(em, efa, tf);
1449         }
1450
1451         uv_map_clip_correct(em, op);
1452
1453         DAG_id_tag_update(obedit->data, 0);
1454         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1455
1456         return OPERATOR_FINISHED;
1457 }
1458
1459 void UV_OT_sphere_project(wmOperatorType *ot)
1460 {
1461         /* identifiers */
1462         ot->name = "Sphere Projection";
1463         ot->idname = "UV_OT_sphere_project";
1464         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1465         
1466         /* api callbacks */
1467         ot->exec = sphere_project_exec;
1468         ot->poll = ED_operator_uvmap;
1469
1470         /* properties */
1471         uv_transform_properties(ot, 0);
1472         uv_map_clip_correct_properties(ot);
1473 }
1474
1475 /***************** Cylinder Project operator **************/
1476
1477 static void uv_cylinder_project(float target[2], float source[3], float center[3], float rotmat[4][4])
1478 {
1479         float pv[3];
1480
1481         sub_v3_v3v3(pv, source, center);
1482         mul_m4_v3(rotmat, pv);
1483
1484         map_to_tube(&target[0], &target[1], pv[0], pv[1], pv[2]);
1485
1486         /* split line is always zero */
1487         if (target[0] >= 1.0f)
1488                 target[0] -= 1.0f;  
1489 }
1490
1491 static int cylinder_project_exec(bContext *C, wmOperator *op)
1492 {
1493         Scene *scene = CTX_data_scene(C);
1494         Object *obedit = CTX_data_edit_object(C);
1495         BMEditMesh *em = BMEdit_FromObject(obedit);
1496         BMFace *efa;
1497         BMLoop *l;
1498         BMIter iter, liter;
1499         MTexPoly *tf;
1500         MLoopUV *luv;
1501         float center[3], rotmat[4][4];
1502
1503         /* add uvs if they don't exist yet */
1504         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1505                 return OPERATOR_CANCELLED;
1506         }
1507
1508         uv_map_transform(C, op, center, rotmat);
1509
1510         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1511                 tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1512                 if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1513                         continue;
1514                 
1515                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1516                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1517
1518                         uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
1519                 }
1520
1521                 uv_map_mirror(em, efa, tf);
1522         }
1523
1524         uv_map_clip_correct(em, op);
1525
1526         DAG_id_tag_update(obedit->data, 0);
1527         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1528
1529         return OPERATOR_FINISHED;
1530 }
1531
1532 void UV_OT_cylinder_project(wmOperatorType *ot)
1533 {
1534         /* identifiers */
1535         ot->name = "Cylinder Projection";
1536         ot->idname = "UV_OT_cylinder_project";
1537         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1538         
1539         /* api callbacks */
1540         ot->exec = cylinder_project_exec;
1541         ot->poll = ED_operator_uvmap;
1542
1543         /* properties */
1544         uv_transform_properties(ot, 1);
1545         uv_map_clip_correct_properties(ot);
1546 }
1547
1548 /******************* Cube Project operator ****************/
1549
1550 static int cube_project_exec(bContext *C, wmOperator *op)
1551 {
1552         Scene *scene = CTX_data_scene(C);
1553         Object *obedit = CTX_data_edit_object(C);
1554         BMEditMesh *em = BMEdit_FromObject(obedit);
1555         BMFace *efa;
1556         BMLoop *l;
1557         BMIter iter, liter;
1558         /* MTexPoly *tf; */ /* UNUSED */
1559         MLoopUV *luv;
1560         float cube_size, *loc, dx, dy;
1561         int cox, coy;
1562
1563         /* add uvs if they don't exist yet */
1564         if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1565                 return OPERATOR_CANCELLED;
1566         }
1567
1568         loc = obedit->obmat[3];
1569         cube_size = RNA_float_get(op->ptr, "cube_size");
1570
1571         /* choose x,y,z axis for projection depending on the largest normal
1572         * component, but clusters all together around the center of map. */
1573
1574         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1575                 int first = 1;
1576
1577                 /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
1578                 if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1579                         continue;
1580
1581                 axis_dominant_v3(&cox, &coy, efa->no);
1582
1583                 dx = dy = 0;
1584                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
1585                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1586
1587                         luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]);
1588                         luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]);
1589                         
1590                         if (first) {
1591                                 dx = floor(luv->uv[0]);
1592                                 dy = floor(luv->uv[1]);
1593                                 first = 0;
1594                         }
1595                         
1596
1597                         luv->uv[0] -= dx;
1598                         luv->uv[1] -= dy;
1599                 }
1600         }
1601
1602         uv_map_clip_correct(em, op);
1603
1604         DAG_id_tag_update(obedit->data, 0);
1605         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1606
1607         return OPERATOR_FINISHED;
1608 }
1609
1610 void UV_OT_cube_project(wmOperatorType *ot)
1611 {
1612         /* identifiers */
1613         ot->name = "Cube Projection";
1614         ot->idname = "UV_OT_cube_project";
1615         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1616         
1617         /* api callbacks */
1618         ot->exec = cube_project_exec;
1619         ot->poll = ED_operator_uvmap;
1620
1621         /* properties */
1622         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);
1623         uv_map_clip_correct_properties(ot);
1624 }