~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to source/blender/editors/uvedit/uvedit_unwrap_ops.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
#include "BKE_main.h"
61
61
#include "BKE_mesh.h"
62
62
#include "BKE_report.h"
 
63
#include "BKE_scene.h"
63
64
#include "BKE_tessmesh.h"
64
65
 
65
66
#include "BLI_math.h"
86
87
#include "uvedit_intern.h"
87
88
#include "uvedit_parametrizer.h"
88
89
 
 
90
static void modifier_unwrap_state(Object *obedit, Scene *scene, short *use_subsurf)
 
91
{
 
92
        ModifierData *md;
 
93
        short subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
 
94
 
 
95
        md = obedit->modifiers.first;
 
96
 
 
97
        /* subsurf will take the modifier settings only if modifier is first or right after mirror */
 
98
        if (subsurf) {
 
99
                if (md && md->type == eModifierType_Subsurf)
 
100
                        subsurf = TRUE;
 
101
                else
 
102
                        subsurf = FALSE;
 
103
        }
 
104
 
 
105
        *use_subsurf = subsurf;
 
106
}
 
107
 
89
108
static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
90
109
{
91
110
        Main *bmain = CTX_data_main(C);
98
117
        SpaceLink *slink;
99
118
        SpaceImage *sima;
100
119
 
101
 
        if (ED_uvedit_test(obedit)) {
 
120
        if (ED_uvedit_test(obedit))
102
121
                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
 
                ED_mesh_uv_loop_reset_ex(C, obedit->data, 0);
109
 
        }
110
 
 
111
 
        if (!ED_uvedit_test(obedit)) {
 
122
 
 
123
        if (em && em->bm->totface && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY))
 
124
                ED_mesh_uv_texture_add(C, obedit->data, NULL, TRUE);
 
125
 
 
126
        if (!ED_uvedit_test(obedit))
112
127
                return 0;
113
 
        }
114
128
 
115
129
        ima = CTX_data_edit_image(C);
116
130
 
147
161
 
148
162
/****************** Parametrizer Conversion ***************/
149
163
 
150
 
static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
 
164
static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit)
151
165
{
152
166
        BMFace *efa;
153
167
        BMLoop *l;
154
168
        BMIter iter, liter;
155
 
        MLoopUV *luv;
156
169
        
 
170
        if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
 
171
                return (em->bm->totfacesel != 0);
 
172
        }
 
173
 
157
174
        /* verify if we have any selected uv's before unwrapping,
158
175
         * so we can cancel the operator early */
159
176
        BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
161
178
                        if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
162
179
                                continue;
163
180
                }
164
 
                else if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))
 
181
                else if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
165
182
                        continue;
166
183
        
167
184
                BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
168
 
                        luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
169
 
                        if (!luv)
170
 
                                return 1;
171
 
                        
172
185
                        if (uvedit_uv_select_test(em, scene, l))
173
186
                                break;
174
187
                }
176
189
                if (implicit && !l)
177
190
                        continue;
178
191
                
179
 
                return 1;
180
 
        }
181
 
 
182
 
        return 0;
183
 
}
184
 
 
185
 
static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, 
 
192
                return true;
 
193
        }
 
194
 
 
195
        return false;
 
196
}
 
197
 
 
198
void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy)
 
199
{
 
200
        int sloppy = TRUE;
 
201
        int selected = FALSE;
 
202
        BMFace *efa;
 
203
        Image *ima;
 
204
 
 
205
        efa = BM_active_face_get(em->bm, sloppy, selected);
 
206
 
 
207
        if (efa) {
 
208
                if (BKE_scene_use_new_shading_nodes(scene)) {
 
209
                        ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL);
 
210
                }
 
211
                else {
 
212
                        MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 
213
                        ima = tf->tpage;
 
214
                }
 
215
 
 
216
                ED_image_get_uv_aspect(ima, NULL, aspx, aspy);
 
217
        }
 
218
        else {
 
219
                *aspx = 1.0f;
 
220
                *aspy = 1.0f;
 
221
        }
 
222
}
 
223
 
 
224
static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh *em, 
186
225
                                           short implicit, short fill, short sel,
187
226
                                           short correct_aspect)
188
227
{
 
228
        BMesh *bm = em->bm;
189
229
        ScanFillContext sf_ctx;
190
230
        ParamHandle *handle;
191
231
        BMFace *efa;
192
232
        BMLoop *l;
193
233
        BMEdge *eed;
194
234
        BMIter iter, liter;
195
 
        MTexPoly *tf;
196
235
        
 
236
        const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
 
237
 
197
238
        handle = param_construct_begin();
198
239
 
 
240
 
199
241
        if (correct_aspect) {
200
 
                efa = BM_active_face_get(em->bm, TRUE);
201
 
 
202
 
                if (efa) {
203
 
                        float aspx, aspy;
204
 
                        tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
205
 
 
206
 
                        ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
207
 
                
208
 
                        if (aspx != aspy)
209
 
                                param_aspect_ratio(handle, aspx, aspy);
210
 
                }
 
242
                float aspx, aspy;
 
243
 
 
244
                uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
 
245
 
 
246
                if (aspx != aspy)
 
247
                        param_aspect_ratio(handle, aspx, aspy);
211
248
        }
212
249
        
213
250
        /* we need the vert indices */
216
253
        BLI_srand(0);
217
254
        
218
255
        BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
219
 
                ScanFillVert *v, *lastv, *firstv;
220
 
                ScanFillFace *sefa;
 
256
                ScanFillVert *sf_vert = NULL, *sf_vert_last, *sf_vert_first;
 
257
                ScanFillFace *sf_tri;
221
258
                ParamKey key, vkeys[4];
222
259
                ParamBool pin[4], select[4];
223
260
                BMLoop *ls[3];
224
261
                float *co[4];
225
262
                float *uv[4];
226
 
                int i, lsel;
 
263
                int lsel;
227
264
 
228
265
                if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || (sel && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0))
