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