Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / uvedit / uvedit_unwrap_ops.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup eduv
22  */
23
24 #include <string.h>
25 #include <stdlib.h>
26 #include <math.h>
27
28 #include "MEM_guardedalloc.h"
29
30 #include "DNA_camera_types.h"
31 #include "DNA_mesh_types.h"
32 #include "DNA_meshdata_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_modifier_types.h"
36
37 #include "BLI_utildefines.h"
38 #include "BLI_alloca.h"
39 #include "BLI_math.h"
40 #include "BLI_uvproject.h"
41 #include "BLI_string.h"
42
43 #include "BLT_translation.h"
44
45 #include "BKE_cdderivedmesh.h"
46 #include "BKE_subsurf.h"
47 #include "BKE_context.h"
48 #include "BKE_customdata.h"
49 #include "BKE_image.h"
50 #include "BKE_main.h"
51 #include "BKE_material.h"
52 #include "BKE_report.h"
53 #include "BKE_scene.h"
54 #include "BKE_editmesh.h"
55 #include "BKE_layer.h"
56
57 #include "DEG_depsgraph.h"
58
59 #include "PIL_time.h"
60
61 #include "UI_interface.h"
62
63 #include "ED_image.h"
64 #include "ED_mesh.h"
65 #include "ED_screen.h"
66 #include "ED_uvedit.h"
67 #include "ED_view3d.h"
68
69 #include "RNA_access.h"
70 #include "RNA_define.h"
71
72 #include "WM_api.h"
73 #include "WM_types.h"
74
75 #include "uvedit_intern.h"
76 #include "uvedit_parametrizer.h"
77
78 static void modifier_unwrap_state(Object *obedit, Scene *scene, bool *r_use_subsurf)
79 {
80   ModifierData *md;
81   bool subsurf = (scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF) != 0;
82
83   md = obedit->modifiers.first;
84
85   /* subsurf will take the modifier settings only if modifier is first or right after mirror */
86   if (subsurf) {
87     if (md && md->type == eModifierType_Subsurf) {
88       subsurf = true;
89     }
90     else {
91       subsurf = false;
92     }
93   }
94
95   *r_use_subsurf = subsurf;
96 }
97
98 static bool ED_uvedit_ensure_uvs(bContext *C, Scene *UNUSED(scene), Object *obedit)
99 {
100   BMEditMesh *em = BKE_editmesh_from_object(obedit);
101   BMFace *efa;
102   BMIter iter;
103   Image *ima;
104   bScreen *sc;
105   ScrArea *sa;
106   SpaceLink *slink;
107   SpaceImage *sima;
108   int cd_loop_uv_offset;
109
110   if (ED_uvedit_test(obedit)) {
111     return 1;
112   }
113
114   if (em && em->bm->totface && !CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
115     ED_mesh_uv_texture_add(obedit->data, NULL, true, true);
116   }
117
118   if (!ED_uvedit_test(obedit)) {
119     return 0;
120   }
121
122   cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
123
124   ima = CTX_data_edit_image(C);
125
126   if (!ima) {
127     /* no image in context in the 3d view, we find first image window .. */
128     sc = CTX_wm_screen(C);
129
130     for (sa = sc->areabase.first; sa; sa = sa->next) {
131       slink = sa->spacedata.first;
132       if (slink->spacetype == SPACE_IMAGE) {
133         sima = (SpaceImage *)slink;
134
135         ima = sima->image;
136         if (ima) {
137           if (ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE) {
138             ima = NULL;
139           }
140           else {
141             break;
142           }
143         }
144       }
145     }
146   }
147
148   /* select new UV's (ignore UV_SYNC_SELECTION in this case) */
149   BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
150     BMIter liter;
151     BMLoop *l;
152
153     BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
154       MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
155       luv->flag |= MLOOPUV_VERTSEL;
156     }
157   }
158
159   return 1;
160 }
161
162 /****************** Parametrizer Conversion ***************/
163
164 typedef struct UnwrapOptions {
165   bool topology_from_uvs; /* Connectivity based on UV coordinates instead of seams. */
166   bool only_selected;     /* Only affect selected faces. */
167   bool fill_holes;        /* Fill holes to better preserve shape. */
168   bool correct_aspect;    /* Correct for mapped image texture aspect ratio. */
169 } UnwrapOptions;
170
171 static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, const UnwrapOptions *options)
172 {
173   BMFace *efa;
174   BMLoop *l;
175   BMIter iter, liter;
176   const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
177
178   if (cd_loop_uv_offset == -1) {
179     return (em->bm->totfacesel != 0);
180   }
181
182   /* verify if we have any selected uv's before unwrapping,
183    * so we can cancel the operator early */
184   BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
185     if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
186       if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
187         continue;
188       }
189     }
190     else if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
191       continue;
192     }
193
194     BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
195       if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
196         break;
197       }
198     }
199
200     if (options->topology_from_uvs && !l) {
201       continue;
202     }
203
204     return true;
205   }
206
207   return false;
208 }
209
210 static bool uvedit_have_selection_multi(Scene *scene,
211                                         Object **objects,
212                                         const uint objects_len,
213                                         const UnwrapOptions *options)
214 {
215   bool have_select = false;
216   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
217     Object *obedit = objects[ob_index];
218     BMEditMesh *em = BKE_editmesh_from_object(obedit);
219     if (uvedit_have_selection(scene, em, options)) {
220       have_select = true;
221       break;
222     }
223   }
224   return have_select;
225 }
226
227 void ED_uvedit_get_aspect(Scene *UNUSED(scene), Object *ob, BMesh *bm, float *aspx, float *aspy)
228 {
229   bool sloppy = true;
230   bool selected = false;
231   BMFace *efa;
232   Image *ima;
233
234   efa = BM_mesh_active_face_get(bm, sloppy, selected);
235
236   if (efa) {
237     ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL);
238
239     ED_image_get_uv_aspect(ima, NULL, aspx, aspy);
240   }
241   else {
242     *aspx = 1.0f;
243     *aspy = 1.0f;
244   }
245 }
246
247 static void construct_param_handle_face_add(
248     ParamHandle *handle, Scene *scene, BMFace *efa, int face_index, const int cd_loop_uv_offset)
249 {
250   ParamKey key;
251   ParamKey *vkeys = BLI_array_alloca(vkeys, efa->len);
252   ParamBool *pin = BLI_array_alloca(pin, efa->len);
253   ParamBool *select = BLI_array_alloca(select, efa->len);
254   float **co = BLI_array_alloca(co, efa->len);
255   float **uv = BLI_array_alloca(uv, efa->len);
256   int i;
257
258   BMIter liter;
259   BMLoop *l;
260
261   key = (ParamKey)face_index;
262
263   /* let parametrizer split the ngon, it can make better decisions
264    * about which split is best for unwrapping than scanfill */
265   BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
266     MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
267
268     vkeys[i] = (ParamKey)BM_elem_index_get(l->v);
269     co[i] = l->v->co;
270     uv[i] = luv->uv;
271     pin[i] = (luv->flag & MLOOPUV_PINNED) != 0;
272     select[i] = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
273   }
274
275   param_face_add(handle, key, i, vkeys, co, uv, pin, select);
276 }
277
278 /* See: construct_param_handle_multi to handle multiple objects at once. */
279 static ParamHandle *construct_param_handle(Scene *scene,
280                                            Object *ob,
281                                            BMesh *bm,
282                                            const UnwrapOptions *options)
283 {
284   ParamHandle *handle;
285   BMFace *efa;
286   BMLoop *l;
287   BMEdge *eed;
288   BMIter iter, liter;
289   int i;
290
291   const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
292
293   handle = param_construct_begin();
294
295   if (options->correct_aspect) {
296     float aspx, aspy;
297
298     ED_uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
299
300     if (aspx != aspy) {
301       param_aspect_ratio(handle, aspx, aspy);
302     }
303   }
304
305   /* we need the vert indices */
306   BM_mesh_elem_index_ensure(bm, BM_VERT);
307
308   BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
309
310     if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
311         (options->only_selected && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) {
312       continue;
313     }
314
315     if (options->topology_from_uvs) {
316       bool is_loopsel = false;
317
318       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
319         if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
320           is_loopsel = true;
321           break;
322         }
323       }
324       if (is_loopsel == false) {
325         continue;
326       }
327     }
328
329     construct_param_handle_face_add(handle, scene, efa, i, cd_loop_uv_offset);
330   }
331
332   if (!options->topology_from_uvs) {
333     BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
334       if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
335         ParamKey vkeys[2];
336         vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
337         vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
338         param_edge_set_seam(handle, vkeys);
339       }
340     }
341   }
342
343   param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
344
345   return handle;
346 }
347
348 /**
349  * Version of #construct_param_handle_single that handles multiple objects.
350  */
351 static ParamHandle *construct_param_handle_multi(Scene *scene,
352                                                  Object **objects,
353                                                  const uint objects_len,
354                                                  const UnwrapOptions *options)
355 {
356   ParamHandle *handle;
357   BMFace *efa;
358   BMLoop *l;
359   BMEdge *eed;
360   BMIter iter, liter;
361   int i;
362
363   handle = param_construct_begin();
364
365   if (options->correct_aspect) {
366     Object *ob = objects[0];
367     BMEditMesh *em = BKE_editmesh_from_object(ob);
368     BMesh *bm = em->bm;
369     float aspx, aspy;
370
371     ED_uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
372     if (aspx != aspy) {
373       param_aspect_ratio(handle, aspx, aspy);
374     }
375   }
376
377   /* we need the vert indices */
378   EDBM_mesh_elem_index_ensure_multi(objects, objects_len, BM_VERT);
379
380   int offset = 0;
381
382   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
383     Object *obedit = objects[ob_index];
384     BMEditMesh *em = BKE_editmesh_from_object(obedit);
385     BMesh *bm = em->bm;
386
387     const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
388
389     BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
390
391       if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
392           (options->only_selected && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) {
393         continue;
394       }
395
396       if (options->topology_from_uvs) {
397         bool is_loopsel = false;
398
399         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
400           if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
401             is_loopsel = true;
402             break;
403           }
404         }
405         if (is_loopsel == false) {
406           continue;
407         }
408       }
409
410       construct_param_handle_face_add(handle, scene, efa, i + offset, cd_loop_uv_offset);
411     }
412
413     if (!options->topology_from_uvs) {
414       BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
415         if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
416           ParamKey vkeys[2];
417           vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
418           vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
419           param_edge_set_seam(handle, vkeys);
420         }
421       }
422     }
423     offset += bm->totface;
424   }
425
426   param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
427
428   return handle;
429 }
430
431 static void texface_from_original_index(BMFace *efa,
432                                         int index,
433                                         float **uv,
434                                         ParamBool *pin,
435                                         ParamBool *select,
436                                         Scene *scene,
437                                         const int cd_loop_uv_offset)
438 {
439   BMLoop *l;
440   BMIter liter;
441   MLoopUV *luv;
442
443   *uv = NULL;
444   *pin = 0;
445   *select = 1;
446
447   if (index == ORIGINDEX_NONE) {
448     return;
449   }
450
451   BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
452     if (BM_elem_index_get(l->v) == index) {
453       luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
454       *uv = luv->uv;
455       *pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0;
456       *select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
457       break;
458     }
459   }
460 }
461
462 /**
463  * Unwrap handle initialization for subsurf aware-unwrapper.
464  * The many modifications required to make the original function(see above)
465  * work justified the existence of a new function.
466  */
467 static ParamHandle *construct_param_handle_subsurfed(Scene *scene,
468                                                      Object *ob,
469                                                      BMEditMesh *em,
470                                                      const UnwrapOptions *options)
471 {
472   ParamHandle *handle;
473   /* index pointers */
474   MPoly *mpoly;
475   MLoop *mloop;
476   MEdge *edge;
477   int i;
478
479   /* pointers to modifier data for unwrap control */
480   ModifierData *md;
481   SubsurfModifierData *smd_real;
482   /* modifier initialization data, will  control what type of subdivision will happen*/
483   SubsurfModifierData smd = {{NULL}};
484   /* Used to hold subsurfed Mesh */
485   DerivedMesh *derivedMesh, *initialDerived;
486   /* holds original indices for subsurfed mesh */
487   const int *origVertIndices, *origEdgeIndices, *origPolyIndices;
488   /* Holds vertices of subsurfed mesh */
489   MVert *subsurfedVerts;
490   MEdge *subsurfedEdges;
491   MPoly *subsurfedPolys;
492   MLoop *subsurfedLoops;
493   /* number of vertices and faces for subsurfed mesh*/
494   int numOfEdges, numOfFaces;
495
496   /* holds a map to editfaces for every subsurfed MFace.
497    * These will be used to get hidden/ selected flags etc. */
498   BMFace **faceMap;
499   /* similar to the above, we need a way to map edges to their original ones */
500   BMEdge **edgeMap;
501
502   const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
503
504   handle = param_construct_begin();
505
506   if (options->correct_aspect) {
507     float aspx, aspy;
508
509     ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
510
511     if (aspx != aspy) {
512       param_aspect_ratio(handle, aspx, aspy);
513     }
514   }
515
516   /* number of subdivisions to perform */
517   md = ob->modifiers.first;
518   smd_real = (SubsurfModifierData *)md;
519
520   smd.levels = smd_real->levels;
521   smd.subdivType = smd_real->subdivType;
522
523   initialDerived = CDDM_from_editbmesh(em, false, false);
524   derivedMesh = subsurf_make_derived_from_derived(
525       initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE);
526
527   initialDerived->release(initialDerived);
528
529   /* get the derived data */
530   subsurfedVerts = derivedMesh->getVertArray(derivedMesh);
531   subsurfedEdges = derivedMesh->getEdgeArray(derivedMesh);
532   subsurfedPolys = derivedMesh->getPolyArray(derivedMesh);
533   subsurfedLoops = derivedMesh->getLoopArray(derivedMesh);
534
535   origVertIndices = derivedMesh->getVertDataArray(derivedMesh, CD_ORIGINDEX);
536   origEdgeIndices = derivedMesh->getEdgeDataArray(derivedMesh, CD_ORIGINDEX);
537   origPolyIndices = derivedMesh->getPolyDataArray(derivedMesh, CD_ORIGINDEX);
538
539   numOfEdges = derivedMesh->getNumEdges(derivedMesh);
540   numOfFaces = derivedMesh->getNumPolys(derivedMesh);
541
542   faceMap = MEM_mallocN(numOfFaces * sizeof(BMFace *), "unwrap_edit_face_map");
543
544   BM_mesh_elem_index_ensure(em->bm, BM_VERT);
545   BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_FACE);
546
547   /* map subsurfed faces to original editFaces */
548   for (i = 0; i < numOfFaces; i++) {
549     faceMap[i] = BM_face_at_index(em->bm, origPolyIndices[i]);
550   }
551
552   edgeMap = MEM_mallocN(numOfEdges * sizeof(BMEdge *), "unwrap_edit_edge_map");
553
554   /* map subsurfed edges to original editEdges */
555   for (i = 0; i < numOfEdges; i++) {
556     /* not all edges correspond to an old edge */
557     edgeMap[i] = (origEdgeIndices[i] != ORIGINDEX_NONE) ?
558                      BM_edge_at_index(em->bm, origEdgeIndices[i]) :
559                      NULL;
560   }
561
562   /* Prepare and feed faces to the solver */
563   for (i = 0, mpoly = subsurfedPolys; i < numOfFaces; i++, mpoly++) {
564     ParamKey key, vkeys[4];
565     ParamBool pin[4], select[4];
566     float *co[4];
567     float *uv[4];
568     BMFace *origFace = faceMap[i];
569
570     if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
571       if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN)) {
572         continue;
573       }
574     }
575     else {
576       if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN) ||
577           (options->only_selected && !BM_elem_flag_test(origFace, BM_ELEM_SELECT))) {
578         continue;
579       }
580     }
581
582     mloop = &subsurfedLoops[mpoly->loopstart];
583
584     /* We will not check for v4 here. Subsurfed mfaces always have 4 vertices. */
585     BLI_assert(mpoly->totloop == 4);
586     key = (ParamKey)i;
587     vkeys[0] = (ParamKey)mloop[0].v;
588     vkeys[1] = (ParamKey)mloop[1].v;
589     vkeys[2] = (ParamKey)mloop[2].v;
590     vkeys[3] = (ParamKey)mloop[3].v;
591
592     co[0] = subsurfedVerts[mloop[0].v].co;
593     co[1] = subsurfedVerts[mloop[1].v].co;
594     co[2] = subsurfedVerts[mloop[2].v].co;
595     co[3] = subsurfedVerts[mloop[3].v].co;
596
597     /* This is where all the magic is done.
598      * If the vertex exists in the, we pass the original uv pointer to the solver, thus
599      * flushing the solution to the edit mesh. */
600     texface_from_original_index(origFace,
601                                 origVertIndices[mloop[0].v],
602                                 &uv[0],
603                                 &pin[0],
604                                 &select[0],
605                                 scene,
606                                 cd_loop_uv_offset);
607     texface_from_original_index(origFace,
608                                 origVertIndices[mloop[1].v],
609                                 &uv[1],
610                                 &pin[1],
611                                 &select[1],
612                                 scene,
613                                 cd_loop_uv_offset);
614     texface_from_original_index(origFace,
615                                 origVertIndices[mloop[2].v],
616                                 &uv[2],
617                                 &pin[2],
618                                 &select[2],
619                                 scene,
620                                 cd_loop_uv_offset);
621     texface_from_original_index(origFace,
622                                 origVertIndices[mloop[3].v],
623                                 &uv[3],
624                                 &pin[3],
625                                 &select[3],
626                                 scene,
627                                 cd_loop_uv_offset);
628
629     param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
630   }
631
632   /* these are calculated from original mesh too */
633   for (edge = subsurfedEdges, i = 0; i < numOfEdges; i++, edge++) {
634     if ((edgeMap[i] != NULL) && BM_elem_flag_test(edgeMap[i], BM_ELEM_SEAM)) {
635       ParamKey vkeys[2];
636       vkeys[0] = (ParamKey)edge->v1;
637       vkeys[1] = (ParamKey)edge->v2;
638       param_edge_set_seam(handle, vkeys);
639     }
640   }
641
642   param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
643
644   /* cleanup */
645   MEM_freeN(faceMap);
646   MEM_freeN(edgeMap);
647   derivedMesh->release(derivedMesh);
648
649   return handle;
650 }
651
652 /* ******************** Minimize Stretch operator **************** */
653
654 typedef struct MinStretch {
655   Scene *scene;
656   Object **objects_edit;
657   uint objects_len;
658   ParamHandle *handle;
659   float blend;
660   double lasttime;
661   int i, iterations;
662   wmTimer *timer;
663 } MinStretch;
664
665 static bool minimize_stretch_init(bContext *C, wmOperator *op)
666 {
667   Scene *scene = CTX_data_scene(C);
668   ViewLayer *view_layer = CTX_data_view_layer(C);
669
670   const UnwrapOptions options = {
671       .topology_from_uvs = true,
672       .fill_holes = RNA_boolean_get(op->ptr, "fill_holes"),
673       .only_selected = true,
674       .correct_aspect = true,
675   };
676
677   uint objects_len = 0;
678   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
679       view_layer, CTX_wm_view3d(C), &objects_len);
680
681   if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
682     MEM_freeN(objects);
683     return false;
684   }
685
686   MinStretch *ms = MEM_callocN(sizeof(MinStretch), "MinStretch");
687   ms->scene = scene;
688   ms->objects_edit = objects;
689   ms->objects_len = objects_len;
690   ms->blend = RNA_float_get(op->ptr, "blend");
691   ms->iterations = RNA_int_get(op->ptr, "iterations");
692   ms->i = 0;
693   ms->handle = construct_param_handle_multi(scene, objects, objects_len, &options);
694   ms->lasttime = PIL_check_seconds_timer();
695
696   param_stretch_begin(ms->handle);
697   if (ms->blend != 0.0f) {
698     param_stretch_blend(ms->handle, ms->blend);
699   }
700
701   op->customdata = ms;
702
703   return true;
704 }
705
706 static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interactive)
707 {
708   MinStretch *ms = op->customdata;
709   ScrArea *sa = CTX_wm_area(C);
710   Scene *scene = CTX_data_scene(C);
711   ToolSettings *ts = scene->toolsettings;
712   const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
713
714   param_stretch_blend(ms->handle, ms->blend);
715   param_stretch_iter(ms->handle);
716
717   ms->i++;
718   RNA_int_set(op->ptr, "iterations", ms->i);
719
720   if (interactive && (PIL_check_seconds_timer() - ms->lasttime > 0.5)) {
721     char str[UI_MAX_DRAW_STR];
722
723     param_flush(ms->handle);
724
725     if (sa) {
726       BLI_snprintf(str, sizeof(str), IFACE_("Minimize Stretch. Blend %.2f"), ms->blend);
727       ED_area_status_text(sa, str);
728       ED_workspace_status_text(C, IFACE_("Press + and -, or scroll wheel to set blending"));
729     }
730
731     ms->lasttime = PIL_check_seconds_timer();
732
733     for (uint ob_index = 0; ob_index < ms->objects_len; ob_index++) {
734       Object *obedit = ms->objects_edit[ob_index];
735       BMEditMesh *em = BKE_editmesh_from_object(obedit);
736
737       if (synced_selection && (em->bm->totfacesel == 0)) {
738         continue;
739       }
740
741       DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
742       WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
743     }
744   }
745 }
746
747 static void minimize_stretch_exit(bContext *C, wmOperator *op, bool cancel)
748 {
749   MinStretch *ms = op->customdata;
750   ScrArea *sa = CTX_wm_area(C);
751   Scene *scene = CTX_data_scene(C);
752   ToolSettings *ts = scene->toolsettings;
753   const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
754
755   ED_area_status_text(sa, NULL);
756   ED_workspace_status_text(C, NULL);
757
758   if (ms->timer) {
759     WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ms->timer);
760   }
761
762   if (cancel) {
763     param_flush_restore(ms->handle);
764   }
765   else {
766     param_flush(ms->handle);
767   }
768
769   param_stretch_end(ms->handle);
770   param_delete(ms->handle);
771
772   for (uint ob_index = 0; ob_index < ms->objects_len; ob_index++) {
773     Object *obedit = ms->objects_edit[ob_index];
774     BMEditMesh *em = BKE_editmesh_from_object(obedit);
775
776     if (synced_selection && (em->bm->totfacesel == 0)) {
777       continue;
778     }
779
780     DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
781     WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
782   }
783
784   MEM_freeN(ms->objects_edit);
785   MEM_freeN(ms);
786   op->customdata = NULL;
787 }
788
789 static int minimize_stretch_exec(bContext *C, wmOperator *op)
790 {
791   int i, iterations;
792
793   if (!minimize_stretch_init(C, op)) {
794     return OPERATOR_CANCELLED;
795   }
796
797   iterations = RNA_int_get(op->ptr, "iterations");
798   for (i = 0; i < iterations; i++) {
799     minimize_stretch_iteration(C, op, false);
800   }
801   minimize_stretch_exit(C, op, false);
802
803   return OPERATOR_FINISHED;
804 }
805
806 static int minimize_stretch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
807 {
808   MinStretch *ms;
809
810   if (!minimize_stretch_init(C, op)) {
811     return OPERATOR_CANCELLED;
812   }
813
814   minimize_stretch_iteration(C, op, true);
815
816   ms = op->customdata;
817   WM_event_add_modal_handler(C, op);
818   ms->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
819
820   return OPERATOR_RUNNING_MODAL;
821 }
822
823 static int minimize_stretch_modal(bContext *C, wmOperator *op, const wmEvent *event)
824 {
825   MinStretch *ms = op->customdata;
826
827   switch (event->type) {
828     case ESCKEY:
829     case RIGHTMOUSE:
830       minimize_stretch_exit(C, op, true);
831       return OPERATOR_CANCELLED;
832     case RETKEY:
833     case PADENTER:
834     case LEFTMOUSE:
835       minimize_stretch_exit(C, op, false);
836       return OPERATOR_FINISHED;
837     case PADPLUSKEY:
838     case WHEELUPMOUSE:
839       if (event->val == KM_PRESS) {
840         if (ms->blend < 0.95f) {
841           ms->blend += 0.1f;
842           ms->lasttime = 0.0f;
843           RNA_float_set(op->ptr, "blend", ms->blend);
844           minimize_stretch_iteration(C, op, true);
845         }
846       }
847       break;
848     case PADMINUS:
849     case WHEELDOWNMOUSE:
850       if (event->val == KM_PRESS) {
851         if (ms->blend > 0.05f) {
852           ms->blend -= 0.1f;
853           ms->lasttime = 0.0f;
854           RNA_float_set(op->ptr, "blend", ms->blend);
855           minimize_stretch_iteration(C, op, true);
856         }
857       }
858       break;
859     case TIMER:
860       if (ms->timer == event->customdata) {
861         double start = PIL_check_seconds_timer();
862
863         do {
864           minimize_stretch_iteration(C, op, true);
865         } while (PIL_check_seconds_timer() - start < 0.01);
866       }
867       break;
868   }
869
870   if (ms->iterations && ms->i >= ms->iterations) {
871     minimize_stretch_exit(C, op, false);
872     return OPERATOR_FINISHED;
873   }
874
875   return OPERATOR_RUNNING_MODAL;
876 }
877
878 static void minimize_stretch_cancel(bContext *C, wmOperator *op)
879 {
880   minimize_stretch_exit(C, op, true);
881 }
882
883 void UV_OT_minimize_stretch(wmOperatorType *ot)
884 {
885   /* identifiers */
886   ot->name = "Minimize Stretch";
887   ot->idname = "UV_OT_minimize_stretch";
888   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
889   ot->description = "Reduce UV stretching by relaxing angles";
890
891   /* api callbacks */
892   ot->exec = minimize_stretch_exec;
893   ot->invoke = minimize_stretch_invoke;
894   ot->modal = minimize_stretch_modal;
895   ot->cancel = minimize_stretch_cancel;
896   ot->poll = ED_operator_uvedit;
897
898   /* properties */
899   RNA_def_boolean(ot->srna,
900                   "fill_holes",
901                   1,
902                   "Fill Holes",
903                   "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and "
904                   "preserve symmetry");
905   RNA_def_float_factor(ot->srna,
906                        "blend",
907                        0.0f,
908                        0.0f,
909                        1.0f,
910                        "Blend",
911                        "Blend factor between stretch minimized and original",
912                        0.0f,
913                        1.0f);
914   RNA_def_int(ot->srna,
915               "iterations",
916               0,
917               0,
918               INT_MAX,
919               "Iterations",
920               "Number of iterations to run, 0 is unlimited when run interactively",
921               0,
922               100);
923 }
924
925 /* ******************** Pack Islands operator **************** */
926
927 static void uvedit_pack_islands(Scene *scene, Object *ob, BMesh *bm)
928 {
929   const UnwrapOptions options = {
930       .topology_from_uvs = true,
931       .only_selected = false,
932       .fill_holes = false,
933       .correct_aspect = false,
934   };
935
936   bool rotate = true;
937   bool ignore_pinned = false;
938
939   ParamHandle *handle;
940   handle = construct_param_handle(scene, ob, bm, &options);
941   param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
942   param_flush(handle);
943   param_delete(handle);
944 }
945
946 static void uvedit_pack_islands_multi(Scene *scene,
947                                       Object **objects,
948                                       const uint objects_len,
949                                       const UnwrapOptions *options,
950                                       bool rotate,
951                                       bool ignore_pinned)
952 {
953   ParamHandle *handle;
954   handle = construct_param_handle_multi(scene, objects, objects_len, options);
955   param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
956   param_flush(handle);
957   param_delete(handle);
958
959   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
960     Object *obedit = objects[ob_index];
961     DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
962     WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
963   }
964 }
965
966 static int pack_islands_exec(bContext *C, wmOperator *op)
967 {
968   ViewLayer *view_layer = CTX_data_view_layer(C);
969   Scene *scene = CTX_data_scene(C);
970
971   const UnwrapOptions options = {
972       .topology_from_uvs = true,
973       .only_selected = true,
974       .fill_holes = false,
975       .correct_aspect = true,
976   };
977
978   bool rotate = RNA_boolean_get(op->ptr, "rotate");
979   bool ignore_pinned = false;
980
981   uint objects_len = 0;
982   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
983       view_layer, CTX_wm_view3d(C), &objects_len);
984
985   if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
986     MEM_freeN(objects);
987     return OPERATOR_CANCELLED;
988   }
989
990   if (RNA_struct_property_is_set(op->ptr, "margin")) {
991     scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
992   }
993   else {
994     RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
995   }
996
997   uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
998
999   MEM_freeN(objects);
1000
1001   return OPERATOR_FINISHED;
1002 }
1003
1004 void UV_OT_pack_islands(wmOperatorType *ot)
1005 {
1006   /* identifiers */
1007   ot->name = "Pack Islands";
1008   ot->idname = "UV_OT_pack_islands";
1009   ot->description = "Transform all islands so that they fill up the UV space as much as possible";
1010
1011   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1012
1013   /* api callbacks */
1014   ot->exec = pack_islands_exec;
1015   ot->poll = ED_operator_uvedit;
1016
1017   /* properties */
1018   RNA_def_boolean(ot->srna, "rotate", true, "Rotate", "Rotate islands for best fit");
1019   RNA_def_float_factor(
1020       ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
1021 }
1022
1023 /* ******************** Average Islands Scale operator **************** */
1024
1025 static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
1026 {
1027   Scene *scene = CTX_data_scene(C);
1028   ViewLayer *view_layer = CTX_data_view_layer(C);
1029   ToolSettings *ts = scene->toolsettings;
1030   const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
1031
1032   const UnwrapOptions options = {
1033       .topology_from_uvs = true,
1034       .only_selected = true,
1035       .fill_holes = false,
1036       .correct_aspect = true,
1037   };
1038
1039   uint objects_len = 0;
1040   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
1041       view_layer, CTX_wm_view3d(C), &objects_len);
1042
1043   if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
1044     MEM_freeN(objects);
1045     return OPERATOR_CANCELLED;
1046   }
1047
1048   ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, &options);
1049   param_average(handle, false);
1050   param_flush(handle);
1051   param_delete(handle);
1052
1053   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1054     Object *obedit = objects[ob_index];
1055     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1056
1057     if (synced_selection && (em->bm->totvertsel == 0)) {
1058       continue;
1059     }
1060
1061     DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
1062     WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1063   }
1064   MEM_freeN(objects);
1065   return OPERATOR_FINISHED;
1066 }
1067
1068 void UV_OT_average_islands_scale(wmOperatorType *ot)
1069 {
1070   /* identifiers */
1071   ot->name = "Average Islands Scale";
1072   ot->idname = "UV_OT_average_islands_scale";
1073   ot->description = "Average the size of separate UV islands, based on their area in 3D space";
1074
1075   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1076
1077   /* api callbacks */
1078   ot->exec = average_islands_scale_exec;
1079   ot->poll = ED_operator_uvedit;
1080 }
1081
1082 /**************** Live Unwrap *****************/
1083
1084 static struct {
1085   ParamHandle **handles;
1086   uint len, len_alloc;
1087 } g_live_unwrap = {NULL};
1088
1089 void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
1090 {
1091   ParamHandle *handle = NULL;
1092   BMEditMesh *em = BKE_editmesh_from_object(obedit);
1093   const bool abf = (scene->toolsettings->unwrapper == 0);
1094   bool use_subsurf;
1095
1096   modifier_unwrap_state(obedit, scene, &use_subsurf);
1097
1098   if (!ED_uvedit_test(obedit)) {
1099     return;
1100   }
1101
1102   const UnwrapOptions options = {
1103       .topology_from_uvs = false,
1104       .only_selected = false,
1105       .fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0,
1106       .correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0,
1107   };
1108
1109   if (use_subsurf) {
1110     handle = construct_param_handle_subsurfed(scene, obedit, em, &options);
1111   }
1112   else {
1113     handle = construct_param_handle(scene, obedit, em->bm, &options);
1114   }
1115
1116   param_lscm_begin(handle, PARAM_TRUE, abf);
1117
1118   /* Create or increase size of g_live_unwrap.handles array */
1119   if (g_live_unwrap.handles == NULL) {
1120     g_live_unwrap.len_alloc = 32;
1121     g_live_unwrap.handles = MEM_mallocN(sizeof(ParamHandle *) * g_live_unwrap.len_alloc,
1122                                         "uvedit_live_unwrap_liveHandles");
1123     g_live_unwrap.len = 0;
1124   }
1125   if (g_live_unwrap.len >= g_live_unwrap.len_alloc) {
1126     g_live_unwrap.len_alloc *= 2;
1127     g_live_unwrap.handles = MEM_reallocN(g_live_unwrap.handles,
1128                                          sizeof(ParamHandle *) * g_live_unwrap.len_alloc);
1129   }
1130   g_live_unwrap.handles[g_live_unwrap.len] = handle;
1131   g_live_unwrap.len++;
1132 }
1133
1134 void ED_uvedit_live_unwrap_re_solve(void)
1135 {
1136   if (g_live_unwrap.handles) {
1137     for (int i = 0; i < g_live_unwrap.len; i++) {
1138       param_lscm_solve(g_live_unwrap.handles[i]);
1139       param_flush(g_live_unwrap.handles[i]);
1140     }
1141   }
1142 }
1143
1144 void ED_uvedit_live_unwrap_end(short cancel)
1145 {
1146   if (g_live_unwrap.handles) {
1147     for (int i = 0; i < g_live_unwrap.len; i++) {
1148       param_lscm_end(g_live_unwrap.handles[i]);
1149       if (cancel) {
1150         param_flush_restore(g_live_unwrap.handles[i]);
1151       }
1152       param_delete(g_live_unwrap.handles[i]);
1153     }
1154     MEM_freeN(g_live_unwrap.handles);
1155     g_live_unwrap.handles = NULL;
1156     g_live_unwrap.len = 0;
1157     g_live_unwrap.len_alloc = 0;
1158   }
1159 }
1160
1161 /*************** UV Map Common Transforms *****************/
1162
1163 #define VIEW_ON_EQUATOR 0
1164 #define VIEW_ON_POLES 1
1165 #define ALIGN_TO_OBJECT 2
1166
1167 #define POLAR_ZX 0
1168 #define POLAR_ZY 1
1169
1170 static void uv_map_transform_calc_bounds(BMEditMesh *em, float r_min[3], float r_max[3])
1171 {
1172   BMFace *efa;
1173   BMIter iter;
1174   INIT_MINMAX(r_min, r_max);
1175   BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1176     if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1177       BM_face_calc_bounds_expand(efa, r_min, r_max);
1178     }
1179   }
1180 }
1181
1182 static void uv_map_transform_calc_center_median(BMEditMesh *em, float r_center[3])
1183 {
1184   BMFace *efa;
1185   BMIter iter;
1186   uint center_accum_num = 0;
1187   zero_v3(r_center);
1188   BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1189     if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1190       float center[3];
1191       BM_face_calc_center_median(efa, center);
1192       add_v3_v3(r_center, center);
1193       center_accum_num += 1;
1194     }
1195   }
1196   mul_v3_fl(r_center, 1.0f / (float)center_accum_num);
1197 }
1198
1199 static void uv_map_transform_center(
1200     Scene *scene, View3D *v3d, Object *ob, BMEditMesh *em, float r_center[3], float r_bounds[2][3])
1201 {
1202   /* only operates on the edit object - this is all that's needed now */
1203   const int around = (v3d) ? scene->toolsettings->transform_pivot_point : V3D_AROUND_CENTER_BOUNDS;
1204
1205   float bounds[2][3];
1206   INIT_MINMAX(bounds[0], bounds[1]);
1207   bool is_minmax_set = false;
1208
1209   switch (around) {
1210     case V3D_AROUND_CENTER_BOUNDS: /* bounding box center */
1211     {
1212       uv_map_transform_calc_bounds(em, bounds[0], bounds[1]);
1213       is_minmax_set = true;
1214       mid_v3_v3v3(r_center, bounds[0], bounds[1]);
1215       break;
1216     }
1217     case V3D_AROUND_CENTER_MEDIAN: {
1218       uv_map_transform_calc_center_median(em, r_center);
1219       break;
1220     }
1221     case V3D_AROUND_CURSOR: /* cursor center */
1222     {
1223       invert_m4_m4(ob->imat, ob->obmat);
1224       mul_v3_m4v3(r_center, ob->imat, scene->cursor.location);
1225       break;
1226     }
1227     case V3D_AROUND_ACTIVE: {
1228       BMEditSelection ese;
1229       if (BM_select_history_active_get(em->bm, &ese)) {
1230         BM_editselection_center(&ese, r_center);
1231         break;
1232       }
1233       ATTR_FALLTHROUGH;
1234     }
1235     case V3D_AROUND_LOCAL_ORIGINS: /* object center */
1236     default:
1237       zero_v3(r_center);
1238       break;
1239   }
1240
1241   /* if this is passed, always set! */
1242   if (r_bounds) {
1243     if (!is_minmax_set) {
1244       uv_map_transform_calc_bounds(em, bounds[0], bounds[1]);
1245     }
1246     copy_v3_v3(r_bounds[0], bounds[0]);
1247     copy_v3_v3(r_bounds[1], bounds[1]);
1248   }
1249 }
1250
1251 static void uv_map_rotation_matrix_ex(float result[4][4],
1252                                       RegionView3D *rv3d,
1253                                       Object *ob,
1254                                       float upangledeg,
1255                                       float sideangledeg,
1256                                       float radius,
1257                                       float offset[4])
1258 {
1259   float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
1260   float sideangle = 0.0f, upangle = 0.0f;
1261
1262   /* get rotation of the current view matrix */
1263   if (rv3d) {
1264     copy_m4_m4(viewmatrix, rv3d->viewmat);
1265   }
1266   else {
1267     unit_m4(viewmatrix);
1268   }
1269
1270   /* but shifting */
1271   copy_v4_fl(viewmatrix[3], 0.0f);
1272
1273   /* get rotation of the current object matrix */
1274   copy_m4_m4(rotobj, ob->obmat);
1275
1276   /* but shifting */
1277   add_v4_v4(rotobj[3], offset);
1278   rotobj[3][3] = 0.0f;
1279
1280   zero_m4(rotup);
1281   zero_m4(rotside);
1282
1283   /* compensate front/side.. against opengl x,y,z world definition */
1284   /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
1285   /* i wanted to keep the reason here, so we're rotating*/
1286   sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f;
1287   rotside[0][0] = cosf(sideangle);
1288   rotside[0][1] = -sinf(sideangle);
1289   rotside[1][0] = sinf(sideangle);
1290   rotside[1][1] = cosf(sideangle);
1291   rotside[2][2] = 1.0f;
1292
1293   upangle = (float)M_PI * upangledeg / 180.0f;
1294   rotup[1][1] = cosf(upangle) / radius;
1295   rotup[1][2] = -sinf(upangle) / radius;
1296   rotup[2][1] = sinf(upangle) / radius;
1297   rotup[2][2] = cosf(upangle) / radius;
1298   rotup[0][0] = 1.0f / radius;
1299
1300   /* calculate transforms*/
1301   mul_m4_series(result, rotup, rotside, viewmatrix, rotobj);
1302 }
1303
1304 static void uv_map_rotation_matrix(float result[4][4],
1305                                    RegionView3D *rv3d,
1306                                    Object *ob,
1307                                    float upangledeg,
1308                                    float sideangledeg,
1309                                    float radius)
1310 {
1311   float offset[4] = {0};
1312   uv_map_rotation_matrix_ex(result, rv3d, ob, upangledeg, sideangledeg, radius, offset);
1313 }
1314
1315 static void uv_map_transform(bContext *C, wmOperator *op, float rotmat[4][4])
1316 {
1317   /* context checks are messy here, making it work in both 3d view and uv editor */
1318   Object *obedit = CTX_data_edit_object(C);
1319   RegionView3D *rv3d = CTX_wm_region_view3d(C);
1320   /* common operator properties */
1321   int align = RNA_enum_get(op->ptr, "align");
1322   int direction = RNA_enum_get(op->ptr, "direction");
1323   float radius = RNA_struct_find_property(op->ptr, "radius") ? RNA_float_get(op->ptr, "radius") :
1324                                                                1.0f;
1325   float upangledeg, sideangledeg;
1326
1327   if (direction == VIEW_ON_EQUATOR) {
1328     upangledeg = 90.0f;
1329     sideangledeg = 0.0f;
1330   }
1331   else {
1332     upangledeg = 0.0f;
1333     if (align == POLAR_ZY) {
1334       sideangledeg = 0.0f;
1335     }
1336     else {
1337       sideangledeg = 90.0f;
1338     }
1339   }
1340
1341   /* be compatible to the "old" sphere/cylinder mode */
1342   if (direction == ALIGN_TO_OBJECT) {
1343     unit_m4(rotmat);
1344   }
1345   else {
1346     uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
1347   }
1348 }
1349
1350 static void uv_transform_properties(wmOperatorType *ot, int radius)
1351 {
1352   static const EnumPropertyItem direction_items[] = {
1353       {VIEW_ON_EQUATOR, "VIEW_ON_EQUATOR", 0, "View on Equator", "3D view is on the equator"},
1354       {VIEW_ON_POLES, "VIEW_ON_POLES", 0, "View on Poles", "3D view is on the poles"},
1355       {ALIGN_TO_OBJECT,
1356        "ALIGN_TO_OBJECT",
1357        0,
1358        "Align to Object",
1359        "Align according to object transform"},
1360       {0, NULL, 0, NULL, NULL},
1361   };
1362   static const EnumPropertyItem align_items[] = {
1363       {POLAR_ZX, "POLAR_ZX", 0, "Polar ZX", "Polar 0 is X"},
1364       {POLAR_ZY, "POLAR_ZY", 0, "Polar ZY", "Polar 0 is Y"},
1365       {0, NULL, 0, NULL, NULL},
1366   };
1367
1368   RNA_def_enum(ot->srna,
1369                "direction",
1370                direction_items,
1371                VIEW_ON_EQUATOR,
1372                "Direction",
1373                "Direction of the sphere or cylinder");
1374   RNA_def_enum(ot->srna,
1375                "align",
1376                align_items,
1377                VIEW_ON_EQUATOR,
1378                "Align",
1379                "How to determine rotation around the pole");
1380   if (radius) {
1381     RNA_def_float(ot->srna,
1382                   "radius",
1383                   1.0f,
1384                   0.0f,
1385                   FLT_MAX,
1386                   "Radius",
1387                   "Radius of the sphere or cylinder",
1388                   0.0001f,
1389                   100.0f);
1390   }
1391 }
1392
1393 static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
1394 {
1395   BMLoop *l;
1396   BMIter iter, liter;
1397   MLoopUV *luv;
1398   BMFace *efa;
1399   float scale, aspx, aspy;
1400
1401   const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1402
1403   ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
1404
1405   if (aspx == aspy) {
1406     return;
1407   }
1408
1409   if (aspx > aspy) {
1410     scale = aspy / aspx;
1411
1412     BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1413       if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1414         continue;
1415       }
1416
1417       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1418         luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1419         luv->uv[0] = ((luv->uv[0] - 0.5f) * scale) + 0.5f;
1420       }
1421     }
1422   }
1423   else {
1424     scale = aspx / aspy;
1425
1426     BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1427       if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1428         continue;
1429       }
1430
1431       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1432         luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1433         luv->uv[1] = ((luv->uv[1] - 0.5f) * scale) + 0.5f;
1434       }
1435     }
1436   }
1437 }
1438
1439 /******************** Map Clip & Correct ******************/
1440
1441 static void uv_map_clip_correct_properties(wmOperatorType *ot)
1442 {
1443   RNA_def_boolean(ot->srna,
1444                   "correct_aspect",
1445                   1,
1446                   "Correct Aspect",
1447                   "Map UVs taking image aspect ratio into account");
1448   RNA_def_boolean(ot->srna,
1449                   "clip_to_bounds",
1450                   0,
1451                   "Clip to Bounds",
1452                   "Clip UV coordinates to bounds after unwrapping");
1453   RNA_def_boolean(ot->srna,
1454                   "scale_to_bounds",
1455                   0,
1456                   "Scale to Bounds",
1457                   "Scale UV coordinates to bounds after unwrapping");
1458 }
1459
1460 static void uv_map_clip_correct_multi(Scene *scene,
1461                                       Object **objects,
1462                                       uint objects_len,
1463                                       wmOperator *op)
1464 {
1465   BMFace *efa;
1466   BMLoop *l;
1467   BMIter iter, liter;
1468   MLoopUV *luv;
1469   float dx, dy, min[2], max[2];
1470   const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
1471   const bool clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds");
1472   const bool scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds");
1473
1474   INIT_MINMAX2(min, max);
1475
1476   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1477     Object *ob = objects[ob_index];
1478
1479     BMEditMesh *em = BKE_editmesh_from_object(ob);
1480     const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1481
1482     /* correct for image aspect ratio */
1483     if (correct_aspect) {
1484       correct_uv_aspect(scene, ob, em);
1485     }
1486
1487     if (scale_to_bounds) {
1488       /* find uv limits */
1489       BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1490         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1491           continue;
1492         }
1493
1494         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1495           luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1496           minmax_v2v2_v2(min, max, luv->uv);
1497         }
1498       }
1499     }
1500     else if (clip_to_bounds) {
1501       /* clipping and wrapping */
1502       BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1503         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1504           continue;
1505         }
1506
1507         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1508           luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1509           CLAMP(luv->uv[0], 0.0f, 1.0f);
1510           CLAMP(luv->uv[1], 0.0f, 1.0f);
1511         }
1512       }
1513     }
1514   }
1515
1516   if (scale_to_bounds) {
1517     /* rescale UV to be in 1/1 */
1518     dx = (max[0] - min[0]);
1519     dy = (max[1] - min[1]);
1520
1521     if (dx > 0.0f) {
1522       dx = 1.0f / dx;
1523     }
1524     if (dy > 0.0f) {
1525       dy = 1.0f / dy;
1526     }
1527
1528     for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1529       Object *ob = objects[ob_index];
1530
1531       BMEditMesh *em = BKE_editmesh_from_object(ob);
1532       const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1533
1534       BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1535         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1536           continue;
1537         }
1538
1539         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1540           luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1541
1542           luv->uv[0] = (luv->uv[0] - min[0]) * dx;
1543           luv->uv[1] = (luv->uv[1] - min[1]) * dy;
1544         }
1545       }
1546     }
1547   }
1548 }
1549
1550 static void uv_map_clip_correct(Scene *scene, Object *ob, wmOperator *op)
1551 {
1552   uv_map_clip_correct_multi(scene, &ob, 1, op);
1553 }
1554
1555 /* ******************** Unwrap operator **************** */
1556
1557 /* Assumes UV Map exists, doesn't run update funcs. */
1558 static void uvedit_unwrap(Scene *scene, Object *obedit, const UnwrapOptions *options)
1559 {
1560   BMEditMesh *em = BKE_editmesh_from_object(obedit);
1561   if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
1562     return;
1563   }
1564
1565   bool use_subsurf;
1566   modifier_unwrap_state(obedit, scene, &use_subsurf);
1567
1568   ParamHandle *handle;
1569   if (use_subsurf) {
1570     handle = construct_param_handle_subsurfed(scene, obedit, em, options);
1571   }
1572   else {
1573     handle = construct_param_handle(scene, obedit, em->bm, options);
1574   }
1575
1576   param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
1577   param_lscm_solve(handle);
1578   param_lscm_end(handle);
1579
1580   param_average(handle, true);
1581
1582   param_flush(handle);
1583
1584   param_delete(handle);
1585 }
1586
1587 static void uvedit_unwrap_multi(Scene *scene,
1588                                 Object **objects,
1589                                 const int objects_len,
1590                                 const UnwrapOptions *options)
1591 {
1592   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1593     Object *obedit = objects[ob_index];
1594     uvedit_unwrap(scene, obedit, options);
1595     DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
1596     WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
1597   }
1598 }
1599
1600 void ED_uvedit_live_unwrap(Scene *scene, Object **objects, int objects_len)
1601 {
1602   if (scene->toolsettings->edge_mode_live_unwrap) {
1603     const UnwrapOptions options = {
1604         .topology_from_uvs = false,
1605         .only_selected = false,
1606         .fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0,
1607         .correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0,
1608     };
1609
1610     bool rotate = true;
1611     bool ignore_pinned = true;
1612
1613     uvedit_unwrap_multi(scene, objects, objects_len, &options);
1614     uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
1615   }
1616 }
1617
1618 enum {
1619   UNWRAP_ERROR_NONUNIFORM = (1 << 0),
1620   UNWRAP_ERROR_NEGATIVE = (1 << 1),
1621 };
1622
1623 static int unwrap_exec(bContext *C, wmOperator *op)
1624 {
1625   ViewLayer *view_layer = CTX_data_view_layer(C);
1626   Scene *scene = CTX_data_scene(C);
1627   int method = RNA_enum_get(op->ptr, "method");
1628   const bool use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
1629   int reported_errors = 0;
1630   /* We will report an error unless at least one object
1631    * has the subsurf modifier in the right place. */
1632   bool subsurf_error = use_subsurf;
1633
1634   uint objects_len = 0;
1635   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1636       view_layer, CTX_wm_view3d(C), &objects_len);
1637
1638   const UnwrapOptions options = {
1639       .topology_from_uvs = false,
1640       .only_selected = true,
1641       .fill_holes = RNA_boolean_get(op->ptr, "fill_holes"),
1642       .correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"),
1643   };
1644
1645   bool rotate = true;
1646   bool ignore_pinned = true;
1647
1648   if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) {
1649     MEM_freeN(objects);
1650     return OPERATOR_CANCELLED;
1651   }
1652
1653   /* add uvs if they don't exist yet */
1654   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1655     Object *obedit = objects[ob_index];
1656     float obsize[3];
1657     bool use_subsurf_final;
1658
1659     if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1660       continue;
1661     }
1662
1663     if (subsurf_error) {
1664       /* Double up the check here but better keep uvedit_unwrap interface simple and not
1665        * pass operator for warning append. */
1666       modifier_unwrap_state(obedit, scene, &use_subsurf_final);
1667       if (use_subsurf_final) {
1668         subsurf_error = false;
1669       }
1670     }
1671
1672     if (reported_errors & (UNWRAP_ERROR_NONUNIFORM | UNWRAP_ERROR_NEGATIVE)) {
1673       continue;
1674     }
1675
1676     mat4_to_size(obsize, obedit->obmat);
1677     if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f)) {
1678       if ((reported_errors & UNWRAP_ERROR_NONUNIFORM) == 0) {
1679         BKE_report(op->reports,
1680                    RPT_INFO,
1681                    "Object has non-uniform scale, unwrap will operate on a non-scaled version of "
1682                    "the mesh");
1683         reported_errors |= UNWRAP_ERROR_NONUNIFORM;
1684       }
1685     }
1686     else if (is_negative_m4(obedit->obmat)) {
1687       if ((reported_errors & UNWRAP_ERROR_NEGATIVE) == 0) {
1688         BKE_report(
1689             op->reports,
1690             RPT_INFO,
1691             "Object has negative scale, unwrap will operate on a non-flipped version of the mesh");
1692         reported_errors |= UNWRAP_ERROR_NEGATIVE;
1693       }
1694     }
1695   }
1696
1697   if (subsurf_error) {
1698     BKE_report(op->reports,
1699                RPT_INFO,
1700                "Subdivision Surface modifier needs to be first to work with unwrap");
1701   }
1702
1703   /* remember last method for live unwrap */
1704   if (RNA_struct_property_is_set(op->ptr, "method")) {
1705     scene->toolsettings->unwrapper = method;
1706   }
1707   else {
1708     RNA_enum_set(op->ptr, "method", scene->toolsettings->unwrapper);
1709   }
1710
1711   /* remember packing margin */
1712   if (RNA_struct_property_is_set(op->ptr, "margin")) {
1713     scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
1714   }
1715   else {
1716     RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
1717   }
1718
1719   if (options.fill_holes) {
1720     scene->toolsettings->uvcalc_flag |= UVCALC_FILLHOLES;
1721   }
1722   else {
1723     scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES;
1724   }
1725
1726   if (options.correct_aspect) {
1727     scene->toolsettings->uvcalc_flag &= ~UVCALC_NO_ASPECT_CORRECT;
1728   }
1729   else {
1730     scene->toolsettings->uvcalc_flag |= UVCALC_NO_ASPECT_CORRECT;
1731   }
1732
1733   if (use_subsurf) {
1734     scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
1735   }
1736   else {
1737     scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
1738   }
1739
1740   /* execute unwrap */
1741   uvedit_unwrap_multi(scene, objects, objects_len, &options);
1742   uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
1743
1744   MEM_freeN(objects);
1745
1746   return OPERATOR_FINISHED;
1747 }
1748
1749 void UV_OT_unwrap(wmOperatorType *ot)
1750 {
1751   static const EnumPropertyItem method_items[] = {
1752       {0, "ANGLE_BASED", 0, "Angle Based", ""},
1753       {1, "CONFORMAL", 0, "Conformal", ""},
1754       {0, NULL, 0, NULL, NULL},
1755   };
1756
1757   /* identifiers */
1758   ot->name = "Unwrap";
1759   ot->description = "Unwrap the mesh of the object being edited";
1760   ot->idname = "UV_OT_unwrap";
1761   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1762
1763   /* api callbacks */
1764   ot->exec = unwrap_exec;
1765   ot->poll = ED_operator_uvmap;
1766
1767   /* properties */
1768   RNA_def_enum(ot->srna,
1769                "method",
1770                method_items,
1771                0,
1772                "Method",
1773                "Unwrapping method (Angle Based usually gives better results than Conformal, while "
1774                "being somewhat slower)");
1775   RNA_def_boolean(ot->srna,
1776                   "fill_holes",
1777                   1,
1778                   "Fill Holes",
1779                   "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and "
1780                   "preserve symmetry");
1781   RNA_def_boolean(ot->srna,
1782                   "correct_aspect",
1783                   1,
1784                   "Correct Aspect",
1785                   "Map UVs taking image aspect ratio into account");
1786   RNA_def_boolean(
1787       ot->srna,
1788       "use_subsurf_data",
1789       0,
1790       "Use Subsurf Modifier",
1791       "Map UVs taking vertex position after Subdivision Surface modifier has been applied");
1792   RNA_def_float_factor(
1793       ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
1794 }
1795
1796 /**************** Project From View operator **************/
1797 static int uv_from_view_exec(bContext *C, wmOperator *op);
1798
1799 static int uv_from_view_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1800 {
1801   View3D *v3d = CTX_wm_view3d(C);
1802   RegionView3D *rv3d = CTX_wm_region_view3d(C);
1803   Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
1804   PropertyRNA *prop;
1805
1806   prop = RNA_struct_find_property(op->ptr, "camera_bounds");
1807   if (!RNA_property_is_set(op->ptr, prop)) {
1808     RNA_property_boolean_set(op->ptr, prop, (camera != NULL));
1809   }
1810   prop = RNA_struct_find_property(op->ptr, "correct_aspect");
1811   if (!RNA_property_is_set(op->ptr, prop)) {
1812     RNA_property_boolean_set(op->ptr, prop, (camera == NULL));
1813   }
1814
1815   return uv_from_view_exec(C, op);
1816 }
1817
1818 static int uv_from_view_exec(bContext *C, wmOperator *op)
1819 {
1820   ViewLayer *view_layer = CTX_data_view_layer(C);
1821   Scene *scene = CTX_data_scene(C);
1822   ARegion *ar = CTX_wm_region(C);
1823   View3D *v3d = CTX_wm_view3d(C);
1824   RegionView3D *rv3d = CTX_wm_region_view3d(C);
1825   Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
1826   BMFace *efa;
1827   BMLoop *l;
1828   BMIter iter, liter;
1829   MLoopUV *luv;
1830   float rotmat[4][4];
1831   float objects_pos_offset[4];
1832   bool changed_multi = false;
1833
1834   const bool use_orthographic = RNA_boolean_get(op->ptr, "orthographic");
1835
1836   /* Note: objects that aren't touched are set to NULL (to skip clipping). */
1837   uint objects_len = 0;
1838   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1839       view_layer, v3d, &objects_len);
1840
1841   if (use_orthographic) {
1842     /* Calculate average object position. */
1843     float objects_pos_avg[4] = {0};
1844
1845     for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1846       add_v4_v4(objects_pos_avg, objects[ob_index]->obmat[3]);
1847     }
1848
1849     mul_v4_fl(objects_pos_avg, 1.0f / objects_len);
1850     negate_v4_v4(objects_pos_offset, objects_pos_avg);
1851   }
1852
1853   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1854     Object *obedit = objects[ob_index];
1855     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1856     bool changed = false;
1857
1858     /* add uvs if they don't exist yet */
1859     if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1860       continue;
1861     }
1862
1863     const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1864
1865     if (use_orthographic) {
1866       uv_map_rotation_matrix_ex(rotmat, rv3d, obedit, 90.0f, 0.0f, 1.0f, objects_pos_offset);
1867
1868       BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1869         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1870           continue;
1871         }
1872
1873         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1874           luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1875           BLI_uvproject_from_view_ortho(luv->uv, l->v->co, rotmat);
1876         }
1877         changed = true;
1878       }
1879     }
1880     else if (camera) {
1881       const bool camera_bounds = RNA_boolean_get(op->ptr, "camera_bounds");
1882       struct ProjCameraInfo *uci = BLI_uvproject_camera_info(
1883           v3d->camera,
1884           obedit->obmat,
1885           camera_bounds ? (scene->r.xsch * scene->r.xasp) : 1.0f,
1886           camera_bounds ? (scene->r.ysch * scene->r.yasp) : 1.0f);
1887
1888       if (uci) {
1889         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1890           if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1891             continue;
1892           }
1893
1894           BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1895             luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1896             BLI_uvproject_from_camera(luv->uv, l->v->co, uci);
1897           }
1898           changed = true;
1899         }
1900
1901         MEM_freeN(uci);
1902       }
1903     }
1904     else {
1905       copy_m4_m4(rotmat, obedit->obmat);
1906
1907       BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1908         if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
1909           continue;
1910         }
1911
1912         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1913           luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1914           BLI_uvproject_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
1915         }
1916         changed = true;
1917       }
1918     }
1919
1920     if (changed) {
1921       changed_multi = true;
1922       DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
1923       WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1924     }
1925     else {
1926       ARRAY_DELETE_REORDER_LAST(objects, ob_index, 1, objects_len);
1927       objects_len -= 1;
1928       ob_index -= 1;
1929     }
1930   }
1931
1932   if (changed_multi) {
1933     uv_map_clip_correct_multi(scene, objects, objects_len, op);
1934   }
1935
1936   MEM_freeN(objects);
1937
1938   if (changed_multi) {
1939     return OPERATOR_FINISHED;
1940   }
1941   else {
1942     return OPERATOR_CANCELLED;
1943   }
1944 }
1945
1946 static bool uv_from_view_poll(bContext *C)
1947 {
1948   RegionView3D *rv3d = CTX_wm_region_view3d(C);
1949
1950   if (!ED_operator_uvmap(C)) {
1951     return 0;
1952   }
1953
1954   return (rv3d != NULL);
1955 }
1956
1957 void UV_OT_project_from_view(wmOperatorType *ot)
1958 {
1959   /* identifiers */
1960   ot->name = "Project From View";
1961   ot->idname = "UV_OT_project_from_view";
1962   ot->description = "Project the UV vertices of the mesh as seen in current 3D view";
1963
1964   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1965
1966   /* api callbacks */
1967   ot->invoke = uv_from_view_invoke;
1968   ot->exec = uv_from_view_exec;
1969   ot->poll = uv_from_view_poll;
1970
1971   /* properties */
1972   RNA_def_boolean(ot->srna, "orthographic", 0, "Orthographic", "Use orthographic projection");
1973   RNA_def_boolean(ot->srna,
1974                   "camera_bounds",
1975                   1,
1976                   "Camera Bounds",
1977                   "Map UVs to the camera region taking resolution and aspect into account");
1978   uv_map_clip_correct_properties(ot);
1979 }
1980
1981 /********************** Reset operator ********************/
1982
1983 static int reset_exec(bContext *C, wmOperator *UNUSED(op))
1984 {
1985   Scene *scene = CTX_data_scene(C);
1986   ViewLayer *view_layer = CTX_data_view_layer(C);
1987   View3D *v3d = CTX_wm_view3d(C);
1988
1989   uint objects_len = 0;
1990   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1991       view_layer, v3d, &objects_len);
1992   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1993     Object *obedit = objects[ob_index];
1994     Mesh *me = (Mesh *)obedit->data;
1995     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1996
1997     if (em->bm->totfacesel == 0) {
1998       continue;
1999     }
2000
2001     /* add uvs if they don't exist yet */
2002     if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
2003       continue;
2004     }
2005
2006     ED_mesh_uv_loop_reset(C, me);
2007
2008     DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
2009     WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
2010   }
2011   MEM_freeN(objects);
2012
2013   return OPERATOR_FINISHED;
2014 }
2015
2016 void UV_OT_reset(wmOperatorType *ot)
2017 {
2018   /* identifiers */
2019   ot->name = "Reset";
2020   ot->idname = "UV_OT_reset";
2021   ot->description = "Reset UV projection";
2022
2023   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2024
2025   /* api callbacks */
2026   ot->exec = reset_exec;
2027   ot->poll = ED_operator_uvmap;
2028 }
2029
2030 /****************** Sphere Project operator ***************/
2031
2032 static void uv_sphere_project(float target[2],
2033                               float source[3],
2034                               float center[3],
2035                               float rotmat[4][4])
2036 {
2037   float pv[3];
2038
2039   sub_v3_v3v3(pv, source, center);
2040   mul_m4_v3(rotmat, pv);
2041
2042   map_to_sphere(&target[0], &target[1], pv[0], pv[1], pv[2]);
2043
2044   /* split line is always zero */
2045   if (target[0] >= 1.0f) {
2046     target[0] -= 1.0f;
2047   }
2048 }
2049
2050 static void uv_map_mirror(BMEditMesh *em, BMFace *efa)
2051 {
2052   BMLoop *l;
2053   BMIter liter;
2054   MLoopUV *luv;
2055   float **uvs = BLI_array_alloca(uvs, efa->len);
2056   float dx;
2057   int i, mi;
2058
2059   const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
2060
2061   BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
2062     luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
2063     uvs[i] = luv->uv;
2064   }
2065
2066   mi = 0;
2067   for (i = 1; i < efa->len; i++) {
2068     if (uvs[i][0] > uvs[mi][0]) {
2069       mi = i;
2070     }
2071   }
2072
2073   for (i = 0; i < efa->len; i++) {
2074     if (i != mi) {
2075       dx = uvs[mi][0] - uvs[i][0];
2076       if (dx > 0.5f) {
2077         uvs[i][0] += 1.0f;
2078       }
2079     }
2080   }
2081 }
2082
2083 static int sphere_project_exec(bContext *C, wmOperator *op)
2084 {
2085   Scene *scene = CTX_data_scene(C);
2086   View3D *v3d = CTX_wm_view3d(C);
2087
2088   ViewLayer *view_layer = CTX_data_view_layer(C);
2089   uint objects_len = 0;
2090   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2091       view_layer, v3d, &objects_len);
2092   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2093     Object *obedit = objects[ob_index];
2094     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2095     BMFace *efa;
2096     BMLoop *l;
2097     BMIter iter, liter;
2098     MLoopUV *luv;
2099
2100     if (em->bm->totfacesel == 0) {
2101       continue;
2102     }
2103
2104     /* add uvs if they don't exist yet */
2105     if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
2106       continue;
2107     }
2108
2109     const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
2110     float center[3], rotmat[4][4];
2111
2112     uv_map_transform(C, op, rotmat);
2113     uv_map_transform_center(scene, v3d, obedit, em, center, NULL);
2114
2115     BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2116       if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
2117         continue;
2118       }
2119
2120       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
2121         luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
2122
2123         uv_sphere_project(luv->uv, l->v->co, center, rotmat);
2124       }
2125
2126       uv_map_mirror(em, efa);
2127     }
2128
2129     uv_map_clip_correct(scene, obedit, op);
2130
2131     DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
2132     WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
2133   }
2134   MEM_freeN(objects);
2135
2136   return OPERATOR_FINISHED;
2137 }
2138
2139 void UV_OT_sphere_project(wmOperatorType *ot)
2140 {
2141   /* identifiers */
2142   ot->name = "Sphere Projection";
2143   ot->idname = "UV_OT_sphere_project";
2144   ot->description = "Project the UV vertices of the mesh over the curved surface of a sphere";
2145
2146   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2147
2148   /* api callbacks */
2149   ot->exec = sphere_project_exec;
2150   ot->poll = ED_operator_uvmap;
2151
2152   /* properties */
2153   uv_transform_properties(ot, 0);
2154   uv_map_clip_correct_properties(ot);
2155 }
2156
2157 /***************** Cylinder Project operator **************/
2158
2159 static void uv_cylinder_project(float target[2],
2160                                 float source[3],
2161                                 float center[3],
2162                                 float rotmat[4][4])
2163 {
2164   float pv[3];
2165
2166   sub_v3_v3v3(pv, source, center);
2167   mul_m4_v3(rotmat, pv);
2168
2169   map_to_tube(&target[0], &target[1], pv[0], pv[1], pv[2]);
2170
2171   /* split line is always zero */
2172   if (target[0] >= 1.0f) {
2173     target[0] -= 1.0f;
2174   }
2175 }
2176
2177 static int cylinder_project_exec(bContext *C, wmOperator *op)
2178 {
2179   Scene *scene = CTX_data_scene(C);
2180   View3D *v3d = CTX_wm_view3d(C);
2181
2182   ViewLayer *view_layer = CTX_data_view_layer(C);
2183   uint objects_len = 0;
2184   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2185       view_layer, v3d, &objects_len);
2186   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2187     Object *obedit = objects[ob_index];
2188     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2189     BMFace *efa;
2190     BMLoop *l;
2191     BMIter iter, liter;
2192     MLoopUV *luv;
2193
2194     if (em->bm->totfacesel == 0) {
2195       continue;
2196     }
2197
2198     /* add uvs if they don't exist yet */
2199     if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
2200       continue;
2201     }
2202
2203     const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
2204     float center[3], rotmat[4][4];
2205
2206     uv_map_transform(C, op, rotmat);
2207     uv_map_transform_center(scene, v3d, obedit, em, center, NULL);
2208
2209     BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2210       if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
2211         continue;
2212       }
2213
2214       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
2215         luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
2216
2217         uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
2218       }
2219
2220       uv_map_mirror(em, efa);
2221     }
2222
2223     uv_map_clip_correct(scene, obedit, op);
2224
2225     DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
2226     WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
2227   }
2228   MEM_freeN(objects);
2229
2230   return OPERATOR_FINISHED;
2231 }
2232
2233 void UV_OT_cylinder_project(wmOperatorType *ot)
2234 {
2235   /* identifiers */
2236   ot->name = "Cylinder Projection";
2237   ot->idname = "UV_OT_cylinder_project";
2238   ot->description = "Project the UV vertices of the mesh over the curved wall of a cylinder";
2239
2240   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2241
2242   /* api callbacks */
2243   ot->exec = cylinder_project_exec;
2244   ot->poll = ED_operator_uvmap;
2245
2246   /* properties */
2247   uv_transform_properties(ot, 1);
2248   uv_map_clip_correct_properties(ot);
2249 }
2250
2251 /******************* Cube Project operator ****************/
2252
2253 static void uvedit_unwrap_cube_project(BMesh *bm,
2254                                        float cube_size,
2255                                        bool use_select,
2256                                        const float center[3])
2257 {
2258   BMFace *efa;
2259   BMLoop *l;
2260   BMIter iter, liter;
2261   MLoopUV *luv;
2262   float loc[3];
2263   int cox, coy;
2264
2265   int cd_loop_uv_offset;
2266
2267   cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
2268
2269   if (center) {
2270     copy_v3_v3(loc, center);
2271   }
2272   else {
2273     zero_v3(loc);
2274   }
2275
2276   /* choose x,y,z axis for projection depending on the largest normal
2277    * component, but clusters all together around the center of map. */
2278
2279   BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
2280     /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
2281     if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
2282       continue;
2283     }
2284
2285     axis_dominant_v3(&cox, &coy, efa->no);
2286
2287     BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
2288       luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
2289       luv->uv[0] = 0.5f + 0.5f * cube_size * (l->v->co[cox] - loc[cox]);
2290       luv->uv[1] = 0.5f + 0.5f * cube_size * (l->v->co[coy] - loc[coy]);
2291     }
2292   }
2293 }
2294
2295 static int cube_project_exec(bContext *C, wmOperator *op)
2296 {
2297   Scene *scene = CTX_data_scene(C);
2298   View3D *v3d = CTX_wm_view3d(C);
2299
2300   PropertyRNA *prop_cube_size = RNA_struct_find_property(op->ptr, "cube_size");
2301   const float cube_size_init = RNA_property_float_get(op->ptr, prop_cube_size);
2302
2303   ViewLayer *view_layer = CTX_data_view_layer(C);
2304   uint objects_len = 0;
2305   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2306       view_layer, v3d, &objects_len);
2307   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2308     Object *obedit = objects[ob_index];
2309     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2310
2311     if (em->bm->totfacesel == 0) {
2312       continue;
2313     }
2314
2315     /* add uvs if they don't exist yet */
2316     if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
2317       continue;
2318     }
2319
2320     float bounds[2][3];
2321     float(*bounds_buf)[3] = NULL;
2322
2323     if (!RNA_property_is_set(op->ptr, prop_cube_size)) {
2324       bounds_buf = bounds;
2325     }
2326
2327     float center[3];
2328     uv_map_transform_center(scene, v3d, obedit, em, center, bounds_buf);
2329
2330     /* calculate based on bounds */
2331     float cube_size = cube_size_init;
2332     if (bounds_buf) {
2333       float dims[3];
2334       sub_v3_v3v3(dims, bounds[1], bounds[0]);
2335       cube_size = max_fff(UNPACK3(dims));
2336       cube_size = cube_size ? 2.0f / cube_size : 1.0f;
2337       if (ob_index == 0) {
2338         /* This doesn't fit well with, multiple objects. */
2339         RNA_property_float_set(op->ptr, prop_cube_size, cube_size);
2340       }
2341     }
2342
2343     uvedit_unwrap_cube_project(em->bm, cube_size, true, center);
2344
2345     uv_map_clip_correct(scene, obedit, op);
2346
2347     DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
2348     WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
2349   }
2350   MEM_freeN(objects);
2351
2352   return OPERATOR_FINISHED;
2353 }
2354
2355 void UV_OT_cube_project(wmOperatorType *ot)
2356 {
2357   /* identifiers */
2358   ot->name = "Cube Projection";
2359   ot->idname = "UV_OT_cube_project";
2360   ot->description = "Project the UV vertices of the mesh over the six faces of a cube";
2361
2362   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2363
2364   /* api callbacks */
2365   ot->exec = cube_project_exec;
2366   ot->poll = ED_operator_uvmap;
2367
2368   /* properties */
2369   RNA_def_float(ot->srna,
2370                 "cube_size",
2371                 1.0f,
2372                 0.0f,
2373                 FLT_MAX,
2374                 "Cube Size",
2375                 "Size of the cube to project on",
2376                 0.001f,
2377                 100.0f);
2378   uv_map_clip_correct_properties(ot);
2379 }
2380
2381 /************************* Simple UVs for texture painting *****************/
2382
2383 void ED_uvedit_add_simple_uvs(Main *bmain, Scene *scene, Object *ob)
2384 {
2385   Mesh *me = ob->data;
2386   bool sync_selection = (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
2387
2388   BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default,
2389                              &((struct BMeshCreateParams){
2390                                  .use_toolflags = false,
2391                              }));
2392
2393   /* turn sync selection off,
2394    * since we are not in edit mode we need to ensure only the uv flags are tested */
2395   scene->toolsettings->uv_flag &= ~UV_SYNC_SELECTION;
2396
2397   ED_mesh_uv_texture_ensure(me, NULL);
2398
2399   BM_mesh_bm_from_me(bm,
2400                      me,
2401                      (&(struct BMeshFromMeshParams){
2402                          .calc_face_normal = true,
2403                      }));
2404   /* select all uv loops first - pack parameters needs this to make sure charts are registered */
2405   ED_uvedit_select_all(bm);
2406   uvedit_unwrap_cube_project(bm, 1.0, false, NULL);
2407   /* set the margin really quickly before the packing operation*/
2408   scene->toolsettings->uvcalc_margin = 0.001f;
2409   uvedit_pack_islands(scene, ob, bm);
2410   BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0}));
2411   BM_mesh_free(bm);
2412
2413   if (sync_selection) {
2414     scene->toolsettings->uv_flag |= UV_SYNC_SELECTION;
2415   }
2416 }