229
266
                        continue;
242
279
 
243
280
                key = (ParamKey)efa;
244
281
 
 
282
                // tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);  // UNUSED
245
283
 
246
284
                if (efa->len == 3 || efa->len == 4) {
 
285
                        int i;
247
286
                        /* for quads let parametrize split, it can make better decisions
248
287
                         * about which split is best for unwrapping than scanfill */
249
288
                        i = 0;
250
289
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
251
 
                                MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
290
                                MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
252
291
                                vkeys[i] = (ParamKey)BM_elem_index_get(l->v);
253
292
                                co[i] = l->v->co;
254
293
                                uv[i] = luv->uv;
262
301
                }
263
302
                else {
264
303
                        /* ngon - scanfill time! */
265
 
                        BLI_begin_edgefill(&sf_ctx);
 
304
                        BLI_scanfill_begin(&sf_ctx);
266
305
                        
267
 
                        firstv = lastv = NULL;
 
306
                        sf_vert_first = sf_vert_last = NULL;
268
307
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
269
308
                                int i;
270
309
                                
271
 
                                v = BLI_addfillvert(&sf_ctx, l->v->co);
 
310
                                sf_vert = BLI_scanfill_vert_add(&sf_ctx, l->v->co);
272
311
                                
273
312
                                /* add small random offset */
274
313
                                for (i = 0; i < 3; i++) {
275
 
                                        v->co[i] += (BLI_frand() - 0.5f) * FLT_EPSILON * 50;
 
314
                                        sf_vert->co[i] += (BLI_frand() - 0.5f) * FLT_EPSILON * 50;
276
315
                                }
277
316
                                
278
 
                                v->tmp.p = l;
 
317
                                sf_vert->tmp.p = l;
279
318
 
280
 
                                if (lastv) {
281
 
                                        BLI_addfilledge(&sf_ctx, lastv, v);
 
319
                                if (sf_vert_last) {
 
320
                                        BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
282
321
                                }
283
322
 
284
 
                                lastv = v;
285
 
                                if (!firstv) 
286
 
                                        firstv = v;
 
323
                                sf_vert_last = sf_vert;
 
324
                                if (!sf_vert_first)
 
325
                                        sf_vert_first = sf_vert;
287
326
                        }
288
327
 
289
 
                        BLI_addfilledge(&sf_ctx, firstv, v);
 
328
                        BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
290
329
 
291
 
                        BLI_edgefill_ex(&sf_ctx, TRUE, efa->no);
292
 
                        for (sefa = sf_ctx.fillfacebase.first; sefa; sefa = sefa->next) {
293
 
                                ls[0] = sefa->v1->tmp.p;
294
 
                                ls[1] = sefa->v2->tmp.p;
295
 
                                ls[2] = sefa->v3->tmp.p;
 
330
                        BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
 
331
                        for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
 
332
                                int i;
 
333
                                ls[0] = sf_tri->v1->tmp.p;
 
334
                                ls[1] = sf_tri->v2->tmp.p;
 
335
                                ls[2] = sf_tri->v3->tmp.p;
296
336
 
297
337
                                for (i = 0; i < 3; i++) {
298
 
                                        MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, ls[i]->head.data, CD_MLOOPUV);
 
338
                                        MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(ls[i], cd_loop_uv_offset);
299
339
                                        vkeys[i] = (ParamKey)BM_elem_index_get(ls[i]->v);
300
340
                                        co[i] = ls[i]->v->co;
301
341
                                        uv[i] = luv->uv;
306
346
                                param_face_add(handle, key, 3, vkeys, co, uv, pin, select);
307
347
                        }
308
348
 
309
 
                        BLI_end_edgefill(&sf_ctx);
 
349
                        BLI_scanfill_end(&sf_ctx);
310
350
                }
311
351
        }
312
352
 
327
367
}
328
368
 
329
369
 
330
 
static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, Scene *scene, BMEditMesh *em)
 
370
static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select,
 
371
                                        Scene *scene, BMEditMesh *em, const int cd_loop_uv_offset)
331
372
{
332
373
        BMLoop *l;
333
374
        BMIter liter;
342
383
 
343
384
        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
344
385
                if (BM_elem_index_get(l->v) == index) {
345
 
                        luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
386
                        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
346
387
                        *uv = luv->uv;
347
388
                        *pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0;
348
389
                        *select = (uvedit_uv_select_test(em, scene, l) != 0);
 
390
                        break;
349
391
                }
350
392
        }
351
393
}
352
394
 
353
395
/* unwrap handle initialization for subsurf aware-unwrapper. The many modifications required to make the original function(see above)
354
396
 * work justified the existence of a new function. */
355
 
static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *em, short fill, short sel, short correct_aspect)
 
