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