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