397
static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, BMEditMesh *em, short fill, short sel, short correct_aspect)
356
398
{
357
399
        ParamHandle *handle;
358
400
        /* index pointers */
359
401
        MFace *face;
360
402
        MEdge *edge;
361
 
        BMFace *editFace;
362
403
        int i;
363
404
 
 
405
        /* pointers to modifier data for unwrap control */
 
406
        ModifierData *md;
 
407
        SubsurfModifierData *smd_real;
364
408
        /* modifier initialization data, will  control what type of subdivision will happen*/
365
409
        SubsurfModifierData smd = {{0}};
366
410
        /* Used to hold subsurfed Mesh */
367
411
        DerivedMesh *derivedMesh, *initialDerived;
368
412
        /* holds original indices for subsurfed mesh */
369
 
        int *origVertIndices, *origFaceIndices, *origEdgeIndices;
 
413
        int *origVertIndices, *origEdgeIndices, *origFaceIndices, *origPolyIndices;
370
414
        /* Holds vertices of subsurfed mesh */
371
415
        MVert *subsurfedVerts;
372
416
        MEdge *subsurfedEdges;
379
423
        /* similar to the above, we need a way to map edges to their original ones */
380
424
        BMEdge **edgeMap;
381
425
 
 
426
        const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 
427
 
382
428
        handle = param_construct_begin();
383
429
 
384
430
        if (correct_aspect) {
385
 
                editFace = BM_active_face_get(em->bm, TRUE);
386
 
 
387
 
                if (editFace) {
388
 
                        MTexPoly *tf;
389
 
                        float aspx, aspy;
390
 
                        tf = CustomData_bmesh_get(&em->bm->pdata, editFace->head.data, CD_MTEXPOLY);
391
 
 
392
 
                        ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
393
 
 
394
 
                        if (aspx != aspy)
395
 
                                param_aspect_ratio(handle, aspx, aspy);
396
 
                }
 
431
                float aspx, aspy;
 
432
 
 
433
                uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
 
434
 
 
435
                if (aspx != aspy)
 
436
                        param_aspect_ratio(handle, aspx, aspy);
397
437
        }
398
438
 
399
439
        /* number of subdivisions to perform */
400
 
        smd.levels = scene->toolsettings->uv_subsurf_level;
401
 
        smd.subdivType = ME_CC_SUBSURF;
 
440
        md = ob->modifiers.first;
 
441
        smd_real = (SubsurfModifierData *)md;
 
442
 
 
443
        smd.levels = smd_real->levels;
 
444
        smd.subdivType = smd_real->subdivType;
402
445
                
403
 
        initialDerived = CDDM_from_BMEditMesh(em, NULL, 0, 0);
 
446
        initialDerived = CDDM_from_editbmesh(em, FALSE, FALSE);
404
447
        derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd,
405
 
                                                        0, NULL, 0, 0, 1);
 
448
                                                        NULL, SUBSURF_IN_EDIT_MODE);
406
449
 
407
450
        initialDerived->release(initialDerived);
408
451
 
414
457
        origVertIndices = derivedMesh->getVertDataArray(derivedMesh, CD_ORIGINDEX);
415
458
        origEdgeIndices = derivedMesh->getEdgeDataArray(derivedMesh, CD_ORIGINDEX);
416
459
        origFaceIndices = derivedMesh->getTessFaceDataArray(derivedMesh, CD_ORIGINDEX);
 
460
        origPolyIndices = derivedMesh->getPolyDataArray(derivedMesh, CD_ORIGINDEX);
417
461
 
418
462
        numOfEdges = derivedMesh->getNumEdges(derivedMesh);
419
463
        numOfFaces = derivedMesh->getNumTessFaces(derivedMesh);
421
465
        faceMap = MEM_mallocN(numOfFaces * sizeof(BMFace *), "unwrap_edit_face_map");
422
466
 
423
467
        BM_mesh_elem_index_ensure(em->bm, BM_VERT);
424
 
        EDBM_index_arrays_init(em, 0, 1, 1);
 
468
        EDBM_index_arrays_ensure(em, BM_EDGE | BM_FACE);
425
469
 
426
470
        /* map subsurfed faces to original editFaces */
427
471
        for (i = 0; i < numOfFaces; i++)
428
 
                faceMap[i] = EDBM_face_at_index(em, origFaceIndices[i]);
 
472
                faceMap[i] = EDBM_face_at_index(em, DM_origindex_mface_mpoly(origFaceIndices, origPolyIndices, i));
429
473
 
430
474
        edgeMap = MEM_mallocN(numOfEdges * sizeof(BMEdge *), "unwrap_edit_edge_map");
431
475
 
432
476
        /* map subsurfed edges to original editEdges */
433
477
        for (i = 0; i < numOfEdges; i++) {
434
478
                /* not all edges correspond to an old edge */
435
 
                edgeMap[i] = (origEdgeIndices[i] != -1) ?
 
479
                edgeMap[i] = (origEdgeIndices[i] != ORIGINDEX_NONE) ?
436
480
                             EDBM_edge_at_index(em, origEdgeIndices[i]) : NULL;
437
481
        }
438
482
 
439
 
        EDBM_index_arrays_free(em);
440
 
 
441
483
        /* Prepare and feed faces to the solver */
442
484
        for (i = 0; i < numOfFaces; i++) {
443
485
                ParamKey key, vkeys[4];
445
487
                float *co[4];
446
488
                float *uv[4];
447
489
                BMFace *origFace = faceMap[i];
448
 
                
 
490
 
449
491
                face = subsurfedFaces + i;
450
492
 
451
493
                if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
471
513
                
472
514
                /* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus
473
515
                 * flushing the solution to the edit mesh. */
474
 
                texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em);
475
 
                texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em);
476
 
                texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em);
477
 
                texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em);
 
516
                texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em, cd_loop_uv_offset);
 
517
                texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em, cd_loop_uv_offset);
 
518
                texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em, cd_loop_uv_offset);
 
519
                texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em, cd_loop_uv_offset);
478
520
 
479
521
                param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
480
522
        }
512
554
        wmTimer *timer;
513
555
} MinStretch;
514
556
 
515
 
static int minimize_stretch_init(bContext *C, wmOperator *op)
 
