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