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