557
static bool minimize_stretch_init(bContext *C, wmOperator *op)
516
558
{
517
559
        Scene *scene = CTX_data_scene(C);
518
560
        Object *obedit = CTX_data_edit_object(C);
519
561
        BMEditMesh *em = BMEdit_FromObject(obedit);
520
562
        MinStretch *ms;
521
563
        int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
522
 
        short implicit = 1;
 
564
        bool implicit = true;
523
565
 
524
566
        if (!uvedit_have_selection(scene, em, implicit)) {
525
 
                return 0;
 
567
                return false;
526
568
        }
527
569
 
528
570
        ms = MEM_callocN(sizeof(MinStretch), "MinStretch");
532
574
        ms->blend = RNA_float_get(op->ptr, "blend");
533
575
        ms->iterations = RNA_int_get(op->ptr, "iterations");
534
576
        ms->i = 0;
535
 
        ms->handle = construct_param_handle(scene, em, implicit, fill_holes, 1, 1);
 
577
        ms->handle = construct_param_handle(scene, obedit, em, implicit, fill_holes, 1, 1);
536
578
        ms->lasttime = PIL_check_seconds_timer();
537
579
 
538
580
        param_stretch_begin(ms->handle);
541
583
 
542
584
        op->customdata = ms;
543
585
 
544
 
        return 1;
 
586
        return true;
545
587
}
546
588
 
547
589
static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interactive)
561
603
                param_flush(ms->handle);
562
604
 
563
605
                if (sa) {
564
 
                        BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f", ms->blend);
 
606
                        BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f (Press + and -, or scroll wheel to set)", ms->blend);
565
607
                        ED_area_headerprint(sa, str);
566
608
                }
567
609
 
644
686
                        return OPERATOR_FINISHED;
645
687
                case PADPLUSKEY:
646
688
                case WHEELUPMOUSE:
647
 
                        if (ms->blend < 0.95f) {
648
 
                                ms->blend += 0.1f;
649
 
                                ms->lasttime = 0.0f;
650
 
                                RNA_float_set(op->ptr, "blend", ms->blend);
651
 
                                minimize_stretch_iteration(C, op, 1);
 
689
                        if (event->val == KM_PRESS) {
 
690
                                if (ms->blend < 0.95f) {
 
691
                                        ms->blend += 0.1f;
 
692
                                        ms->lasttime = 0.0f;
 
693
                                        RNA_float_set(op->ptr, "blend", ms->blend);
 
694
                                        minimize_stretch_iteration(C, op, 1);
 
695
                                }
652
696
                        }
653
697
                        break;
654
698
                case PADMINUS:
655
699
                case WHEELDOWNMOUSE:
656
 
                        if (ms->blend > 0.05f) {
657
 
                                ms->blend -= 0.1f;
658
 
                                ms->lasttime = 0.0f;
659
 
                                RNA_float_set(op->ptr, "blend", ms->blend);
660
 
                                minimize_stretch_iteration(C, op, 1);
 
700
                        if (event->val == KM_PRESS) {
 
701
                                if (ms->blend > 0.05f) {
 
702
                                        ms->blend -= 0.1f;
 
703
                                        ms->lasttime = 0.0f;
 
704
                                        RNA_float_set(op->ptr, "blend", ms->blend);
 
705
                                        minimize_stretch_iteration(C, op, 1);
 
706
                                }
661
707
                        }
662
708
                        break;
663
709
                case TIMER:
715
761
        Object *obedit = CTX_data_edit_object(C);
716
762
        BMEditMesh *em = BMEdit_FromObject(obedit);
717
763
        ParamHandle *handle;
718
 
        short implicit = 1;
 
764
        bool implicit = true;
719
765
 
720
766
        if (!uvedit_have_selection(scene, em, implicit)) {
721
767
                return OPERATOR_CANCELLED;
722
768
        }
723
769
 
724
 
        if (RNA_struct_property_is_set(op->ptr, "margin")) {
 
770
        if (RNA_struct_property_is_set(op->ptr, "margin"))
725
771
                scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
726
 
        }
727
 
        else {
 
772
        else
728
773
                RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
729
 
        }
730
774
 
731
 
        handle = construct_param_handle(scene, em, implicit, 0, 1, 1);
 
775
        handle = construct_param_handle(scene, obedit, em, implicit, 0, 1, 1);
732
776
        param_pack(handle, scene->toolsettings->uvcalc_margin);
733
777
        param_flush(handle);
734
778
        param_delete(handle);
744
788
        /* identifiers */
745
789
        ot->name = "Pack Islands";
746
790
        ot->idname = "UV_OT_pack_islands";
 
791
        ot->description = "Transform all islands so that they fill up the UV space as much as possible";
 
792
 
747
793
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
748
794
        
749
795
        /* api callbacks */
751
797
        ot->poll = ED_operator_uvedit;
752
798
 
753
799
        /* properties */
754
 
        RNA_def_float_factor(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
 
800
        RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
755
801
}
756
802
 
757
803
/* ******************** Average Islands Scale operator **************** */
762
808
        Object *obedit = CTX_data_edit_object(C);
763
809
        BMEditMesh *em = BMEdit_FromObject(obedit);
764
810
        ParamHandle *handle;
765
 
        short implicit = 1;
 
811
        bool implicit = true;
766
812
 
767
813
        if (!uvedit_have_selection(scene, em, implicit)) {
768
814
                return OPERATOR_CANCELLED;
769
815
        }
770
816
 
771
 
        handle = construct_param_handle(scene, em, implicit, 0, 1, 1);
 
817
        handle = construct_param_handle(scene, obedit, em, implicit, 0, 1, 1);
772
818
        param_average(handle);
773
819
        param_flush(handle);
774
820
        param_delete(handle);
784
830
        /* identifiers */
785
831
        ot->name = "Average Islands Scale";
786
832
        ot->idname = "UV_OT_average_islands_scale";
 
833
        ot->description = "Average the size of separate UV islands, based on their area in 3D space";
 
834
 
787
835
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
788
836
        
789
837
        /* api callbacks */
800
848
        BMEditMesh *em = BMEdit_FromObject(obedit);
801
849
        short abf = scene->toolsettings->unwrapper == 0;
802
850
        short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
803
 
        short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
 
851
        short use_subsurf;
 
852
 
 
853
        modifier_unwrap_state(obedit, scene, &use_subsurf);
804
854
 
805
855
        if (!ED_uvedit_test(obedit)) {
806
856
                return;
807
857
        }
808
858
 
809
859
        if (use_subsurf)
810
 
                liveHandle = construct_param_handle_subsurfed(scene, em, fillholes, 0, 1);
 
860
                liveHandle = construct_param_handle_subsurfed(scene, obedit, em, fillholes, FALSE, TRUE);
811
861
        else
812
 
                liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1);
 
862
                liveHandle = construct_param_handle(scene, obedit, em, FALSE, fillholes, FALSE, TRUE);
813
863
 
814
864
        param_lscm_begin(liveHandle, PARAM_TRUE, abf);
815
865
}
837
887
{
838
888
        BMEditMesh *em = BMEdit_FromObject(obedit);
839
889
 
840
 
    if (scene->toolsettings->edge_mode_live_unwrap &&
841
 
        CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
842
 
        ED_unwrap_lscm(scene, obedit, FALSE); /* unwrap all not just sel */
843
 
    }
 
890
        if (scene->toolsettings->edge_mode_live_unwrap &&
 
891
            CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV))
 
892
        {
 
893
                ED_unwrap_lscm(scene, obedit, FALSE); /* unwrap all not just sel */
 
894
        }
844
895
}
845
896
 
846
897
/*************** UV Map Common Transforms *****************/
855
906
static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, 
856
907
                                    Object *ob, BMEditMesh *em)
857
908
{
858
 
        BMFace *efa;
859
 
        BMLoop *l;
860
 
        BMIter iter, liter;
861
 
        float min[3], max[3], *cursx;
862
909
        int around = (v3d) ? v3d->around : V3D_CENTER;
863
910
 
864
911
        /* only operates on the edit object - this is all that's needed now */
865
912
 
866
913
        switch (around) {
867
914
                case V3D_CENTER: /* bounding box center */
868
 
                        min[0] = min[1] = min[2] = 1e20f;
869
 
                        max[0] = max[1] = max[2] = -1e20f;
 
915
                {
 
916
                        BMFace *efa;
 
917
                        BMLoop *l;
 
918
                        BMIter iter, liter;
 
919
                        float min[3], max[3];
 
920
 
 
921
                        INIT_MINMAX(min, max);
870
922
                        
871
923
                        BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
872
924
                                if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
873
925
                                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
874
 
                                                DO_MINMAX(l->v->co, min, max);
 
926
                                                minmax_v3v3_v3(min, max, l->v->co);
875
927
                                        }
876
928
                                }
877
929
                        }
878
930
                        mid_v3_v3v3(result, min, max);
879
931
                        break;
880
 
 
881
 
                case V3D_CURSOR: /*cursor center*/ 
882
 
                        cursx = give_cursor(scene, v3d);
 
932
                }
 
933
                case V3D_CURSOR:  /* cursor center */
 
934
                {
 
935
                        const float *curs = give_cursor(scene, v3d);
883
936
                        /* shift to objects world */
884
 
                        result[0] = cursx[0] - ob->obmat[3][0];
885
 
                        result[1] = cursx[1] - ob->obmat[3][1];
886
 
                        result[2] = cursx[2] - ob->obmat[3][2];
 
937
                        sub_v3_v3v3(result, curs, ob->obmat[3]);
887
938
                        break;
888
 
 
889
 
                case V3D_LOCAL: /*object center*/
890
 
                case V3D_CENTROID: /* multiple objects centers, only one object here*/
 
939
                }
 
940
                case V3D_LOCAL:     /* object center */
 
941
                case V3D_CENTROID:  /* multiple objects centers, only one object here*/
891
942
                default:
892
 
                        result[0] = result[1] = result[2] = 0.0;
 
943
                        zero_v3(result);
893
944
                        break;
894
945
        }
895
946
}
896
947
 
897
 
static void uv_map_rotation_matrix(float result[][4], RegionView3D *rv3d, Object *ob,
 
948
static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Object *ob,
898
949
                                   float upangledeg, float sideangledeg, float radius)
899
950
{
900
951
        float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
925
976
        /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
926
977
        /* i wanted to keep the reason here, so we're rotating*/
927
978
        sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f;
928
 
        rotside[0][0] = (float)cos(sideangle);
929
 
        rotside[0][1] = -(float)sin(sideangle);
930
 
        rotside[1][0] = (float)sin(sideangle);
931
 
        rotside[1][1] = (float)cos(sideangle);
932
 
        rotside[2][2] = 1.0f;
 
979
        rotside[0][0] =  cosf(sideangle);
 
980
        rotside[0][1] = -sinf(sideangle);
 
981
        rotside[1][0] =  sinf(sideangle);
 
982
        rotside[1][1] =  cosf(sideangle);
 
983
        rotside[2][2] =  1.0f;
933
984
 
934
985
        upangle = (float)M_PI * upangledeg / 180.0f;
935
 
        rotup[1][1] = (float)cos(upangle) / radius;
936
 
        rotup[1][2] = -(float)sin(upangle) / radius;
937
 
        rotup[2][1] = (float)sin(upangle) / radius;
938
 
        rotup[2][2] = (float)cos(upangle) / radius;
939
 
        rotup[0][0] = (float)1.0f / radius;
 
986
        rotup[1][1] =  cosf(upangle) / radius;
 
987
        rotup[1][2] = -sinf(upangle) / radius;
 
988
        rotup[2][1] =  sinf(upangle) / radius;
 
989
        rotup[2][2] =  cosf(upangle) / radius;
 
990
        rotup[0][0] =  1.0f / radius;
940
991
 
941
992
        /* calculate transforms*/
942
993
        mul_serie_m4(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL);
999
1050
                              "Radius of the sphere or cylinder", 0.0001f, 100.0f);
1000
1051
}
1001
1052
 
1002
 
static void correct_uv_aspect(BMEditMesh *em)
 
1053
static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
1003
1054
{
1004
 
        BMFace *efa = BM_active_face_get(em->bm, TRUE);
1005
1055
        BMLoop *l;
1006
1056
        BMIter iter, liter;
1007
1057
        MLoopUV *luv;
1008
 
        float scale, aspx = 1.0f, aspy = 1.0f;
 
1058
        BMFace *efa;
 
1059
        float scale, aspx, aspy;
1009
1060
        
1010
 
        if (efa) {
1011
 
                MTexPoly *tf;
 
1061
        const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
1012
1062
 
1013
 
                tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1014
 
                ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
1015
 
        }
 
1063
        uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
1016
1064
        
1017
1065
        if (aspx == aspy)
1018
1066
                return;
1021
1069
                scale = aspy / aspx;
1022
1070
 
1023
1071
                BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1024
 
                        if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
 
1072
                        if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1025
1073
                                continue;
1026
1074
                        
1027
1075
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1028
 
                                luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1029
 
                                luv->uv[0] = ((luv->uv[0] - 0.5) * scale) + 0.5;
 
1076
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 
1077
                                luv->uv[0] = ((luv->uv[0] - 0.5f) * scale) + 0.5f;
1030
1078
                        }
1031
1079
                }
1032
1080
        }
1034
1082
                scale = aspx / aspy;
1035
1083
 
1036
1084
                BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1037
 
                        if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
 
1085
                        if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1038
1086
                                continue;
1039
1087
                        
1040
1088
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1041
 
                                luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1042
 
                                luv->uv[1] = ((luv->uv[1] - 0.5) * scale) + 0.5;
 
1089
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 
1090
                                luv->uv[1] = ((luv->uv[1] - 0.5f) * scale) + 0.5f;
1043
1091
                        }
1044
1092
                }
1045
1093
        }
1057
1105
                        "Scale UV coordinates to bounds after unwrapping");
1058
1106
}
1059
1107
 
1060
 
static void uv_map_clip_correct(BMEditMesh *em, wmOperator *op)
 
1108
static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOperator *op)
1061
1109
{
1062
1110
        BMFace *efa;
1063
1111
        BMLoop *l;
1068
1116
        int clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds");
1069
1117
        int scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds");
1070
1118
 
 
1119
        const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 
1120
 
1071
1121
        /* correct for image aspect ratio */
1072
1122
        if (correct_aspect)
1073
 
                correct_uv_aspect(em);
 
1123
                correct_uv_aspect(scene, ob, em);
1074
1124
 
1075
1125
        if (scale_to_bounds) {
1076
1126
                INIT_MINMAX2(min, max);
1080
1130
                                continue;
1081
1131
 
1082
1132
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1083
 
                                luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1084
 
                                DO_MINMAX2(luv->uv, min, max);
 
1133
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 
1134
                                minmax_v2v2_v2(min, max, luv->uv);
1085
1135
                        }
1086
1136
                }
1087
1137
                
1099
1149
                                continue;
1100
1150
 
1101
1151
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1102
 
                                luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1152
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1103
1153
                                
1104
1154
                                luv->uv[0] = (luv->uv[0] - min[0]) * dx;
1105
1155
                                luv->uv[1] = (luv->uv[1] - min[1]) * dy;
1113
1163
                                continue;
1114
1164
 
1115
1165
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1116
 
                                luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1166
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1117
1167
                                CLAMP(luv->uv[0], 0.0f, 1.0f);
1118
1168
                                CLAMP(luv->uv[1], 0.0f, 1.0f);
1119
1169
                        }
1131
1181
 
1132
1182
        const short fill_holes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
1133
1183
        const short correct_aspect = !(scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT);
1134
 
        const short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
 
1184
        short use_subsurf;
 
1185
 
 
1186
        modifier_unwrap_state(obedit, scene, &use_subsurf);
1135
1187
 
1136
1188
        if (use_subsurf)
1137
 
                handle = construct_param_handle_subsurfed(scene, em, fill_holes, sel, correct_aspect);
 
1189
                handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect);
1138
1190
        else
1139
 
                handle = construct_param_handle(scene, em, 0, fill_holes, sel, correct_aspect);
 
1191
                handle = construct_param_handle(scene, obedit, em, FALSE, fill_holes, sel, correct_aspect);
1140
1192
 
1141
1193
        param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
1142
1194
        param_lscm_solve(handle);
1159
1211
        int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
1160
1212
        int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
1161
1213
        int use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
1162
 
        int subsurf_level = RNA_int_get(op->ptr, "uv_subsurf_level");
1163
 
        float obsize[3], unitsize[3] = {1.0f, 1.0f, 1.0f};
1164
 
        short implicit = 0;
 
1214
        short use_subsurf_final;
 
1215
        float obsize[3];
 
1216
        bool implicit = false;
1165
1217
 
1166
1218
        if (!uvedit_have_selection(scene, em, implicit)) {
1167
1219
                return OPERATOR_CANCELLED;
1173
1225
        }
1174
1226
 
1175
1227
        mat4_to_size(obsize, obedit->obmat);
1176
 
        if (!compare_v3v3(obsize, unitsize, 1e-4f))
1177
 
                BKE_report(op->reports, RPT_INFO, "Object scale is not 1.0. Unwrap will operate on a non-scaled version of the mesh.");
 
1228
        if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f))
 
1229
                BKE_report(op->reports, RPT_INFO,
 
1230
                           "Object has non-uniform scale, unwrap will operate on a non-scaled version of the mesh");
1178
1231
 
1179
1232
        /* remember last method for live unwrap */
1180
 
        if(RNA_struct_property_is_set(op->ptr, "method"))
 
1233
        if (RNA_struct_property_is_set(op->ptr, "method"))
1181
1234
                scene->toolsettings->unwrapper = method;
1182
 
        
1183
 
        scene->toolsettings->uv_subsurf_level = subsurf_level;
 
1235
        else
 
1236
                RNA_enum_set(op->ptr, "method", scene->toolsettings->unwrapper);
 
1237
 
 
1238
        /* remember packing marging */
 
1239
        if (RNA_struct_property_is_set(op->ptr, "margin"))
 
1240
                scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin");
 
1241
        else
 
1242
                RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
1184
1243
 
1185
1244
        if (fill_holes) scene->toolsettings->uvcalc_flag |=  UVCALC_FILLHOLES;
1186
1245
        else scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES;
1191
1250
        if (use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
1192
1251
        else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
1193
1252
 
 
1253
        /* double up the check here but better keep ED_unwrap_lscm interface simple and not
 
1254
         * pass operator for warning append */
 
1255
        modifier_unwrap_state(obedit, scene, &use_subsurf_final);
 
1256
        if (use_subsurf != use_subsurf_final)
 
1257
                BKE_report(op->reports, RPT_INFO, "Subsurf modifier needs to be first to work with unwrap");
 
1258
 
1194
1259
        /* execute unwrap */
1195
1260
        ED_unwrap_lscm(scene, obedit, TRUE);
1196
1261
 
1205
1270
        static EnumPropertyItem method_items[] = {
1206
1271
                {0, "ANGLE_BASED", 0, "Angle Based", ""},
1207
1272
                {1, "CONFORMAL", 0, "Conformal", ""},
1208
 
                {0, NULL, 0, NULL, NULL}};
 
1273
                {0, NULL, 0, NULL, NULL}
 
1274
        };
1209
1275
 
1210
1276
        /* identifiers */
1211
1277
        ot->name = "Unwrap";
1224
1290
                        "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
1225
1291
        RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
1226
1292
                        "Map UVs taking image aspect ratio into account");
1227
 
        RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Data",
 
1293
        RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Modifier",
1228
1294
                        "Map UVs taking vertex position after subsurf into account");
1229
 
        RNA_def_int(ot->srna, "uv_subsurf_level", 1, 1, 6, "SubSurf Target",
1230
 
                    "Number of times to subdivide before calculating UVs", 1, 6);
 
1295
        RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
1231
1296
}
1232
1297
 
1233
1298
/**************** Project From View operator **************/
1246
1311
        MLoopUV *luv;
1247
1312
        float rotmat[4][4];
1248
1313
 
 
1314
        int cd_loop_uv_offset;
 
1315
 
1249
1316
        /* add uvs if they don't exist yet */
1250
1317
        if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1251
1318
                return OPERATOR_CANCELLED;
1252
1319
        }
1253
1320
 
 
1321
        cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 
1322
 
1254
1323
        /* establish the camera object, so we can default to view mapping if anything is wrong with it */
1255
1324
        if ((rv3d->persp == RV3D_CAMOB) && (v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
1256
1325
                camera = v3d->camera->data;
1264
1333
                                continue;
1265
1334
 
1266
1335
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1267
 
                                luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1268
 
                                project_from_view_ortho(luv->uv, l->v->co, rotmat);
 
1336
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 
1337
                                BLI_uvproject_from_view_ortho(luv->uv, l->v->co, rotmat);
1269
1338
                        }
1270
1339
                }
1271
1340
        }
1272
1341
        else if (camera) {
1273
 
                struct UvCameraInfo *uci = project_camera_info(v3d->camera, obedit->obmat, scene->r.xsch, scene->r.ysch);
 
1342
                struct ProjCameraInfo *uci = BLI_uvproject_camera_info(v3d->camera, obedit->obmat, scene->r.xsch, scene->r.ysch);
1274
1343
                
1275
1344
                if (uci) {
1276
1345
                        BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1278
1347
                                        continue;
1279
1348
 
1280
1349
                                BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1281
 
                                        luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1282
 
                                        project_from_camera(luv->uv, l->v->co, uci);
 
1350
                                        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 
1351
                                        BLI_uvproject_from_camera(luv->uv, l->v->co, uci);
1283
1352
                                }
1284
1353
                        }
1285
1354
                        
1294
1363
                                continue;
1295
1364
 
1296
1365
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1297
 
                                luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
1298
 
                                project_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
 
1366
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 
1367
                                BLI_uvproject_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
1299
1368
                        }
1300
1369
                }
1301
1370
        }
1302
1371
 
1303
 
        uv_map_clip_correct(em, op);
 
1372
        uv_map_clip_correct(scene, obedit, em, op);
1304
1373
 
1305
1374
        DAG_id_tag_update(obedit->data, 0);
1306
1375
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1318
1387
        return (rv3d != NULL);
1319
1388
}
1320
1389
 
1321
 
void UV_OT_from_view(wmOperatorType *ot)
 
1390
void UV_OT_project_from_view(wmOperatorType *ot)
1322
1391
{
1323
1392
        /* identifiers */
1324
1393
        ot->name = "Project From View";
1325
1394
        ot->idname = "UV_OT_project_from_view";
 
1395
        ot->description = "Project the UV vertices of the mesh as seen in current 3D view";
 
1396
 
1326
1397
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1327
1398
        
1328
1399
        /* api callbacks */
1362
1433
        /* identifiers */
1363
1434
        ot->name = "Reset";
1364
1435
        ot->idname = "UV_OT_reset";
 
1436
        ot->description = "Reset UV projection";
 
1437
 
1365
1438
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1366
1439
        
1367
1440
        /* api callbacks */
1390
1463
        BMLoop *l;
1391
1464
        BMIter liter;
1392
1465
        MLoopUV *luv;
1393
 
        float **uvs = NULL;
1394
 
        BLI_array_fixedstack_declare(uvs, BM_NGON_STACK_SIZE, efa->len, __func__);
 
1466
        float **uvs = BLI_array_alloca(uvs, efa->len);
1395
1467
        float dx;
1396
1468
        int i, mi;
1397
1469
 
1398
 
        i = 0;
1399
 
        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1400
 
                luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1470
        const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 
1471
 
 
1472
        BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
 
1473
                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1401
1474
                uvs[i] = luv->uv;
1402
 
                i++;
1403
1475
        }
1404
1476
 
1405
1477
        mi = 0;
1411
1483
                if (i != mi) {
1412
1484
                        dx = uvs[mi][0] - uvs[i][0];
1413
1485
                        if (dx > 0.5f) uvs[i][0] += 1.0f;
1414
 
                } 
1415
 
        } 
1416
 
 
1417
 
        BLI_array_fixedstack_free(uvs);
 
1486
                }
 
1487
        }
1418
1488
}
1419
1489
 
1420
1490
static int sphere_project_exec(bContext *C, wmOperator *op)
1429
1499
        MLoopUV *luv;
1430
1500
        float center[3], rotmat[4][4];
1431
1501
 
 
1502
        int cd_loop_uv_offset;
 
1503
 
1432
1504
        /* add uvs if they don't exist yet */
1433
1505
        if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1434
1506
                return OPERATOR_CANCELLED;
1435
1507
        }
1436
1508
 
 
1509
        cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 
1510
 
1437
1511
        uv_map_transform(C, op, center, rotmat);
1438
1512
 
1439
1513
        BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1441
1515
                        continue;
1442
1516
 
1443
1517
                BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1444
 
                        luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1518
                        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1445
1519
 
1446
1520
                        uv_sphere_project(luv->uv, l->v->co, center, rotmat);
1447
1521
                }
1450
1524
                uv_map_mirror(em, efa, tf);
1451
1525
        }
1452
1526
 
1453
 
        uv_map_clip_correct(em, op);
 
1527
        uv_map_clip_correct(scene, obedit, em, op);
1454
1528
 
1455
1529
        DAG_id_tag_update(obedit->data, 0);
1456
1530
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1463
1537
        /* identifiers */
1464
1538
        ot->name = "Sphere Projection";
1465
1539
        ot->idname = "UV_OT_sphere_project";
 
1540
        ot->description = "Project the UV vertices of the mesh over the curved surface of a sphere";
 
1541
 
1466
1542
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1467
1543
        
1468
1544
        /* api callbacks */
1502
1578
        MLoopUV *luv;
1503
1579
        float center[3], rotmat[4][4];
1504
1580
 
 
1581
        int cd_loop_uv_offset;
 
1582
 
1505
1583
        /* add uvs if they don't exist yet */
1506
1584
        if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1507
1585
                return OPERATOR_CANCELLED;
1508
1586
        }
1509
1587
 
 
1588
        cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 
1589
 
1510
1590
        uv_map_transform(C, op, center, rotmat);
1511
1591
 
1512
1592
        BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1513
 
                tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1514
1593
                if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
1515
1594
                        continue;
1516
1595
                
1517
1596
                BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1518
 
                        luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1597
                        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1519
1598
 
1520
1599
                        uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
1521
1600
                }
1522
1601
 
 
1602
                tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
1523
1603
                uv_map_mirror(em, efa, tf);
1524
1604
        }
1525
1605
 
1526
 
        uv_map_clip_correct(em, op);
 
1606
        uv_map_clip_correct(scene, obedit, em, op);
1527
1607
 
1528
1608
        DAG_id_tag_update(obedit->data, 0);
1529
1609
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1536
1616
        /* identifiers */
1537
1617
        ot->name = "Cylinder Projection";
1538
1618
        ot->idname = "UV_OT_cylinder_project";
 
1619
        ot->description = "Project the UV vertices of the mesh over the curved wall of a cylinder";
 
1620
 
1539
1621
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1540
1622
        
1541
1623
        /* api callbacks */
1562
1644
        float cube_size, *loc, dx, dy;
1563
1645
        int cox, coy;
1564
1646
 
 
1647
        int cd_loop_uv_offset;
 
1648
 
1565
1649
        /* add uvs if they don't exist yet */
1566
1650
        if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
1567
1651
                return OPERATOR_CANCELLED;
1568
1652
        }
1569
1653
 
 
1654
        cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 
1655
 
1570
1656
        loc = obedit->obmat[3];
1571
1657
        cube_size = RNA_float_get(op->ptr, "cube_size");
1572
1658
 
1584
1670
 
1585
1671
                dx = dy = 0;
1586
1672
                BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1587
 
                        luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1673
                        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
1588
1674
 
1589
1675
                        luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]);
1590
1676
                        luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]);
1601
1687
                }
1602
1688
        }
1603
1689
 
1604
 
        uv_map_clip_correct(em, op);
 
1690
        uv_map_clip_correct(scene, obedit, em, op);
1605
1691
 
1606
1692
        DAG_id_tag_update(obedit->data, 0);
1607
1693
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1614
1700
        /* identifiers */
1615
1701
        ot->name = "Cube Projection";
1616
1702
        ot->idname = "UV_OT_cube_project";
 
1703
        ot->description = "Project the UV vertices of the mesh over the six faces of a cube";
 
1704
 
1617
1705
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1618
1706
        
1619
1707
        /* api callbacks */