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

« back to all changes in this revision

Viewing changes to source/blender/editors/uvedit/uvedit_smart_stitch.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:
46
46
#include "BLI_math_vector.h"
47
47
#include "BLI_string.h"
48
48
 
 
49
#include "BIF_gl.h"
 
50
 
49
51
#include "BKE_context.h"
50
52
#include "BKE_customdata.h"
51
53
#include "BKE_depsgraph.h"
55
57
#include "ED_mesh.h"
56
58
#include "ED_uvedit.h"
57
59
#include "ED_screen.h"
 
60
#include "ED_space_api.h"
58
61
 
59
62
#include "RNA_access.h"
60
63
#include "RNA_define.h"
63
66
#include "WM_types.h"
64
67
 
65
68
#include "UI_view2d.h"
 
69
#include "UI_resources.h"
66
70
 
67
71
#include "uvedit_intern.h"
68
72
 
69
73
/* ********************** smart stitch operator *********************** */
70
74
 
 
75
/* object that stores display data for previewing before confirming stitching */
 
76
typedef struct StitchPreviewer {
 
77
        /* here we'll store the preview triangle indices of the mesh */
 
78
        float *preview_polys;
 
79
        /* uvs per polygon. */
 
80
        unsigned int *uvs_per_polygon;
 
81
        /*number of preview polygons */
 
82
        unsigned int num_polys;
 
83
        /* preview data. These will be either the previewed vertices or edges depending on stitch mode settings */
 
84
        float *preview_stitchable;
 
85
        float *preview_unstitchable;
 
86
        /* here we'll store the number of elements to be drawn */
 
87
        unsigned int num_stitchable;
 
88
        unsigned int num_unstitchable;
 
89
        unsigned int preview_uvs;
 
90
        /* ...and here we'll store the static island triangles*/
 
91
        float *static_tris;
 
92
        unsigned int num_static_tris;
 
93
} StitchPreviewer;
 
94
 
71
95
 
72
96
struct IslandStitchData;
73
97
 
76
100
typedef struct IslandStitchData {
77
101
        /* rotation can be used only for edges, for vertices there is no such notion */
78
102
        float rotation;
 
103
        float rotation_neg;
79
104
        float translation[2];
80
105
        /* Used for rotation, the island will rotate around this point */
81
106
        float medianPoint[2];
82
107
        int numOfElements;
83
108
        int num_rot_elements;
 
109
        int num_rot_elements_neg;
84
110
        /* flag to remember if island has been added for preview */
85
111
        char addedForPreview;
86
112
        /* flag an island to be considered for determining static island */
100
126
        unsigned int uv1;
101
127
        unsigned int uv2;
102
128
        /* general use flag (Used to check if edge is boundary here, and propagates to adjacency elements) */
103
 
        char flag;
104
 
        /* element that guarantees element->face has the face on element->tfindex and element->tfindex+1 is the second uv */
 
129
        unsigned char flag;
 
130
        /* element that guarantees element->face has the edge on element->tfindex and element->tfindex+1 is the second uv */
105
131
        UvElement *element;
 
132
        /* next uv edge with the same exact vertices as this one.. Calculated at startup to save time */
 
133
        struct UvEdge *next;
 
134
        /* point to first of common edges. Needed for iteration */
 
135
        struct UvEdge *first;
106
136
} UvEdge;
107
137
 
108
138
 
109
139
/* stitch state object */
110
140
typedef struct StitchState {
 
141
        float aspect;
111
142
        /* use limit flag */
112
143
        char use_limit;
113
144
        /* limit to operator, same as original operator */
118
149
        char midpoints;
119
150
        /* editmesh, cached for use in modal handler */
120
151
        BMEditMesh *em;
 
152
        /* clear seams of stitched edges after stitch */
 
153
        char clear_seams;
121
154
        /* element map for getting info about uv connectivity */
122
155
        UvElementMap *element_map;
123
156
        /* edge container */
130
163
        float *normals;
131
164
        /* edge storage */
132
165
        UvEdge *edges;
 
166
        /* hash for quick lookup of edges */
 
167
        GHash *edge_hash;
133
168
 
134
169
        /* count of separate uvs and edges */
135
 
        int total_boundary_edges;
 
170
        int total_separate_edges;
136
171
        int total_separate_uvs;
137
172
        /* hold selection related information */
138
 
        UvElement **selection_stack;
 
173
        void **selection_stack;
139
174
        int selection_size;
140
175
        /* island that stays in place */
141
176
        int static_island;
142
177
        /* store number of primitives per face so that we can allocate the active island buffer later */
143
178
        unsigned int *tris_per_island;
 
179
 
 
180
        /* vert or edge mode used for stitching */
 
181
        char mode;
 
182
        /* handle for drawing */
 
183
        void *draw_handle;
 
184
        /* preview data */
 
185
        StitchPreviewer *stitch_preview;
144
186
} StitchState;
145
187
 
146
188
typedef struct PreviewPosition {
148
190
        int polycount_position;
149
191
} PreviewPosition;
150
192
/*
151
 
 * defines for UvElement flags
 
193
 * defines for UvElement/UcEdge flags
152
194
 */
153
195
#define STITCH_SELECTED 1
154
196
#define STITCH_STITCHABLE 2
158
200
 
159
201
#define STITCH_NO_PREVIEW -1
160
202
 
161
 
/* previewer stuff (see uvedit_intern.h for more info) */
162
 
static StitchPreviewer *_stitch_preview;
 
203
enum StitchModes {
 
204
        STITCH_VERT,
 
205
        STITCH_EDGE
 
206
};
163
207
 
164
208
/* constructor */
165
209
static StitchPreviewer *stitch_preview_init(void)
166
210
{
167
 
        _stitch_preview = MEM_mallocN(sizeof(StitchPreviewer), "stitch_previewer");
168
 
        _stitch_preview->preview_polys = NULL;
169
 
        _stitch_preview->preview_stitchable = NULL;
170
 
        _stitch_preview->preview_unstitchable = NULL;
171
 
        _stitch_preview->uvs_per_polygon = NULL;
172
 
 
173
 
        _stitch_preview->preview_uvs = 0;
174
 
        _stitch_preview->num_polys = 0;
175
 
        _stitch_preview->num_stitchable = 0;
176
 
        _stitch_preview->num_unstitchable = 0;
177
 
 
178
 
        _stitch_preview->static_tris = NULL;
179
 
 
180
 
        _stitch_preview->num_static_tris = 0;
181
 
 
182
 
        return _stitch_preview;
 
211
        StitchPreviewer *stitch_preview;
 
212
 
 
213
        stitch_preview = MEM_mallocN(sizeof(StitchPreviewer), "stitch_previewer");
 
214
        stitch_preview->preview_polys = NULL;
 
215
        stitch_preview->preview_stitchable = NULL;
 
216
        stitch_preview->preview_unstitchable = NULL;
 
217
        stitch_preview->uvs_per_polygon = NULL;
 
218
 
 
219
        stitch_preview->preview_uvs = 0;
 
220
        stitch_preview->num_polys = 0;
 
221
        stitch_preview->num_stitchable = 0;
 
222
        stitch_preview->num_unstitchable = 0;
 
223
 
 
224
        stitch_preview->static_tris = NULL;
 
225
 
 
226
        stitch_preview->num_static_tris = 0;
 
227
 
 
228
        return stitch_preview;
183
229
}
184
230
 
185
231
/* destructor...yeah this should be C++ :) */
186
 
static void stitch_preview_delete(void)
 
232
static void stitch_preview_delete(StitchPreviewer *stitch_preview)
187
233
{
188
 
        if (_stitch_preview) {
189
 
                if (_stitch_preview->preview_polys) {
190
 
                        MEM_freeN(_stitch_preview->preview_polys);
191
 
                        _stitch_preview->preview_polys = NULL;
192
 
                }
193
 
                if (_stitch_preview->uvs_per_polygon) {
194
 
                        MEM_freeN(_stitch_preview->uvs_per_polygon);
195
 
                        _stitch_preview->uvs_per_polygon = NULL;
196
 
                }
197
 
                if (_stitch_preview->preview_stitchable) {
198
 
                        MEM_freeN(_stitch_preview->preview_stitchable);
199
 
                        _stitch_preview->preview_stitchable = NULL;
200
 
                }
201
 
                if (_stitch_preview->preview_unstitchable) {
202
 
                        MEM_freeN(_stitch_preview->preview_unstitchable);
203
 
                        _stitch_preview->preview_unstitchable = NULL;
204
 
                }
205
 
                if (_stitch_preview->static_tris) {
206
 
                        MEM_freeN(_stitch_preview->static_tris);
207
 
                        _stitch_preview->static_tris = NULL;
208
 
                }
209
 
 
210
 
                MEM_freeN(_stitch_preview);
211
 
                _stitch_preview = NULL;
 
234
        if (stitch_preview) {
 
235
                if (stitch_preview->preview_polys) {
 
236
                        MEM_freeN(stitch_preview->preview_polys);
 
237
                        stitch_preview->preview_polys = NULL;
 
238
                }
 
239
                if (stitch_preview->uvs_per_polygon) {
 
240
                        MEM_freeN(stitch_preview->uvs_per_polygon);
 
241
                        stitch_preview->uvs_per_polygon = NULL;
 
242
                }
 
243
                if (stitch_preview->preview_stitchable) {
 
244
                        MEM_freeN(stitch_preview->preview_stitchable);
 
245
                        stitch_preview->preview_stitchable = NULL;
 
246
                }
 
247
                if (stitch_preview->preview_unstitchable) {
 
248
                        MEM_freeN(stitch_preview->preview_unstitchable);
 
249
                        stitch_preview->preview_unstitchable = NULL;
 
250
                }
 
251
                if (stitch_preview->static_tris) {
 
252
                        MEM_freeN(stitch_preview->static_tris);
 
253
                        stitch_preview->static_tris = NULL;
 
254
                }
 
255
                MEM_freeN(stitch_preview);
212
256
        }
213
257
}
214
258
 
215
 
 
216
 
/* "getter method" */
217
 
StitchPreviewer *uv_get_stitch_previewer(void)
218
 
{
219
 
        return _stitch_preview;
220
 
}
221
 
 
222
259
#define HEADER_LENGTH 256
223
260
 
224
261
/* This function updates the header of the UV editor when the stitch tool updates its settings */
225
 
static void stitch_update_header(StitchState *stitch_state, bContext *C)
 
262
static void stitch_update_header(StitchState *state, bContext *C)
226
263
{
227
 
        static char str[] = "(S)nap %s, (M)idpoints %s, (L)imit %.2f (Alt Wheel adjust) %s, Switch (I)sland, shift select vertices";
 
264
        static char str[] = "Mode(TAB) %s, (S)nap %s, (M)idpoints %s, (L)imit %.2f (Alt Wheel adjust) %s, Switch (I)sland, shift select vertices";
228
265
 
229
266
        char msg[HEADER_LENGTH];
230
267
        ScrArea *sa = CTX_wm_area(C);
231
268
 
232
269
        if (sa) {
233
270
                BLI_snprintf(msg, HEADER_LENGTH, str,
234
 
                             stitch_state->snap_islands ? "On" : "Off",
235
 
                             stitch_state->midpoints    ? "On" : "Off",
236
 
                             stitch_state->limit_dist,
237
 
                             stitch_state->use_limit    ? "On" : "Off");
 
271
                             state->mode == STITCH_VERT ? "Vertex" : "Edge",
 
272
                             state->snap_islands ? "On" : "Off",
 
273
                             state->midpoints    ? "On" : "Off",
 
274
                             state->limit_dist,
 
275
                             state->use_limit    ? "On" : "Off");
238
276
 
239
277
                ED_area_headerprint(sa, msg);
240
278
        }
250
288
        }
251
289
}
252
290
 
253
 
static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2])
 
291
static void stitch_uv_rotate(float mat[2][2], float medianPoint[2], float uv[2], float aspect)
254
292
{
255
293
        float uv_rotation_result[2];
256
294
 
257
 
        uv[0] -= medianPoint[0];
258
 
        uv[1] -= medianPoint[1];
259
 
 
260
 
        uv_rotation_result[0] = cos(rotation) * uv[0] - sin(rotation) * uv[1];
261
 
        uv_rotation_result[1] = sin(rotation) * uv[0] + cos(rotation) * uv[1];
262
 
 
263
 
        uv[0] = uv_rotation_result[0] + medianPoint[0];
264
 
        uv[1] = uv_rotation_result[1] + medianPoint[1];
 
295
        uv[1] /= aspect;
 
296
 
 
297
        sub_v2_v2(uv, medianPoint);
 
298
        mul_v2_m2v2(uv_rotation_result, mat, uv);
 
299
        add_v2_v2v2(uv, uv_rotation_result, medianPoint);
 
300
 
 
301
        uv[1] *= aspect;
265
302
}
266
303
 
 
304
/* check if two uvelements are stitchable. This should only operate on -different- separate UvElements */
267
305
static int stitch_check_uvs_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
268
306
{
269
307
        float limit;
270
 
        int do_limit;
271
308
 
272
309
        if (element_iter == element) {
273
310
                return 0;
274
311
        }
275
312
 
276
313
        limit = state->limit_dist;
277
 
        do_limit = state->use_limit;
278
 
 
279
 
        if (do_limit) {
280
 
                MLoopUV *luv_orig, *luv_iter;
281
 
                BMLoop *l_orig, *l_iter;
282
 
 
283
 
 
284
 
                l_orig = element->l;
285
 
                luv_orig = CustomData_bmesh_get(&state->em->bm->ldata, l_orig->head.data, CD_MLOOPUV);
286
 
                l_iter = element_iter->l;
287
 
                luv_iter = CustomData_bmesh_get(&state->em->bm->ldata, l_iter->head.data, CD_MLOOPUV);
288
 
 
289
 
                if (fabs(luv_orig->uv[0] - luv_iter->uv[0]) < limit &&
290
 
                    fabs(luv_orig->uv[1] - luv_iter->uv[1]) < limit)
291
 
                {
292
 
                        return 1;
293
 
                }
294
 
                else {
295
 
                        return 0;
296
 
                }
297
 
        }
298
 
        else {
299
 
                return 1;
300
 
        }
301
 
}
302
 
 
 
314
 
 
315
        if (state->use_limit) {
 
316
                MLoopUV *luv, *luv_iter;
 
317
                BMLoop *l;
 
318
 
 
319
 
 
320
                l = element->l;
 
321
                luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
322
                l = element_iter->l;
 
323
                luv_iter = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
324
 
 
325
                if (fabsf(luv->uv[0] - luv_iter->uv[0]) < limit &&
 
326
                    fabsf(luv->uv[1] - luv_iter->uv[1]) < limit)
 
327
                {
 
328
                        return 1;
 
329
                }
 
330
                else {
 
331
                        return 0;
 
332
                }
 
333
        }
 
334
        else {
 
335
                return 1;
 
336
        }
 
337
}
 
338
 
 
339
static int stitch_check_edges_stitchable(UvEdge *edge, UvEdge *edge_iter, StitchState *state)
 
340
{
 
341
        float limit;
 
342
 
 
343
        if (edge_iter == edge) {
 
344
                return 0;
 
345
        }
 
346
 
 
347
        limit = state->limit_dist;
 
348
 
 
349
        if (state->use_limit) {
 
350
                BMLoop *l;
 
351
                MLoopUV *luv_orig1, *luv_iter1;
 
352
                MLoopUV *luv_orig2, *luv_iter2;
 
353
 
 
354
                l = state->uvs[edge->uv1]->l;
 
355
                luv_orig1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
356
                l = state->uvs[edge_iter->uv1]->l;
 
357
                luv_iter1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
358
 
 
359
                l = state->uvs[edge->uv2]->l;
 
360
                luv_orig2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
361
                l = state->uvs[edge_iter->uv2]->l;
 
362
                luv_iter2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
363
 
 
364
                if (fabsf(luv_orig1->uv[0] - luv_iter1->uv[0]) < limit &&
 
365
                    fabsf(luv_orig1->uv[1] - luv_iter1->uv[1]) < limit &&
 
366
                    fabsf(luv_orig2->uv[0] - luv_iter2->uv[0]) < limit &&
 
367
                    fabsf(luv_orig2->uv[1] - luv_iter2->uv[1]) < limit)
 
368
                {
 
369
                        return 1;
 
370
                }
 
371
                else {
 
372
                        return 0;
 
373
                }
 
374
        }
 
375
        else {
 
376
                return 1;
 
377
        }
 
378
}
303
379
 
304
380
static int stitch_check_uvs_state_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
305
381
{
313
389
}
314
390
 
315
391
 
 
392
static int stitch_check_edges_state_stitchable(UvEdge *edge, UvEdge *edge_iter, StitchState *state)
 
393
{
 
394
        if ((state->snap_islands && edge->element->island == edge_iter->element->island) ||
 
395
            (!state->midpoints && edge->element->island == edge_iter->element->island))
 
396
        {
 
397
                return 0;
 
398
        }
 
399
 
 
400
        return stitch_check_edges_stitchable(edge, edge_iter, state);
 
401
}
 
402
 
316
403
/* calculate snapping for islands */
317
404
static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition *preview_position, StitchPreviewer *preview, IslandStitchData *island_stitch_data, int final)
318
405
{
319
406
        int i;
320
407
        UvElement *element;
321
408
 
322
 
        for (i = 0; i <  state->element_map->totalIslands; i++) {
 
409
        for (i = 0; i < state->element_map->totalIslands; i++) {
323
410
                if (island_stitch_data[i].addedForPreview) {
324
411
                        int numOfIslandUVs = 0, j;
 
412
                        int totelem = island_stitch_data[i].num_rot_elements_neg + island_stitch_data[i].num_rot_elements;
 
413
                        float rotation;
 
414
                        float rotation_mat[2][2];
325
415
 
326
416
                        /* check to avoid divide by 0 */
327
 
                        if (island_stitch_data[i].num_rot_elements > 0) {
 
417
                        if (island_stitch_data[i].num_rot_elements > 1)
328
418
                                island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements;
 
419
 
 
420
                        if (island_stitch_data[i].num_rot_elements_neg > 1)
 
421
                                island_stitch_data[i].rotation_neg /= island_stitch_data[i].num_rot_elements_neg;
 
422
 
 
423
                        if (island_stitch_data[i].numOfElements > 1) {
329
424
                                island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements;
330
425
                                island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements;
331
 
                        }
332
 
                        island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
333
 
                        island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
 
426
 
 
427
                                island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
 
428
                                island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
 
429
                        }
 
430
 
 
431
                        island_stitch_data[i].medianPoint[1] /= state->aspect;
 
432
                        if ((island_stitch_data[i].rotation + island_stitch_data[i].rotation_neg < (float)M_PI_2) ||
 
433
                            island_stitch_data[i].num_rot_elements == 0 || island_stitch_data[i].num_rot_elements_neg == 0)
 
434
                        {
 
435
                                rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements -
 
436
                                            island_stitch_data[i].rotation_neg *
 
437
                                            island_stitch_data[i].num_rot_elements_neg) / totelem;
 
438
                        }
 
439
                        else {
 
440
                                rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements +
 
441
                                            (2.0f * (float)M_PI - island_stitch_data[i].rotation_neg) *
 
442
                                            island_stitch_data[i].num_rot_elements_neg) / totelem;
 
443
                        }
 
444
 
 
445
                        rotate_m2(rotation_mat, rotation);
334
446
                        numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
335
447
                        element = &state->element_map->buf[state->element_map->islandIndices[i]];
336
448
                        for (j = 0; j < numOfIslandUVs; j++, element++) {
344
456
 
345
457
                                        if (final) {
346
458
 
347
 
                                                stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, luv->uv);
 
459
                                                stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint, luv->uv, state->aspect);
348
460
 
349
461
                                                add_v2_v2(luv->uv, island_stitch_data[i].translation);
350
462
                                        }
351
463
 
352
464
                                        else {
353
 
                                                int face_preview_pos = preview_position[BM_elem_index_get(element->face)].data_position;
354
 
 
355
 
                                                stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint,
356
 
                                                                 preview->preview_polys + face_preview_pos + 2 * element->tfindex);
 
465
 
 
466
                                                int face_preview_pos = preview_position[BM_elem_index_get(element->l->f)].data_position;
 
467
 
 
468
                                                stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint,
 
469
                                                                 preview->preview_polys + face_preview_pos + 2 * element->tfindex, state->aspect);
357
470
 
358
471
                                                add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->tfindex,
359
472
                                                          island_stitch_data[i].translation);
376
489
        int index1, index2;
377
490
        float rotation;
378
491
        MLoopUV *luv1, *luv2;
379
 
        BMLoop *l1, *l2;
380
492
 
381
493
        element1 = state->uvs[edge->uv1];
382
494
        element2 = state->uvs[edge->uv2];
383
495
 
384
 
        l1 = element1->l;
385
 
        luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l1->head.data, CD_MLOOPUV);
386
 
        l2 = element2->l;
387
 
        luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l2->head.data, CD_MLOOPUV);
388
 
 
389
 
        index1 = uvfinal_map[element1 - state->element_map->buf];
390
 
        index2 = uvfinal_map[element2 - state->element_map->buf];
391
 
 
 
496
        luv1 = CustomData_bmesh_get(&state->em->bm->ldata, element1->l->head.data, CD_MLOOPUV);
 
497
        luv2 = CustomData_bmesh_get(&state->em->bm->ldata, element2->l->head.data, CD_MLOOPUV);
 
498
 
 
499
        if (state->mode == STITCH_VERT) {
 
500
                index1 = uvfinal_map[element1 - state->element_map->buf];
 
501
                index2 = uvfinal_map[element2 - state->element_map->buf];
 
502
        }
 
503
        else {
 
504
                index1 = edge->uv1;
 
505
                index2 = edge->uv2;
 
506
        }
392
507
        /* the idea here is to take the directions of the edges and find the rotation between final and initial
393
508
         * direction. This, using inner and outer vector products, gives the angle. Directions are differences so... */
394
509
        uv1[0] = luv2->uv[0] - luv1->uv[0];
395
510
        uv1[1] = luv2->uv[1] - luv1->uv[1];
396
511
 
 
512
        uv1[1] /= state->aspect;
 
513
 
397
514
        uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
398
515
        uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
399
516
 
 
517
        uv2[1] /= state->aspect;
 
518
 
400
519
        normalize_v2(uv1);
401
520
        normalize_v2(uv2);
402
521
 
403
 
        edgecos = uv1[0] * uv2[0] + uv1[1] * uv2[1];
404
 
        edgesin = uv1[0] * uv2[1] - uv2[0] * uv1[1];
405
 
 
406
 
        rotation = (edgesin > 0) ? acos(MAX2(-1.0, MIN2(1.0, edgecos))) : -acos(MAX2(-1.0, MIN2(1.0, edgecos)));
407
 
 
408
 
        island_stitch_data[element1->island].num_rot_elements++;
409
 
        island_stitch_data[element1->island].rotation += rotation;
 
522
        edgecos = dot_v2v2(uv1, uv2);
 
523
        edgesin = cross_v2v2(uv1, uv2);
 
524
        rotation = acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
 
525
 
 
526
        if (edgesin > 0.0f) {
 
527
                island_stitch_data[element1->island].num_rot_elements++;
 
528
                island_stitch_data[element1->island].rotation += rotation;
 
529
        }
 
530
        else {
 
531
                island_stitch_data[element1->island].num_rot_elements_neg++;
 
532
                island_stitch_data[element1->island].rotation_neg += rotation;
 
533
        }
410
534
}
411
535
 
412
536
 
413
537
static void stitch_island_calculate_vert_rotation(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data)
414
538
{
415
 
        float edgecos = 1, edgesin = 0;
 
539
        float edgecos = 1.0f, edgesin = 0.0f;
416
540
        int index;
417
541
        UvElement *element_iter;
418
 
        float rotation = 0;
 
542
        float rotation = 0, rotation_neg = 0;
 
543
        int rot_elem = 0, rot_elem_neg = 0;
419
544
        BMLoop *l;
420
545
 
421
546
        if (element->island == state->static_island && !state->midpoints)
431
556
                if (element_iter->separate && stitch_check_uvs_state_stitchable(element, element_iter, state)) {
432
557
                        int index_tmp1, index_tmp2;
433
558
                        float normal[2];
434
 
                        /* easily possible*/
 
559
 
 
560
                        /* only calculate rotation against static island uv verts */
 
561
                        if (!state->midpoints && element_iter->island != state->static_island)
 
562
                                continue;
435
563
 
436
564
                        index_tmp1 = element_iter - state->element_map->buf;
437
565
                        index_tmp1 = state->map[index_tmp1];
441
569
                        negate_v2_v2(normal, state->normals + index_tmp2 * 2);
442
570
                        edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
443
571
                        edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
444
 
                        rotation += (edgesin > 0) ? acos(edgecos) : -acos(edgecos);
 
572
                        if (edgesin > 0.0f) {
 
573
                            rotation += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
 
574
                                rot_elem++;
 
575
                        }
 
576
                        else {
 
577
                            rotation_neg += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
 
578
                                rot_elem_neg++;
 
579
                        }
445
580
                }
446
581
        }
447
582
 
448
 
        if (state->midpoints)
449
 
                rotation /= 2.0;
450
 
        island_stitch_data[element->island].num_rot_elements++;
 
583
        if (state->midpoints) {
 
584
                rotation /= 2.0f;
 
585
                rotation_neg /= 2.0f;
 
586
        }
 
587
        island_stitch_data[element->island].num_rot_elements += rot_elem;
451
588
        island_stitch_data[element->island].rotation += rotation;
452
 
}
453
 
 
454
 
 
455
 
static void stitch_state_delete(StitchState *stitch_state)
456
 
{
457
 
        if (stitch_state) {
458
 
                if (stitch_state->element_map) {
459
 
                        EDBM_uv_element_map_free(stitch_state->element_map);
460
 
                }
461
 
                if (stitch_state->uvs) {
462
 
                        MEM_freeN(stitch_state->uvs);
463
 
                }
464
 
                if (stitch_state->selection_stack) {
465
 
                        MEM_freeN(stitch_state->selection_stack);
466
 
                }
467
 
                if (stitch_state->tris_per_island) {
468
 
                        MEM_freeN(stitch_state->tris_per_island);
469
 
                }
470
 
                if (stitch_state->map) {
471
 
                        MEM_freeN(stitch_state->map);
472
 
                }
473
 
                if (stitch_state->normals) {
474
 
                        MEM_freeN(stitch_state->normals);
475
 
                }
476
 
                if (stitch_state->edges) {
477
 
                        MEM_freeN(stitch_state->edges);
478
 
                }
479
 
                MEM_freeN(stitch_state);
480
 
        }
481
 
}
482
 
 
 
589
        island_stitch_data[element->island].num_rot_elements_neg += rot_elem_neg;
 
590
        island_stitch_data[element->island].rotation_neg += rotation_neg;
 
591
}
 
592
 
 
593
 
 
594
static void state_delete(StitchState *state)
 
595
{
 
596
        if (state) {
 
597
                if (state->element_map) {
 
598
                        EDBM_uv_element_map_free(state->element_map);
 
599
                }
 
600
                if (state->uvs) {
 
601
                        MEM_freeN(state->uvs);
 
602
                }
 
603
                if (state->selection_stack) {
 
604
                        MEM_freeN(state->selection_stack);
 
605
                }
 
606
                if (state->tris_per_island) {
 
607
                        MEM_freeN(state->tris_per_island);
 
608
                }
 
609
                if (state->map) {
 
610
                        MEM_freeN(state->map);
 
611
                }
 
612
                if (state->normals) {
 
613
                        MEM_freeN(state->normals);
 
614
                }
 
615
                if (state->edges) {
 
616
                        MEM_freeN(state->edges);
 
617
                }
 
618
                if (state->stitch_preview) {
 
619
                        stitch_preview_delete(state->stitch_preview);
 
620
                }
 
621
                if (state->edge_hash) {
 
622
                        BLI_ghash_free(state->edge_hash, NULL, NULL);
 
623
                }
 
624
                MEM_freeN(state);
 
625
        }
 
626
}
 
627
 
 
628
static void stitch_uv_edge_generate_linked_edges(GHash *edge_hash, StitchState *state)
 
629
{
 
630
        UvEdge *edges = state->edges;
 
631
        int *map = state->map;
 
632
        UvElementMap *element_map = state->element_map;
 
633
        UvElement *first_element = element_map->buf;
 
634
        int i;
 
635
 
 
636
        for (i = 0; i < state->total_separate_edges; i++) {
 
637
                UvEdge *edge = edges + i;
 
638
 
 
639
                if (edge->first)
 
640
                        continue;
 
641
 
 
642
                /* only boundary edges can be stitched. Yes. Sorry about that :p */
 
643
                if (edge->flag & STITCH_BOUNDARY) {
 
644
                        UvElement *element1 = state->uvs[edge->uv1];
 
645
                        UvElement *element2 = state->uvs[edge->uv2];
 
646
 
 
647
                        /* Now iterate through all faces and try to find edges sharing the same vertices */
 
648
                        UvElement *iter1 = element_map->vert[BM_elem_index_get(element1->l->v)];
 
649
                        UvEdge *last_set = edge;
 
650
                        int elemindex2 = BM_elem_index_get(element2->l->v);
 
651
 
 
652
                        edge->first = edge;
 
653
 
 
654
                        for (; iter1; iter1 = iter1->next) {
 
655
                                UvElement *iter2 = NULL;
 
656
 
 
657
                                /* check to see if other vertex of edge belongs to same vertex as */
 
658
                                if (BM_elem_index_get(iter1->l->next->v) == elemindex2)
 
659
                                        iter2 = ED_uv_element_get(element_map, iter1->l->f, iter1->l->next);
 
660
                                else if (BM_elem_index_get(iter1->l->prev->v) == elemindex2)
 
661
                                        iter2 = ED_uv_element_get(element_map, iter1->l->f, iter1->l->prev);
 
662
 
 
663
                                if (iter2) {
 
664
                                        int index1 = map[iter1 - first_element];
 
665
                                        int index2 = map[iter2 - first_element];
 
666
 
 
667
                                        /* make certain we do not have the same edge! */
 
668
                                        if (state->uvs[index2] != element2 && state->uvs[index1] != element1) {
 
669
                                                UvEdge edgetmp;
 
670
                                                UvEdge *edge2;
 
671
 
 
672
 
 
673
                                                /* make sure the indices are well behaved */
 
674
                                                if (index1 < index2) {
 
675
                                                        edgetmp.uv1 = index1;
 
676
                                                        edgetmp.uv2 = index2;
 
677
                                                }
 
678
                                                else {
 
679
                                                        edgetmp.uv1 = index2;
 
680
                                                        edgetmp.uv2 = index1;
 
681
                                                }
 
682
 
 
683
                                                /* get the edge from the hash */
 
684
                                                edge2 = BLI_ghash_lookup(edge_hash, &edgetmp);
 
685
 
 
686
                                                /* here I am taking care of non manifold case, assuming more than two matching edges.
 
687
                                                 * I am not too sure we want this though */
 
688
                                                last_set->next = edge2;
 
689
                                                last_set = edge2;
 
690
                                                /* set first, similarly to uv elements. Now we can iterate among common edges easily */
 
691
                                                edge2->first = edge;
 
692
                                        }
 
693
                                }
 
694
                        }
 
695
                }
 
696
                else {
 
697
                        /* so stitchability code works */
 
698
                        edge->first = edge;
 
699
                }
 
700
        }
 
701
}
483
702
 
484
703
 
485
704
/* checks for remote uvs that may be stitched with a certain uv, flags them if stitchable. */
496
715
 
497
716
        for (; element_iter; element_iter = element_iter->next) {
498
717
                if (element_iter->separate) {
499
 
                        if (element_iter == element) {
500
 
                                continue;
501
 
                        }
502
718
                        if (stitch_check_uvs_stitchable(element, element_iter, state)) {
503
719
                                island_stitch_data[element_iter->island].stitchableCandidate = 1;
504
720
                                island_stitch_data[element->island].stitchableCandidate = 1;
508
724
        }
509
725
}
510
726
 
 
727
static void determine_uv_edge_stitchability(UvEdge *edge, StitchState *state, IslandStitchData *island_stitch_data)
 
728
{
 
729
        UvEdge *edge_iter = edge->first;
 
730
 
 
731
        for (; edge_iter; edge_iter = edge_iter->next) {
 
732
                if (stitch_check_edges_stitchable(edge, edge_iter, state)) {
 
733
                        island_stitch_data[edge_iter->element->island].stitchableCandidate = 1;
 
734
                        island_stitch_data[edge->element->island].stitchableCandidate = 1;
 
735
                        edge->flag |= STITCH_STITCHABLE_CANDIDATE;
 
736
                }
 
737
        }
 
738
}
 
739
 
511
740
 
512
741
/* set preview buffer position of UV face in editface->tmp.l */
513
742
static void stitch_set_face_preview_buffer_position(BMFace *efa, StitchPreviewer *preview, PreviewPosition *preview_position)
525
754
/* setup face preview for all coincident uvs and their faces */
526
755
static void stitch_setup_face_preview_for_uv_group(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
527
756
                                                   PreviewPosition *preview_position) {
528
 
        StitchPreviewer *preview = uv_get_stitch_previewer();
 
757
        StitchPreviewer *preview = state->stitch_preview;
529
758
 
530
759
        /* static island does not change so returning immediately */
531
760
        if (state->snap_islands && !state->midpoints && state->static_island == element->island)
536
765
        }
537
766
 
538
767
        do {
539
 
                stitch_set_face_preview_buffer_position(element->face, preview, preview_position);
 
768
                stitch_set_face_preview_buffer_position(element->l->f, preview, preview_position);
540
769
                element = element->next;
541
770
        } while (element && !element->separate);
542
771
}
543
772
 
544
773
 
545
774
/* checks if uvs are indeed stitchable and registers so that they can be shown in preview */
546
 
static void stitch_validate_stichability(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
 
775
static void stitch_validate_uv_stichability(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
547
776
                                         PreviewPosition *preview_position) {
548
777
        UvElement *element_iter;
549
 
        StitchPreviewer *preview;
 
778
        StitchPreviewer *preview = state->stitch_preview;
550
779
        int vert_index;
551
780
        BMLoop *l;
552
781
 
554
783
 
555
784
        vert_index = BM_elem_index_get(l->v);
556
785
 
557
 
        preview = uv_get_stitch_previewer();
558
786
        element_iter = state->element_map->vert[vert_index];
559
787
 
560
788
        for (; element_iter; element_iter = element_iter->next) {
578
806
        }
579
807
}
580
808
 
 
809
 
 
810
static void stitch_validate_edge_stichability(UvEdge *edge, StitchState *state, IslandStitchData *island_stitch_data,
 
811
                                              PreviewPosition *preview_position) {
 
812
        UvEdge *edge_iter = edge->first;
 
813
        StitchPreviewer *preview = state->stitch_preview;
 
814
 
 
815
        for (; edge_iter; edge_iter = edge_iter->next) {
 
816
                if (edge_iter == edge)
 
817
                        continue;
 
818
                if (stitch_check_edges_state_stitchable(edge, edge_iter, state)) {
 
819
                        if ((edge_iter->element->island == state->static_island) || (edge->element->island == state->static_island)) {
 
820
                                edge->flag |= STITCH_STITCHABLE;
 
821
                                preview->num_stitchable++;
 
822
                                stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv1], state, island_stitch_data, preview_position);
 
823
                                stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv2], state, island_stitch_data, preview_position);
 
824
                                return;
 
825
                        }
 
826
                }
 
827
        }
 
828
 
 
829
        /* this can happen if the uvs to be stitched are not on a stitchable island */
 
830
        if (!(edge->flag & STITCH_STITCHABLE)) {
 
831
                preview->num_unstitchable++;
 
832
        }
 
833
}
 
834
 
 
835
 
 
836
static void stitch_propagate_uv_final_position(UvElement *element, int index, PreviewPosition *preview_position, UVVertAverage *final_position, StitchState *state, char final, Scene *scene)
 
837
{
 
838
        StitchPreviewer *preview = state->stitch_preview;
 
839
 
 
840
        if (element->flag & STITCH_STITCHABLE) {
 
841
                UvElement *element_iter = element;
 
842
                /* propagate to coincident uvs */
 
843
                do {
 
844
                        BMLoop *l;
 
845
                        MLoopUV *luv;
 
846
 
 
847
                        l = element_iter->l;
 
848
                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
849
 
 
850
                        element_iter->flag |= STITCH_PROCESSED;
 
851
                        /* either flush to preview or to the MTFace, if final */
 
852
                        if (final) {
 
853
                                copy_v2_v2(luv->uv, final_position[index].uv);
 
854
 
 
855
                                uvedit_uv_select_enable(state->em, scene, l, FALSE);
 
856
                        }
 
857
                        else {
 
858
                                int face_preview_pos = preview_position[BM_elem_index_get(element_iter->l->f)].data_position;
 
859
                                if (face_preview_pos != STITCH_NO_PREVIEW) {
 
860
                                        copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->tfindex,
 
861
                                                   final_position[index].uv);
 
862
                                }
 
863
                        }
 
864
 
 
865
                        /* end of calculations, keep only the selection flag */
 
866
                        if ( (!state->snap_islands) || ((!state->midpoints) && (element_iter->island == state->static_island))) {
 
867
                                element_iter->flag &= STITCH_SELECTED;
 
868
                        }
 
869
 
 
870
                        element_iter = element_iter->next;
 
871
                } while (element_iter && !element_iter->separate);
 
872
        }
 
873
}
 
874
 
581
875
/* main processing function. It calculates preview and final positions. */
582
876
static int stitch_process_data(StitchState *state, Scene *scene, int final)
583
877
{
587
881
        int previous_island = state->static_island;
588
882
        BMFace *efa;
589
883
        BMIter iter;
590
 
        UVVertAverage *final_position;
 
884
        UVVertAverage *final_position = NULL;
 
885
 
591
886
        char stitch_midpoints = state->midpoints;
592
887
        /* used to map uv indices to uvaverage indices for selection */
593
 
        unsigned int *uvfinal_map;
 
888
        unsigned int *uvfinal_map = NULL;
594
889
        /* per face preview position in preview buffer */
595
 
        PreviewPosition *preview_position;
 
890
        PreviewPosition *preview_position = NULL;
596
891
 
597
892
        /* cleanup previous preview */
598
 
        stitch_preview_delete();
599
 
        preview = stitch_preview_init();
 
893
        stitch_preview_delete(state->stitch_preview);
 
894
        preview = state->stitch_preview = stitch_preview_init();
600
895
        if (preview == NULL)
601
896
                return 0;
602
897
 
619
914
         *****************************************/
620
915
 
621
916
        for (i = 0; i < state->selection_size; i++) {
622
 
                UvElement *element = state->selection_stack[i];
623
 
                determine_uv_stitchability(element, state, island_stitch_data);
 
917
                if (state->mode == STITCH_VERT) {
 
918
                        UvElement *element = (UvElement *)state->selection_stack[i];
 
919
                        determine_uv_stitchability(element, state, island_stitch_data);
 
920
                }
 
921
                else {
 
922
                        UvEdge *edge = (UvEdge *)state->selection_stack[i];
 
923
                        determine_uv_edge_stitchability(edge, state, island_stitch_data);
 
924
                }
624
925
        }
625
926
 
626
927
        /* set static island to one that is added for preview */
634
935
        }
635
936
 
636
937
        for (i = 0; i < state->selection_size; i++) {
637
 
                UvElement *element = state->selection_stack[i];
638
 
                if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
639
 
                        element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
640
 
                        stitch_validate_stichability(element, state, island_stitch_data, preview_position);
 
938
                if (state->mode == STITCH_VERT) {
 
939
                        UvElement *element = (UvElement *)state->selection_stack[i];
 
940
                        if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
 
941
                                element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
 
942
                                stitch_validate_uv_stichability(element, state, island_stitch_data, preview_position);
 
943
                        }
 
944
                        else {
 
945
                                /* add to preview for unstitchable */
 
946
                                preview->num_unstitchable++;
 
947
                        }
641
948
                }
642
949
                else {
643
 
                        /* add to preview for unstitchable */
644
 
                        preview->num_unstitchable++;
 
950
                        UvEdge *edge = (UvEdge *)state->selection_stack[i];
 
951
                        if (edge->flag & STITCH_STITCHABLE_CANDIDATE) {
 
952
                                edge->flag &= ~STITCH_STITCHABLE_CANDIDATE;
 
953
                                stitch_validate_edge_stichability(edge, state, island_stitch_data, preview_position);
 
954
                        }
 
955
                        else {
 
956
                                preview->num_unstitchable++;
 
957
                        }
645
958
                }
646
959
        }
647
960
 
649
962
         *  Setup preview for stitchable islands *
650
963
         *****************************************/
651
964
        if (state->snap_islands) {
652
 
                for (i = 0; i <  state->element_map->totalIslands; i++) {
 
965
                for (i = 0; i < state->element_map->totalIslands; i++) {
653
966
                        if (island_stitch_data[i].addedForPreview) {
654
967
                                int numOfIslandUVs = 0, j;
655
968
                                UvElement *element;
656
969
                                numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
657
970
                                element = &state->element_map->buf[state->element_map->islandIndices[i]];
658
971
                                for (j = 0; j < numOfIslandUVs; j++, element++) {
659
 
                                        stitch_set_face_preview_buffer_position(element->face, preview, preview_position);
 
972
                                        stitch_set_face_preview_buffer_position(element->l->f, preview, preview_position);
660
973
                                }
661
974
                        }
662
975
                }
671
984
                MLoopUV *luv;
672
985
                unsigned int buffer_index = 0;
673
986
                int stitchBufferIndex = 0, unstitchBufferIndex = 0;
 
987
                int preview_size = (state->mode == STITCH_VERT) ? 2 : 4;
674
988
                /* initialize the preview buffers */
675
989
                preview->preview_polys = (float *)MEM_mallocN(preview->preview_uvs * sizeof(float) * 2, "tri_uv_stitch_prev");
676
990
                preview->uvs_per_polygon = MEM_mallocN(preview->num_polys * sizeof(*preview->uvs_per_polygon), "tri_uv_stitch_prev");
677
 
                preview->preview_stitchable = (float *)MEM_mallocN(preview->num_stitchable * sizeof(float) * 2, "stitch_preview_stichable_data");
678
 
                preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * sizeof(float) * 2, "stitch_preview_unstichable_data");
 
991
                preview->preview_stitchable = (float *)MEM_mallocN(preview->num_stitchable * sizeof(float) * preview_size, "stitch_preview_stichable_data");
 
992
                preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * sizeof(float) * preview_size, "stitch_preview_unstichable_data");
679
993
 
680
994
                preview->static_tris = (float *)MEM_mallocN(state->tris_per_island[state->static_island] * sizeof(float) * 6, "static_island_preview_tris");
681
995
 
685
999
                        return 0;
686
1000
                }
687
1001
 
688
 
                /* copy data from MTFaces to the preview display buffers */
 
1002
                /* copy data from MLoopUVs to the preview display buffers */
689
1003
                BM_ITER_MESH (efa, &iter, state->em->bm, BM_FACES_OF_MESH) {
690
1004
                        /* just to test if face was added for processing. uvs of inselected vertices will return NULL */
691
1005
                        UvElement *element = ED_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
727
1041
                }
728
1042
 
729
1043
                /* fill the appropriate preview buffers */
730
 
                for (i = 0; i < state->total_separate_uvs; i++) {
731
 
                        UvElement *element = (UvElement *)state->uvs[i];
732
 
                        if (element->flag & STITCH_STITCHABLE) {
733
 
                                l = element->l;
734
 
                                luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
735
 
 
736
 
                                copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
737
 
 
738
 
                                stitchBufferIndex++;
 
1044
                if (state->mode == STITCH_VERT) {
 
1045
                        for (i = 0; i < state->total_separate_uvs; i++) {
 
1046
                                UvElement *element = (UvElement *)state->uvs[i];
 
1047
                                if (element->flag & STITCH_STITCHABLE) {
 
1048
                                        l = element->l;
 
1049
                                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1050
 
 
1051
                                        copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
 
1052
 
 
1053
                                        stitchBufferIndex++;
 
1054
                                }
 
1055
                                else if (element->flag & STITCH_SELECTED) {
 
1056
                                        l = element->l;
 
1057
                                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1058
 
 
1059
                                        copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
 
1060
                                        unstitchBufferIndex++;
 
1061
                                }
739
1062
                        }
740
 
                        else if (element->flag & STITCH_SELECTED) {
741
 
                                l = element->l;
742
 
                                luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
743
 
 
744
 
                                copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
745
 
                                unstitchBufferIndex++;
 
1063
                }
 
1064
                else {
 
1065
                        for (i = 0; i < state->total_separate_edges; i++) {
 
1066
                                UvEdge *edge = state->edges + i;
 
1067
                                UvElement *element1 = state->uvs[edge->uv1];
 
1068
                                UvElement *element2 = state->uvs[edge->uv2];
 
1069
 
 
1070
                                if (edge->flag & STITCH_STITCHABLE) {
 
1071
                                        l = element1->l;
 
1072
                                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1073
                                        copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv->uv);
 
1074
 
 
1075
                                        l = element2->l;
 
1076
                                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1077
                                        copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv->uv);
 
1078
 
 
1079
                                        stitchBufferIndex++;
 
1080
                                        BLI_assert(stitchBufferIndex <= preview->num_stitchable);
 
1081
                                }
 
1082
                                else if (edge->flag & STITCH_SELECTED) {
 
1083
                                        l = element1->l;
 
1084
                                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1085
                                        copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv->uv);
 
1086
 
 
1087
                                        l = element2->l;
 
1088
                                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1089
                                        copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv->uv);
 
1090
 
 
1091
                                        unstitchBufferIndex++;
 
1092
                                        BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
 
1093
                                }
746
1094
                        }
747
1095
                }
748
1096
        }
751
1099
         * Here we calculate the final coordinates of the uvs *
752
1100
         ******************************************************/
753
1101
 
754
 
        final_position = MEM_callocN(state->selection_size * sizeof(*final_position), "stitch_uv_average");
755
 
        uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map), "stitch_uv_final_map");
 
1102
        if (state->mode == STITCH_VERT) {
 
1103
                final_position = MEM_callocN(state->selection_size * sizeof(*final_position), "stitch_uv_average");
 
1104
                uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map), "stitch_uv_final_map");
 
1105
        }
 
1106
        else {
 
1107
                final_position = MEM_callocN(state->total_separate_uvs * sizeof(*final_position), "stitch_uv_average");
 
1108
        }
756
1109
 
757
1110
        /* first pass, calculate final position for stitchable uvs of the static island */
758
1111
        for (i = 0; i < state->selection_size; i++) {
759
 
                UvElement *element = state->selection_stack[i];
760
 
                if (element->flag & STITCH_STITCHABLE) {
761
 
                        BMLoop *l;
762
 
                        MLoopUV *luv;
763
 
                        UvElement *element_iter;
764
 
 
765
 
                        l = element->l;
766
 
                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
767
 
 
768
 
 
769
 
                        uvfinal_map[element - state->element_map->buf] = i;
770
 
 
771
 
                        copy_v2_v2(final_position[i].uv, luv->uv);
772
 
                        final_position[i].count = 1;
773
 
 
774
 
                        if (state->snap_islands && element->island == state->static_island && !stitch_midpoints)
775
 
                                continue;
776
 
 
777
 
                        element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
778
 
 
779
 
                        for ( ; element_iter; element_iter = element_iter->next) {
780
 
                                if (element_iter->separate) {
781
 
                                        if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
782
 
                                                l = element_iter->l;
783
 
                                                luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1112
                if (state->mode == STITCH_VERT) {
 
1113
                        UvElement *element = state->selection_stack[i];
 
1114
 
 
1115
                        if (element->flag & STITCH_STITCHABLE) {
 
1116
                                BMLoop *l;
 
1117
                                MLoopUV *luv;
 
1118
                                UvElement *element_iter;
 
1119
 
 
1120
                                l = element->l;
 
1121
                                luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1122
 
 
1123
                                uvfinal_map[element - state->element_map->buf] = i;
 
1124
 
 
1125
                                copy_v2_v2(final_position[i].uv, luv->uv);
 
1126
                                final_position[i].count = 1;
 
1127
 
 
1128
                                if (state->snap_islands && element->island == state->static_island && !stitch_midpoints)
 
1129
                                        continue;
 
1130
 
 
1131
                                element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
 
1132
 
 
1133
                                for ( ; element_iter; element_iter = element_iter->next) {
 
1134
                                        if (element_iter->separate) {
 
1135
                                                if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
 
1136
                                                        l = element_iter->l;
 
1137
                                                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1138
                                                        if (stitch_midpoints) {
 
1139
                                                                add_v2_v2(final_position[i].uv, luv->uv);
 
1140
                                                                final_position[i].count++;
 
1141
                                                        }
 
1142
                                                        else if (element_iter->island == state->static_island) {
 
1143
                                                                /* if multiple uvs on the static island exist,
 
1144
                                                                 * last checked remains. to disambiguate we need to limit or use
 
1145
                                                                 * edge stitch */
 
1146
                                                                copy_v2_v2(final_position[i].uv, luv->uv);
 
1147
                                                        }
 
1148
                                                }
 
1149
                                        }
 
1150
                                }
 
1151
                        }
 
1152
                        if (stitch_midpoints) {
 
1153
                                final_position[i].uv[0] /= final_position[i].count;
 
1154
                                final_position[i].uv[1] /= final_position[i].count;
 
1155
                        }
 
1156
                }
 
1157
                else {
 
1158
                        UvEdge *edge = state->selection_stack[i];
 
1159
 
 
1160
                        if (edge->flag & STITCH_STITCHABLE) {
 
1161
                                MLoopUV *luv2, *luv1;
 
1162
                                BMLoop *l;
 
1163
                                UvEdge *edge_iter;
 
1164
 
 
1165
                                l = state->uvs[edge->uv1]->l;
 
1166
                                luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1167
                                l = state->uvs[edge->uv2]->l;
 
1168
                                luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1169
 
 
1170
                                copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
 
1171
                                copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
 
1172
                                final_position[edge->uv1].count = 1;
 
1173
                                final_position[edge->uv2].count = 1;
 
1174
 
 
1175
                                state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE;
 
1176
                                state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE;
 
1177
 
 
1178
                                if (state->snap_islands && edge->element->island == state->static_island && !stitch_midpoints)
 
1179
                                        continue;
 
1180
 
 
1181
                                for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) {
 
1182
                                        if (stitch_check_edges_state_stitchable (edge, edge_iter, state)) {
 
1183
                                                l = state->uvs[edge_iter->uv1]->l;
 
1184
                                                luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1185
                                                l = state->uvs[edge_iter->uv2]->l;
 
1186
                                                luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1187
 
784
1188
                                                if (stitch_midpoints) {
785
 
                                                        add_v2_v2(final_position[i].uv, luv->uv);
786
 
                                                        final_position[i].count++;
 
1189
                                                        add_v2_v2(final_position[edge->uv1].uv, luv1->uv);
 
1190
                                                        final_position[edge->uv1].count++;
 
1191
                                                        add_v2_v2(final_position[edge->uv2].uv, luv2->uv);
 
1192
                                                        final_position[edge->uv2].count++;
787
1193
                                                }
788
 
                                                else if (element_iter->island == state->static_island) {
789
 
                                                        /* if multiple uvs on the static island exist,
790
 
                                                         * last checked remains. to disambiguate we need to limit or use
791
 
                                                         * edge stitch */
792
 
                                                        copy_v2_v2(final_position[i].uv, luv->uv);
 
1194
                                                else if (edge_iter->element->island == state->static_island) {
 
1195
                                                        copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
 
1196
                                                        copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
793
1197
                                                }
794
1198
                                        }
795
1199
                                }
796
1200
                        }
797
1201
                }
798
 
                if (stitch_midpoints) {
 
1202
        }
 
1203
 
 
1204
        /* take mean position here. For edge case, this can't be done inside the loop for shared uvverts */
 
1205
        if (state->mode == STITCH_EDGE && stitch_midpoints) {
 
1206
                for (i = 0; i < state->total_separate_uvs; i++) {
799
1207
                        final_position[i].uv[0] /= final_position[i].count;
800
1208
                        final_position[i].uv[1] /= final_position[i].count;
801
1209
                }
803
1211
 
804
1212
        /* second pass, calculate island rotation and translation before modifying any uvs */
805
1213
        if (state->snap_islands) {
806
 
                for (i = 0; i < state->selection_size; i++) {
807
 
                        UvElement *element = state->selection_stack[i];
808
 
                        if (element->flag & STITCH_STITCHABLE) {
809
 
                                BMLoop *l;
810
 
                                MLoopUV *luv;
811
 
 
812
 
                                l = element->l;
813
 
                                luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
814
 
 
815
 
                                /* accumulate each islands' translation from stitchable elements. it is important to do here
816
 
                                 * because in final pass MTFaces get modified and result is zero. */
817
 
                                island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
818
 
                                island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
819
 
                                island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
820
 
                                island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
821
 
                                island_stitch_data[element->island].numOfElements++;
822
 
                        }
823
 
                }
824
 
 
825
 
                /* only calculate rotation when an edge has been fully selected */
826
 
                for (i = 0; i < state->total_boundary_edges; i++) {
827
 
                        UvEdge *edge = state->edges + i;
828
 
                        if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)) {
829
 
                                stitch_island_calculate_edge_rotation(edge, state, final_position, uvfinal_map, island_stitch_data);
830
 
                                island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = 1;
831
 
                        }
832
 
                }
833
 
 
834
 
                for (i = 0; i < state->selection_size; i++) {
835
 
                        UvElement *element = state->selection_stack[i];
836
 
                        if (!island_stitch_data[element->island].use_edge_rotation) {
837
 
                                if (element->flag & STITCH_STITCHABLE) {
838
 
                                        stitch_island_calculate_vert_rotation(element, state, island_stitch_data);
839
 
                                }
840
 
                        }
841
 
                }
842
 
 
 
1214
                if (state->mode == STITCH_VERT) {
 
1215
                        for (i = 0; i < state->selection_size; i++) {
 
1216
                                UvElement *element = state->selection_stack[i];
 
1217
 
 
1218
                                if (element->flag & STITCH_STITCHABLE) {
 
1219
                                        BMLoop *l;
 
1220
                                        MLoopUV *luv;
 
1221
 
 
1222
                                        l = element->l;
 
1223
                                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1224
 
 
1225
                                        /* accumulate each islands' translation from stitchable elements. it is important to do here
 
1226
                                         * because in final pass MTFaces get modified and result is zero. */
 
1227
                                        island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
 
1228
                                        island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
 
1229
                                        island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
 
1230
                                        island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
 
1231
                                        island_stitch_data[element->island].numOfElements++;
 
1232
                                }
 
1233
                        }
 
1234
 
 
1235
                        /* only calculate rotation when an edge has been fully selected */
 
1236
                        for (i = 0; i < state->total_separate_edges; i++) {
 
1237
                                UvEdge *edge = state->edges + i;
 
1238
                                if ((edge->flag & STITCH_BOUNDARY) && (state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)) {
 
1239
                                        stitch_island_calculate_edge_rotation(edge, state, final_position, uvfinal_map, island_stitch_data);
 
1240
                                        island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = TRUE;
 
1241
                                }
 
1242
                        }
 
1243
 
 
1244
                        /* clear seams of stitched edges */
 
1245
                        if (final && state->clear_seams) {
 
1246
                                for (i = 0; i < state->total_separate_edges; i++) {
 
1247
                                        UvEdge *edge = state->edges + i;
 
1248
                                        if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
 
1249
                                                BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
 
1250
                                }
 
1251
                        }
 
1252
 
 
1253
                        for (i = 0; i < state->selection_size; i++) {
 
1254
                                UvElement *element = state->selection_stack[i];
 
1255
                                if (!island_stitch_data[element->island].use_edge_rotation) {
 
1256
                                        if (element->flag & STITCH_STITCHABLE) {
 
1257
                                                stitch_island_calculate_vert_rotation(element, state, island_stitch_data);
 
1258
                                        }
 
1259
                                }
 
1260
                        }
 
1261
                }
 
1262
                else {
 
1263
                        for (i = 0; i < state->total_separate_uvs; i++) {
 
1264
                                UvElement *element = state->uvs[i];
 
1265
 
 
1266
                                if (element->flag & STITCH_STITCHABLE) {
 
1267
                                        BMLoop *l;
 
1268
                                        MLoopUV *luv;
 
1269
 
 
1270
                                        l = element->l;
 
1271
                                        luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
 
1272
 
 
1273
                                        /* accumulate each islands' translation from stitchable elements. it is important to do here
 
1274
                                         * because in final pass MTFaces get modified and result is zero. */
 
1275
                                        island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
 
1276
                                        island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
 
1277
                                        island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
 
1278
                                        island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
 
1279
                                        island_stitch_data[element->island].numOfElements++;
 
1280
                                }
 
1281
                        }
 
1282
 
 
1283
                        for (i = 0; i < state->selection_size; i++) {
 
1284
                                UvEdge *edge = state->selection_stack[i];
 
1285
 
 
1286
                                if (edge->flag & STITCH_STITCHABLE) {
 
1287
                                        stitch_island_calculate_edge_rotation(edge, state, final_position, NULL, island_stitch_data);
 
1288
                                        island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = TRUE;
 
1289
                                }
 
1290
                        }
 
1291
 
 
1292
                        /* clear seams of stitched edges */
 
1293
                        if (final && state->clear_seams) {
 
1294
                                for (i = 0; i < state->selection_size; i++) {
 
1295
                                        UvEdge *edge = state->selection_stack[i];
 
1296
                                        if (edge->flag & STITCH_STITCHABLE) {
 
1297
                                                BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
 
1298
                                        }
 
1299
                                }
 
1300
                        }
 
1301
                }
843
1302
        }
844
1303
 
845
1304
        /* third pass, propagate changes to coincident uvs */
846
1305
        for (i = 0; i < state->selection_size; i++) {
847
 
                UvElement *element = state->selection_stack[i];
848
 
                if (element->flag & STITCH_STITCHABLE) {
849
 
                        UvElement *element_iter = element;
850
 
                        /* propagate to coincident uvs */
851
 
                        do {
852
 
                                BMLoop *l;
853
 
                                MLoopUV *luv;
854
 
 
855
 
                                l = element_iter->l;
856
 
                                luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
857
 
 
858
 
                                element_iter->flag |= STITCH_PROCESSED;
859
 
                                /* either flush to preview or to the MTFace, if final */
860
 
                                if (final) {
861
 
                                        copy_v2_v2(luv->uv, final_position[i].uv);
862
 
 
863
 
                                        uvedit_uv_select_enable(state->em, scene, l, FALSE);
864
 
                                }
865
 
                                else {
866
 
                                        int face_preview_pos = preview_position[BM_elem_index_get(element_iter->face)].data_position;
867
 
                                        if (face_preview_pos != STITCH_NO_PREVIEW) {
868
 
                                                copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->tfindex,
869
 
                                                           final_position[i].uv);
870
 
                                        }
871
 
                                }
872
 
 
873
 
                                /* end of calculations, keep only the selection flag */
874
 
                                if ( (!state->snap_islands) || ((!stitch_midpoints) && (element_iter->island == state->static_island))) {
875
 
                                        element_iter->flag &= STITCH_SELECTED;
876
 
                                }
877
 
 
878
 
                                element_iter = element_iter->next;
879
 
                        } while (element_iter && !element_iter->separate);
 
1306
                if (state->mode == STITCH_VERT) {
 
1307
                        UvElement *element = state->selection_stack[i];
 
1308
 
 
1309
                        stitch_propagate_uv_final_position (element, i, preview_position, final_position, state, final, scene);
 
1310
                }
 
1311
                else {
 
1312
                        UvEdge *edge = state->selection_stack[i];
 
1313
 
 
1314
                        stitch_propagate_uv_final_position (state->uvs[edge->uv1], edge->uv1, preview_position, final_position, state, final, scene);
 
1315
                        stitch_propagate_uv_final_position (state->uvs[edge->uv2], edge->uv2, preview_position, final_position, state, final, scene);
 
1316
 
 
1317
                        edge->flag &= (STITCH_SELECTED | STITCH_BOUNDARY);
880
1318
                }
881
1319
        }
882
1320
 
886
1324
        }
887
1325
 
888
1326
        MEM_freeN(final_position);
889
 
        MEM_freeN(uvfinal_map);
 
1327
        if (state->mode == STITCH_VERT) {
 
1328
                MEM_freeN(uvfinal_map);
 
1329
        }
890
1330
        MEM_freeN(island_stitch_data);
891
1331
        MEM_freeN(preview_position);
892
1332
 
898
1338
{
899
1339
        UvEdge *edge = (UvEdge *)key;
900
1340
        return
901
 
            BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv2)) +
902
 
            BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv1));
 
1341
                BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv2)) +
 
1342
                BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv1));
903
1343
}
904
1344
 
905
1345
static int uv_edge_compare(const void *a, const void *b)
913
1353
        return 1;
914
1354
}
915
1355
 
 
1356
/* select all common edges */
 
1357
static void stitch_select_edge(UvEdge *edge, StitchState *state, int always_select)
 
1358
{
 
1359
        UvEdge *eiter;
 
1360
        UvEdge **selection_stack = (UvEdge **)state->selection_stack;
 
1361
 
 
1362
        for (eiter = edge->first; eiter; eiter = eiter->next) {
 
1363
                if (eiter->flag & STITCH_SELECTED) {
 
1364
                        int i;
 
1365
                        if (always_select)
 
1366
                                continue;
 
1367
 
 
1368
                        eiter->flag &= ~STITCH_SELECTED;
 
1369
                        for (i = 0; i < state->selection_size; i++) {
 
1370
                                if (selection_stack[i] == eiter) {
 
1371
                                        (state->selection_size)--;
 
1372
                                        selection_stack[i] = selection_stack[state->selection_size];
 
1373
                                        break;
 
1374
                                }
 
1375
                        }
 
1376
                }
 
1377
                else {
 
1378
                        eiter->flag |= STITCH_SELECTED;
 
1379
                        selection_stack[state->selection_size++] = eiter;
 
1380
                }
 
1381
        }
 
1382
}
 
1383
 
916
1384
 
917
1385
/* Select all common uvs */
918
1386
static void stitch_select_uv(UvElement *element, StitchState *state, int always_select)
919
1387
{
920
1388
        BMLoop *l;
921
1389
        UvElement *element_iter;
922
 
        UvElement **selection_stack = state->selection_stack;
 
1390
        UvElement **selection_stack = (UvElement **)state->selection_stack;
923
1391
 
924
1392
        l = element->l;
925
1393
 
950
1418
        }
951
1419
}
952
1420
 
953
 
static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal)
 
1421
static void stitch_switch_selection_mode(StitchState *state)
 
1422
{
 
1423
        void **old_selection_stack = state->selection_stack;
 
1424
        int old_selection_size = state->selection_size;
 
1425
        state->selection_size = 0;
 
1426
 
 
1427
        if (state->mode == STITCH_VERT) {
 
1428
                int i;
 
1429
                state->selection_stack = MEM_mallocN(state->total_separate_edges * sizeof(*state->selection_stack),
 
1430
                                                     "stitch_new_edge_selection_stack");
 
1431
 
 
1432
                /* check if both elements of an edge are selected */
 
1433
                for (i = 0; i < state->total_separate_edges; i++) {
 
1434
                        UvEdge *edge = state->edges + i;
 
1435
                        UvElement *element1 = state->uvs[edge->uv1];
 
1436
                        UvElement *element2 = state->uvs[edge->uv2];
 
1437
 
 
1438
                        if ((element1->flag & STITCH_SELECTED) && (element2->flag & STITCH_SELECTED))
 
1439
                                stitch_select_edge(edge, state, TRUE);
 
1440
                }
 
1441
 
 
1442
                /* unselect selected uvelements */
 
1443
                for (i = 0; i < old_selection_size; i++) {
 
1444
                        UvElement *element = old_selection_stack[i];
 
1445
 
 
1446
                        element->flag &= ~STITCH_SELECTED;
 
1447
                }
 
1448
                state->mode = STITCH_EDGE;
 
1449
        }
 
1450
        else {
 
1451
                int i;
 
1452
                state->selection_stack = MEM_mallocN(state->total_separate_uvs * sizeof(*state->selection_stack),
 
1453
                                                     "stitch_new_vert_selection_stack");
 
1454
 
 
1455
                for (i = 0; i < old_selection_size; i++) {
 
1456
                        UvEdge *edge = old_selection_stack[i];
 
1457
                        UvElement *element1 = state->uvs[edge->uv1];
 
1458
                        UvElement *element2 = state->uvs[edge->uv2];
 
1459
 
 
1460
                        stitch_select_uv(element1, state, TRUE);
 
1461
                        stitch_select_uv(element2, state, TRUE);
 
1462
 
 
1463
                        edge->flag &= ~STITCH_SELECTED;
 
1464
                }
 
1465
                state->mode = STITCH_VERT;
 
1466
        }
 
1467
        MEM_freeN(old_selection_stack);
 
1468
}
 
1469
 
 
1470
static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
954
1471
{
955
1472
        BMLoop *l1 = edge->element->l;
956
 
        BMLoop *l2 = l1->next;
957
1473
        MLoopUV *luv1, *luv2;
958
1474
        float tangent[2];
959
1475
 
960
1476
        luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
961
 
        luv2 = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, CD_MLOOPUV);
 
1477
        luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV);
962
1478
 
963
1479
        sub_v2_v2v2(tangent, luv2->uv,  luv1->uv);
964
1480
 
 
1481
        tangent[1] /= aspect;
 
1482
 
965
1483
        normal[0] = tangent[1];
966
1484
        normal[1] = -tangent[0];
967
1485
 
968
1486
        normalize_v2(normal);
969
1487
}
970
1488
 
 
1489
static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
 
1490
{
 
1491
        int i, index = 0;
 
1492
        float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
 
1493
        StitchState *state = (StitchState *)arg;
 
1494
        StitchPreviewer *stitch_preview = state->stitch_preview;
 
1495
 
 
1496
        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
 
1497
        glEnableClientState(GL_VERTEX_ARRAY);
 
1498
 
 
1499
        glPointSize(pointsize * 2.0f);
 
1500
 
 
1501
        glEnable(GL_BLEND);
 
1502
 
 
1503
        UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE);
 
1504
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
1505
        glVertexPointer(2, GL_FLOAT, 0, stitch_preview->static_tris);
 
1506
        glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_static_tris * 3);
 
1507
 
 
1508
        glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_polys);
 
1509
        for (i = 0; i < stitch_preview->num_polys; i++) {
 
1510
                glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
1511
                UI_ThemeColor4(TH_STITCH_PREVIEW_FACE);
 
1512
                glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
 
1513
                glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 
1514
                UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE);
 
1515
                glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
 
1516
                #if 0
 
1517
                glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
 
1518
                UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
 
1519
                glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
 
1520
                #endif
 
1521
 
 
1522
                index += stitch_preview->uvs_per_polygon[i];
 
1523
        }
 
1524
        glDisable(GL_BLEND);
 
1525
 
 
1526
        /* draw vert preview */
 
1527
        if (state->mode == STITCH_VERT) {
 
1528
                UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
 
1529
                glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
 
1530
                glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable);
 
1531
 
 
1532
                UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
 
1533
                glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
 
1534
                glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable);
 
1535
        }
 
1536
        else {
 
1537
                UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
 
1538
                glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
 
1539
                glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_stitchable);
 
1540
 
 
1541
                UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
 
1542
                glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
 
1543
                glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_unstitchable);
 
1544
        }
 
1545
 
 
1546
        glPopClientAttrib();
 
1547
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
1548
 
 
1549
        glPointSize(1.0);
 
1550
}
 
1551
 
 
1552
static UvEdge *uv_edge_get (BMLoop *l, StitchState *state)
 
1553
{
 
1554
        UvEdge tmp_edge;
 
1555
 
 
1556
        UvElement *element1 = ED_uv_element_get(state->element_map, l->f, l);
 
1557
        UvElement *element2 = ED_uv_element_get(state->element_map, l->f, l->next);
 
1558
 
 
1559
        int uv1 = state->map[element1 - state->element_map->buf];
 
1560
        int uv2 = state->map[element2 - state->element_map->buf];
 
1561
 
 
1562
        if (uv1 < uv2) {
 
1563
                tmp_edge.uv1 = uv1;
 
1564
                tmp_edge.uv2 = uv2;
 
1565
        }
 
1566
        else {
 
1567
                tmp_edge.uv1 = uv2;
 
1568
                tmp_edge.uv2 = uv1;
 
1569
        }
 
1570
 
 
1571
        return BLI_ghash_lookup(state->edge_hash, &tmp_edge);
 
1572
}
 
1573
 
971
1574
static int stitch_init(bContext *C, wmOperator *op)
972
1575
{
973
1576
        /* for fast edge lookup... */
974
 
        GHash *edgeHash;
 
1577
        GHash *edge_hash;
975
1578
        /* ...and actual edge storage */
976
1579
        UvEdge *edges;
977
1580
        int total_edges;
984
1587
        BMEditMesh *em;
985
1588
        GHashIterator *ghi;
986
1589
        UvEdge *all_edges;
987
 
        StitchState *state = MEM_mallocN(sizeof(StitchState), "stitch state");
 
1590
        StitchState *state;
988
1591
        Scene *scene = CTX_data_scene(C);
989
1592
        ToolSettings *ts = scene->toolsettings;
990
 
 
 
1593
        ARegion *ar = CTX_wm_region(C);
 
1594
        float aspx, aspy;
991
1595
        Object *obedit = CTX_data_edit_object(C);
992
1596
 
 
1597
        if (!ar)
 
1598
                return 0;
 
1599
 
 
1600
        state = MEM_mallocN(sizeof(StitchState), "stitch state");
 
1601
 
 
1602
        if (!state)
 
1603
                return 0;
 
1604
 
993
1605
        op->customdata = state;
994
1606
 
995
 
        if (!state)
996
 
                return 0;
997
 
 
998
1607
        /* initialize state */
999
1608
        state->use_limit = RNA_boolean_get(op->ptr, "use_limit");
1000
1609
        state->limit_dist = RNA_float_get(op->ptr, "limit");
1002
1611
        state->snap_islands = RNA_boolean_get(op->ptr, "snap_islands");
1003
1612
        state->static_island = RNA_int_get(op->ptr, "static_island");
1004
1613
        state->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap");
 
1614
        state->clear_seams = RNA_boolean_get(op->ptr, "clear_seams");
 
1615
        if (RNA_struct_property_is_set(op->ptr, "mode")) {
 
1616
                state->mode = RNA_enum_get(op->ptr, "mode");
 
1617
        }
 
1618
        else {
 
1619
                if (ts->uv_flag & UV_SYNC_SELECTION) {
 
1620
                        if (ts->selectmode & SCE_SELECT_VERTEX)
 
1621
                                state->mode = STITCH_VERT;
 
1622
                        else
 
1623
                                state->mode = STITCH_EDGE;
 
1624
                }
 
1625
                else {
 
1626
                        if (ts->uv_selectmode & UV_SELECT_VERTEX) {
 
1627
                                state->mode = STITCH_VERT;
 
1628
                        }
 
1629
                        else {
 
1630
                                state->mode = STITCH_EDGE;
 
1631
                        }
 
1632
                }
 
1633
        }
 
1634
 
 
1635
        state->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, state, REGION_DRAW_POST_VIEW);
1005
1636
        /* in uv synch selection, all uv's are visible */
1006
1637
        if (ts->uv_flag & UV_SYNC_SELECTION) {
1007
 
                state->element_map = EDBM_uv_element_map_create(state->em, 0, 1);
 
1638
                state->element_map = EDBM_uv_element_map_create(state->em, FALSE, TRUE);
1008
1639
        }
1009
1640
        else {
1010
 
                state->element_map = EDBM_uv_element_map_create(state->em, 1, 1);
 
1641
                state->element_map = EDBM_uv_element_map_create(state->em, TRUE, TRUE);
1011
1642
        }
1012
1643
        if (!state->element_map) {
1013
 
                stitch_state_delete(state);
 
1644
                state_delete(state);
1014
1645
                return 0;
1015
1646
        }
1016
1647
 
 
1648
        uvedit_get_aspect(scene, obedit, em, &aspx, &aspy);
 
1649
        state->aspect = aspx / aspy;
 
1650
 
1017
1651
        /* Entirely possible if redoing last operator that static island is bigger than total number of islands.
1018
 
         * This ensures we get no hang in the island checking code in stitch_process_data. */
 
1652
         * This ensures we get no hang in the island checking code in stitch_stitch_process_data. */
1019
1653
        state->static_island %= state->element_map->totalIslands;
1020
1654
 
1021
1655
        /* Count 'unique' uvs */
1025
1659
                }
1026
1660
        }
1027
1661
 
 
1662
        /* explicitly set preview to NULL, to avoid deleting an invalid pointer on stitch_process_data */
 
1663
        state->stitch_preview = NULL;
1028
1664
        /* Allocate the unique uv buffers */
1029
1665
        state->uvs = MEM_mallocN(sizeof(*state->uvs) * counter, "uv_stitch_unique_uvs");
1030
1666
        /* internal uvs need no normals but it is hard and slow to keep a map of
1031
1667
         * normals only for boundary uvs, so allocating for all uvs */
1032
1668
        state->normals = MEM_callocN(sizeof(*state->normals) * counter * 2, "uv_stitch_normals");
1033
1669
        state->total_separate_uvs = counter;
1034
 
        /* we can at most have totalUVs edges or uvs selected. Actually they are less, considering we store only
1035
 
         * unique uvs for processing but I am accounting for all bizarre cases, especially for edges, this way */
1036
 
        state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * counter, "uv_stitch_selection_stack");
1037
1670
        state->map = map = MEM_mallocN(sizeof(*map) * state->element_map->totalUVs, "uv_stitch_unique_map");
1038
1671
        /* Allocate the edge stack */
1039
 
        edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
 
1672
        edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
1040
1673
        all_edges = MEM_mallocN(sizeof(*all_edges) * state->element_map->totalUVs, "stitch_all_edges");
1041
1674
 
1042
 
        if (!state->selection_stack || !state->uvs || !map || !edgeHash || !all_edges) {
1043
 
                stitch_state_delete(state);
 
1675
        if (!state->uvs || !map || !edge_hash || !all_edges) {
 
1676
                state_delete(state);
1044
1677
                return 0;
1045
1678
        }
1046
1679
 
1073
1706
                        offset1 = map[itmp1];
1074
1707
                        offset2 = map[itmp2];
1075
1708
 
 
1709
                        all_edges[counter].next = NULL;
 
1710
                        all_edges[counter].first = NULL;
1076
1711
                        all_edges[counter].flag = 0;
1077
1712
                        all_edges[counter].element = element;
1078
1713
                        /* using an order policy, sort uvs according to address space. This avoids
1086
1721
                                all_edges[counter].uv2 = offset1;
1087
1722
                        }
1088
1723
 
1089
 
                        if (BLI_ghash_haskey(edgeHash, &all_edges[counter])) {
1090
 
                                char *flag = BLI_ghash_lookup(edgeHash, &all_edges[counter]);
1091
 
                                *flag = 0;
 
1724
                        if (BLI_ghash_haskey(edge_hash, &all_edges[counter])) {
 
1725
                                UvEdge *edge = BLI_ghash_lookup(edge_hash, &all_edges[counter]);
 
1726
                                edge->flag = 0;
1092
1727
                        }
1093
1728
                        else {
1094
 
                                BLI_ghash_insert(edgeHash, &all_edges[counter], &(all_edges[counter].flag));
 
1729
                                BLI_ghash_insert(edge_hash, &all_edges[counter], &all_edges[counter]);
1095
1730
                                all_edges[counter].flag = STITCH_BOUNDARY;
1096
1731
                        }
1097
1732
                        counter++;
1099
1734
        }
1100
1735
 
1101
1736
 
1102
 
        ghi = BLI_ghashIterator_new(edgeHash);
1103
 
        total_edges = 0;
1104
 
        /* fill the edges with data */
1105
 
        for (; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
1106
 
                UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
1107
 
                if (edge->flag & STITCH_BOUNDARY) {
1108
 
                        total_edges++;
1109
 
                }
1110
 
        }
 
1737
        ghi = BLI_ghashIterator_new(edge_hash);
 
1738
        total_edges = BLI_ghash_size(edge_hash);
1111
1739
        state->edges = edges = MEM_mallocN(sizeof(*edges) * total_edges, "stitch_edges");
1112
 
        if (!ghi || !edges) {
1113
 
                MEM_freeN(all_edges);
1114
 
                stitch_state_delete(state);
 
1740
 
 
1741
        /* I assume any system will be able to at least allocate an iterator :p */
 
1742
        if (!edges) {
 
1743
                BLI_ghashIterator_free(ghi);
 
1744
                state_delete(state);
1115
1745
                return 0;
1116
1746
        }
1117
1747
 
1118
 
        state->total_boundary_edges = total_edges;
 
1748
        state->total_separate_edges = total_edges;
1119
1749
 
1120
1750
        /* fill the edges with data */
1121
 
        for (i = 0, BLI_ghashIterator_init(ghi, edgeHash); !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
1122
 
                UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
1123
 
                if (edge->flag & STITCH_BOUNDARY) {
1124
 
                        edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
1125
 
                }
 
1751
        for (i = 0, BLI_ghashIterator_init(ghi, edge_hash); !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
 
1752
                edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
1126
1753
        }
1127
1754
 
1128
1755
        /* cleanup temporary stuff */
1129
1756
        BLI_ghashIterator_free(ghi);
1130
1757
        MEM_freeN(all_edges);
1131
1758
 
1132
 
        /* refill hash with new pointers to cleanup duplicates */
1133
 
        BLI_ghash_free(edgeHash, NULL, NULL);
 
1759
        BLI_ghash_free(edge_hash, NULL, NULL);
 
1760
 
 
1761
        /* refill an edge hash to create edge connnectivity data */
 
1762
        state->edge_hash = edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
 
1763
        for (i = 0; i < total_edges; i++) {
 
1764
                BLI_ghash_insert(edge_hash, edges + i, edges + i);
 
1765
        }
 
1766
        stitch_uv_edge_generate_linked_edges(edge_hash, state);
1134
1767
 
1135
1768
        /***** calculate 2D normals for boundary uvs *****/
1136
1769
 
1137
1770
        /* we use boundary edges to calculate 2D normals.
1138
1771
         * to disambiguate the direction of the normal, we also need
1139
1772
         * a point "inside" the island, that can be provided by
1140
 
         * the opposite uv for a quad, or the next uv for a triangle. */
 
1773
         * the winding of the polygon (assuming counter-clockwise flow). */
1141
1774
 
1142
1775
        for (i = 0; i < total_edges; i++) {
 
1776
                UvEdge *edge = edges + i;
1143
1777
                float normal[2];
1144
 
                stitch_calculate_edge_normal(em, edges + i, normal);
1145
 
 
1146
 
                add_v2_v2(state->normals + edges[i].uv1 * 2, normal);
1147
 
                add_v2_v2(state->normals + edges[i].uv2 * 2, normal);
1148
 
 
1149
 
                normalize_v2(state->normals + edges[i].uv1 * 2);
1150
 
                normalize_v2(state->normals + edges[i].uv2 * 2);
 
1778
                if (edge->flag & STITCH_BOUNDARY) {
 
1779
                        stitch_calculate_edge_normal(em, edge, normal, state->aspect);
 
1780
 
 
1781
                        add_v2_v2(state->normals + edge->uv1 * 2, normal);
 
1782
                        add_v2_v2(state->normals + edge->uv2 * 2, normal);
 
1783
 
 
1784
                        normalize_v2(state->normals + edge->uv1 * 2);
 
1785
                        normalize_v2(state->normals + edge->uv2 * 2);
 
1786
                }
1151
1787
        }
1152
1788
 
1153
1789
 
1159
1795
        if (RNA_struct_property_is_set(op->ptr, "selection")) {
1160
1796
                int faceIndex, elementIndex;
1161
1797
                UvElement *element;
1162
 
 
1163
 
                EDBM_index_arrays_init(em, 0, 0, 1);
1164
 
 
1165
 
                RNA_BEGIN(op->ptr, itemptr, "selection") {
1166
 
                        faceIndex = RNA_int_get(&itemptr, "face_index");
1167
 
                        elementIndex = RNA_int_get(&itemptr, "element_index");
1168
 
                        efa = EDBM_face_at_index(em, faceIndex);
1169
 
                        element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
1170
 
                        stitch_select_uv(element, state, 1);
1171
 
                }
1172
 
                RNA_END;
1173
 
 
1174
 
                EDBM_index_arrays_free(em);
 
1798
                enum StitchModes stored_mode = RNA_enum_get(op->ptr, "stored_mode");
 
1799
 
 
1800
                EDBM_index_arrays_ensure(em, BM_FACE);
 
1801
 
 
1802
                if (stored_mode == STITCH_VERT) {
 
1803
                        state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_uvs, "uv_stitch_selection_stack");
 
1804
 
 
1805
                        RNA_BEGIN (op->ptr, itemptr, "selection")
 
1806
                        {
 
1807
                                faceIndex = RNA_int_get(&itemptr, "face_index");
 
1808
                                elementIndex = RNA_int_get(&itemptr, "element_index");
 
1809
                                efa = EDBM_face_at_index(em, faceIndex);
 
1810
                                element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
 
1811
                                stitch_select_uv(element, state, 1);
 
1812
                        }
 
1813
                        RNA_END;
 
1814
                }
 
1815
                else {
 
1816
                        state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_edges, "uv_stitch_selection_stack");
 
1817
 
 
1818
                        RNA_BEGIN (op->ptr, itemptr, "selection")
 
1819
                        {
 
1820
                                UvEdge tmp_edge, *edge;
 
1821
                                int uv1, uv2;
 
1822
                                faceIndex = RNA_int_get(&itemptr, "face_index");
 
1823
                                elementIndex = RNA_int_get(&itemptr, "element_index");
 
1824
                                efa = EDBM_face_at_index(em, faceIndex);
 
1825
                                element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
 
1826
                                uv1 = map[element - state->element_map->buf];
 
1827
 
 
1828
                                element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, (elementIndex + 1) % efa->len));
 
1829
                                uv2 = map[element - state->element_map->buf];
 
1830
 
 
1831
                                if (uv1 < uv2) {
 
1832
                                        tmp_edge.uv1 = uv1;
 
1833
                                        tmp_edge.uv2 = uv2;
 
1834
                                }
 
1835
                                else {
 
1836
                                        tmp_edge.uv1 = uv2;
 
1837
                                        tmp_edge.uv2 = uv1;
 
1838
                                }
 
1839
 
 
1840
                                edge = BLI_ghash_lookup(edge_hash, &tmp_edge);
 
1841
 
 
1842
                                stitch_select_edge(edge, state, TRUE);
 
1843
                        }
 
1844
                        RNA_END;
 
1845
                }
 
1846
                /* if user has switched the operator mode after operation, we need to convert
 
1847
                 * the stored format */
 
1848
                if (state->mode != stored_mode) {
 
1849
                        state->mode = stored_mode;
 
1850
                        stitch_switch_selection_mode(state);
 
1851
                }
1175
1852
                /* Clear the selection */
1176
1853
                RNA_collection_clear(op->ptr, "selection");
1177
1854
 
1178
1855
        }
1179
1856
        else {
1180
 
                BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1181
 
                        BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
1182
 
                                if (uvedit_uv_select_test(em, scene, l)) {
1183
 
                                        UvElement *element = ED_uv_element_get(state->element_map, efa, l);
1184
 
                                        if (element) {
1185
 
                                                stitch_select_uv(element, state, 1);
 
1857
                if (state->mode == STITCH_VERT) {
 
1858
                        state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_uvs, "uv_stitch_selection_stack");
 
1859
 
 
1860
                        BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
 
1861
                                BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
 
1862
                                        if (uvedit_uv_select_test(em, scene, l)) {
 
1863
                                                UvElement *element = ED_uv_element_get(state->element_map, efa, l);
 
1864
                                                if (element) {
 
1865
                                                        stitch_select_uv(element, state, 1);
 
1866
                                                }
 
1867
                                        }
 
1868
                                }
 
1869
                        }
 
1870
                }
 
1871
                else {
 
1872
                        state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_edges, "uv_stitch_selection_stack");
 
1873
 
 
1874
                        BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
 
1875
                                BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
 
1876
                                        if (uvedit_edge_select_test(em, scene, l)) {
 
1877
                                                UvEdge *edge = uv_edge_get(l, state);
 
1878
                                                if (edge) {
 
1879
                                                        stitch_select_edge(edge, state, TRUE);
 
1880
                                                }
1186
1881
                                        }
1187
1882
                                }
1188
1883
                        }
1205
1900
                }
1206
1901
        }
1207
1902
 
1208
 
        if (!stitch_process_data(state, scene, 0)) {
1209
 
                stitch_state_delete(state);
 
1903
        if (!stitch_process_data(state, scene, FALSE)) {
 
1904
 
 
1905
                state_delete(state);
1210
1906
                return 0;
1211
1907
        }
1212
1908
 
1227
1923
 
1228
1924
static void stitch_exit(bContext *C, wmOperator *op, int finished)
1229
1925
{
1230
 
        StitchState *stitch_state;
 
1926
        StitchState *state;
1231
1927
        Scene *scene;
1232
1928
        SpaceImage *sima;
1233
1929
        ScrArea *sa = CTX_wm_area(C);
1237
1933
        obedit = CTX_data_edit_object(C);
1238
1934
        sima = CTX_wm_space_image(C);
1239
1935
 
1240
 
        stitch_state = (StitchState *)op->customdata;
 
1936
        state = (StitchState *)op->customdata;
1241
1937
 
1242
1938
        if (finished) {
1243
1939
                int i;
1244
1940
 
1245
 
                RNA_float_set(op->ptr, "limit", stitch_state->limit_dist);
1246
 
                RNA_boolean_set(op->ptr, "use_limit", stitch_state->use_limit);
1247
 
                RNA_boolean_set(op->ptr, "snap_islands", stitch_state->snap_islands);
1248
 
                RNA_int_set(op->ptr, "static_island", stitch_state->static_island);
1249
 
                RNA_boolean_set(op->ptr, "midpoint_snap", stitch_state->midpoints);
 
1941
                RNA_float_set(op->ptr, "limit", state->limit_dist);
 
1942
                RNA_boolean_set(op->ptr, "use_limit", state->use_limit);
 
1943
                RNA_boolean_set(op->ptr, "snap_islands", state->snap_islands);
 
1944
                RNA_int_set(op->ptr, "static_island", state->static_island);
 
1945
                RNA_boolean_set(op->ptr, "midpoint_snap", state->midpoints);
 
1946
                RNA_enum_set(op->ptr, "mode", state->mode);
 
1947
                RNA_enum_set(op->ptr, "stored_mode", state->mode);
1250
1948
 
1251
1949
                /* Store selection for re-execution of stitch */
1252
 
                for (i = 0; i < stitch_state->selection_size; i++) {
 
1950
                for (i = 0; i < state->selection_size; i++) {
 
1951
                        UvElement *element;
1253
1952
                        PointerRNA itemptr;
1254
 
                        UvElement *element = stitch_state->selection_stack[i];
1255
 
 
 
1953
                        if (state->mode == STITCH_VERT) {
 
1954
                                element = state->selection_stack[i];
 
1955
                        }
 
1956
                        else {
 
1957
                                element = ((UvEdge *)state->selection_stack[i])->element;
 
1958
                        }
1256
1959
                        RNA_collection_add(op->ptr, "selection", &itemptr);
1257
1960
 
1258
 
                        RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->face));
1259
 
 
 
1961
                        RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->l->f));
1260
1962
                        RNA_int_set(&itemptr, "element_index", element->tfindex);
1261
1963
                }
1262
1964
 
1263
 
 
1264
1965
                uvedit_live_unwrap_update(sima, scene, obedit);
1265
1966
        }
1266
1967
 
1267
1968
        if (sa)
1268
1969
                ED_area_headerprint(sa, NULL);
1269
1970
 
 
1971
        ED_region_draw_cb_exit(CTX_wm_region(C)->type, state->draw_handle);
 
1972
 
1270
1973
        DAG_id_tag_update(obedit->data, 0);
1271
1974
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1272
1975
 
1273
 
        stitch_state_delete(stitch_state);
 
1976
        state_delete(state);
1274
1977
        op->customdata = NULL;
1275
 
 
1276
 
        stitch_preview_delete();
1277
1978
}
1278
1979
 
1279
1980
 
1299
2000
        }
1300
2001
}
1301
2002
 
1302
 
static void stitch_select(bContext *C, Scene *scene, wmEvent *event, StitchState *stitch_state)
 
2003
static void stitch_select(bContext *C, Scene *scene, wmEvent *event, StitchState *state)
1303
2004
{
1304
2005
        /* add uv under mouse to processed uv's */
1305
2006
        float co[2];
1308
2009
        Image *ima = CTX_data_edit_image(C);
1309
2010
 
1310
2011
        UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
1311
 
        uv_find_nearest_vert(scene, ima, stitch_state->em, co, NULL, &hit);
1312
 
 
1313
 
        if (hit.efa) {
1314
 
                /* Add vertex to selection, deselect all common uv's of vert other
1315
 
                 * than selected and update the preview. This behavior was decided so that
1316
 
                 * you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */
1317
 
 
1318
 
                /* This works due to setting of tmp in find nearest uv vert */
1319
 
                UvElement *element = ED_uv_element_get(stitch_state->element_map, hit.efa, hit.l);
1320
 
                stitch_select_uv(element, stitch_state, 0);
1321
 
 
 
2012
 
 
2013
        if (state->mode == STITCH_VERT) {
 
2014
                uv_find_nearest_vert(scene, ima, state->em, co, NULL, &hit);
 
2015
 
 
2016
                if (hit.efa) {
 
2017
                        /* Add vertex to selection, deselect all common uv's of vert other
 
2018
                         * than selected and update the preview. This behavior was decided so that
 
2019
                         * you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */
 
2020
 
 
2021
                        /* This works due to setting of tmp in find nearest uv vert */
 
2022
                        UvElement *element = ED_uv_element_get(state->element_map, hit.efa, hit.l);
 
2023
                        stitch_select_uv(element, state, FALSE);
 
2024
 
 
2025
                }
 
2026
        }
 
2027
        else {
 
2028
                uv_find_nearest_edge(scene, ima, state->em, co, &hit);
 
2029
 
 
2030
                if (hit.efa) {
 
2031
                        UvEdge *edge = uv_edge_get(hit.l, state);
 
2032
                        stitch_select_edge(edge, state, FALSE);
 
2033
                }
1322
2034
        }
1323
2035
}
1324
2036
 
1325
2037
static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
1326
2038
{
1327
 
        StitchState *stitch_state;
 
2039
        StitchState *state;
1328
2040
        Scene *scene = CTX_data_scene(C);
1329
2041
 
1330
 
        stitch_state = (StitchState *)op->customdata;
 
2042
        state = (StitchState *)op->customdata;
1331
2043
 
1332
2044
        switch (event->type) {
1333
2045
                case MIDDLEMOUSE:
1334
2046
                        return OPERATOR_PASS_THROUGH;
1335
2047
 
1336
 
                /* Cancel */
 
2048
                        /* Cancel */
1337
2049
                case ESCKEY:
1338
2050
                        return stitch_cancel(C, op);
1339
2051
 
1340
2052
 
1341
2053
                case LEFTMOUSE:
1342
2054
                        if (event->shift && (U.flag & USER_LMOUSESELECT)) {
1343
 
                                if (event->val == KM_RELEASE) {
1344
 
                                        stitch_select(C, scene, event, stitch_state);
 
2055
                                if (event->val == KM_PRESS) {
 
2056
                                        stitch_select(C, scene, event, state);
1345
2057
 
1346
 
                                        if (!stitch_process_data(stitch_state, scene, 0)) {
 
2058
                                        if (!stitch_process_data(state, scene, FALSE)) {
1347
2059
                                                return stitch_cancel(C, op);
1348
2060
                                        }
1349
2061
                                }
1351
2063
                        }
1352
2064
                case PADENTER:
1353
2065
                case RETKEY:
1354
 
                        if (stitch_process_data(stitch_state, scene, 1)) {
1355
 
                                stitch_exit(C, op, 1);
1356
 
                                return OPERATOR_FINISHED;
 
2066
                        if (event->val == KM_PRESS) {
 
2067
                                if (stitch_process_data(state, scene, TRUE)) {
 
2068
                                        stitch_exit(C, op, 1);
 
2069
                                        return OPERATOR_FINISHED;
 
2070
                                }
 
2071
                                else {
 
2072
                                        return stitch_cancel(C, op);
 
2073
                                }
1357
2074
                        }
1358
2075
                        else {
1359
 
                                return stitch_cancel(C, op);
 
2076
                                return OPERATOR_PASS_THROUGH;
1360
2077
                        }
1361
 
 
1362
 
                /* Increase limit */
 
2078
                        /* Increase limit */
1363
2079
                case PADPLUSKEY:
1364
2080
                case WHEELUPMOUSE:
1365
 
                        if (event->alt) {
1366
 
                                stitch_state->limit_dist += 0.01;
1367
 
                                if (!stitch_process_data(stitch_state, scene, 0)) {
 
2081
                        if (event->val == KM_PRESS && event->alt) {
 
2082
                                state->limit_dist += 0.01f;
 
2083
                                if (!stitch_process_data(state, scene, FALSE)) {
1368
2084
                                        return stitch_cancel(C, op);
1369
2085
                                }
1370
2086
                                break;
1372
2088
                        else {
1373
2089
                                return OPERATOR_PASS_THROUGH;
1374
2090
                        }
1375
 
                /* Decrease limit */
 
2091
                        /* Decrease limit */
1376
2092
                case PADMINUS:
1377
2093
                case WHEELDOWNMOUSE:
1378
 
                        if (event->alt) {
1379
 
                                stitch_state->limit_dist -= 0.01;
1380
 
                                stitch_state->limit_dist = MAX2(0.01, stitch_state->limit_dist);
1381
 
                                if (!stitch_process_data(stitch_state, scene, 0)) {
 
2094
                        if (event->val == KM_PRESS && event->alt) {
 
2095
                                state->limit_dist -= 0.01f;
 
2096
                                state->limit_dist = MAX2(0.01f, state->limit_dist);
 
2097
                                if (!stitch_process_data(state, scene, FALSE)) {
1382
2098
                                        return stitch_cancel(C, op);
1383
2099
                                }
1384
2100
                                break;
1387
2103
                                return OPERATOR_PASS_THROUGH;
1388
2104
                        }
1389
2105
 
1390
 
                /* Use Limit (Default off)*/
 
2106
                        /* Use Limit (Default off)*/
1391
2107
                case LKEY:
1392
2108
                        if (event->val == KM_PRESS) {
1393
 
                                stitch_state->use_limit = !stitch_state->use_limit;
1394
 
                                if (!stitch_process_data(stitch_state, scene, 0)) {
 
2109
                                state->use_limit = !state->use_limit;
 
2110
                                if (!stitch_process_data(state, scene, FALSE)) {
1395
2111
                                        return stitch_cancel(C, op);
1396
2112
                                }
1397
2113
                                break;
1400
2116
 
1401
2117
                case IKEY:
1402
2118
                        if (event->val == KM_PRESS) {
1403
 
                                stitch_state->static_island++;
1404
 
                                stitch_state->static_island %= stitch_state->element_map->totalIslands;
 
2119
                                state->static_island++;
 
2120
                                state->static_island %= state->element_map->totalIslands;
1405
2121
 
1406
 
                                if (!stitch_process_data(stitch_state, scene, 0)) {
 
2122
                                if (!stitch_process_data(state, scene, FALSE)) {
1407
2123
                                        return stitch_cancel(C, op);
1408
2124
                                }
1409
2125
                                break;
1412
2128
 
1413
2129
                case MKEY:
1414
2130
                        if (event->val == KM_PRESS) {
1415
 
                                stitch_state->midpoints = !stitch_state->midpoints;
1416
 
                                if (!stitch_process_data(stitch_state, scene, 0)) {
 
2131
                                state->midpoints = !state->midpoints;
 
2132
                                if (!stitch_process_data(state, scene, FALSE)) {
1417
2133
                                        return stitch_cancel(C, op);
1418
2134
                                }
1419
2135
                        }
1420
2136
                        break;
1421
2137
 
1422
 
                /* Select geometry*/
 
2138
                        /* Select geometry*/
1423
2139
                case RIGHTMOUSE:
1424
2140
                        if (!event->shift) {
1425
2141
                                return stitch_cancel(C, op);
1426
2142
                        }
1427
 
                        if (event->val == KM_RELEASE && !(U.flag & USER_LMOUSESELECT)) {
1428
 
                                stitch_select(C, scene, event, stitch_state);
 
2143
                        if (event->val == KM_PRESS && !(U.flag & USER_LMOUSESELECT)) {
 
2144
                                stitch_select(C, scene, event, state);
1429
2145
 
1430
 
                                if (!stitch_process_data(stitch_state, scene, 0)) {
 
2146
                                if (!stitch_process_data(state, scene, FALSE)) {
1431
2147
                                        return stitch_cancel(C, op);
1432
2148
                                }
1433
2149
                                break;
1434
2150
                        }
1435
2151
                        return OPERATOR_RUNNING_MODAL;
1436
2152
 
1437
 
                /* snap islands on/off */
 
2153
                        /* snap islands on/off */
1438
2154
                case SKEY:
1439
2155
                        if (event->val == KM_PRESS) {
1440
 
                                stitch_state->snap_islands = !stitch_state->snap_islands;
1441
 
                                if (!stitch_process_data(stitch_state, scene, 0)) {
 
2156
                                state->snap_islands = !state->snap_islands;
 
2157
                                if (!stitch_process_data(state, scene, FALSE)) {
1442
2158
                                        return stitch_cancel(C, op);
1443
2159
                                }
1444
2160
                                break;
1447
2163
                                return OPERATOR_RUNNING_MODAL;
1448
2164
                        }
1449
2165
 
 
2166
                        /* switch between edge/vertex mode */
 
2167
                case TABKEY:
 
2168
                        if (event->val == KM_PRESS) {
 
2169
                                stitch_switch_selection_mode(state);
 
2170
 
 
2171
                                if (!stitch_process_data(state, scene, FALSE)) {
 
2172
                                        return stitch_cancel(C, op);
 
2173
                                }
 
2174
                        }
 
2175
                        break;
 
2176
 
1450
2177
                default:
1451
2178
                        return OPERATOR_RUNNING_MODAL;
1452
2179
        }
1453
2180
 
1454
2181
        /* if updated settings, renew feedback message */
1455
 
        stitch_update_header(stitch_state, C);
 
2182
        stitch_update_header(state, C);
1456
2183
        ED_region_tag_redraw(CTX_wm_region(C));
1457
2184
        return OPERATOR_RUNNING_MODAL;
1458
2185
}
1461
2188
{
1462
2189
        PropertyRNA *prop;
1463
2190
 
 
2191
        static EnumPropertyItem stitch_modes[] = {
 
2192
            {STITCH_VERT, "VERTEX", 0, "Vertex", ""},
 
2193
            {STITCH_EDGE, "EDGE", 0, "Edge", ""},
 
2194
            {0, NULL, 0, NULL, NULL}
 
2195
        };
 
2196
 
1464
2197
        /* identifiers */
1465
2198
        ot->name = "Stitch";
1466
2199
        ot->description = "Stitch selected UV vertices by proximity";
1485
2218
                    "Island that stays in place when stitching islands", 0, INT_MAX);
1486
2219
        RNA_def_boolean(ot->srna, "midpoint_snap", 0, "Snap At Midpoint",
1487
2220
                        "UVs are stitched at midpoint instead of at static island");
 
2221
        RNA_def_boolean(ot->srna, "clear_seams", 1, "Clear Seams",
 
2222
                        "Clear seams of stitched edges");
 
2223
        RNA_def_enum(ot->srna, "mode", stitch_modes, STITCH_VERT, "Operation Mode",
 
2224
                     "Use vertex or edge stitching");
 
2225
        prop =  RNA_def_enum(ot->srna, "stored_mode", stitch_modes, STITCH_VERT, "Stored Operation Mode",
 
2226
                             "Use vertex or edge stitching");
 
2227
        RNA_def_property_flag(prop, PROP_HIDDEN);
1488
2228
        prop = RNA_def_collection_runtime(ot->srna, "selection", &RNA_SelectedUvElement, "Selection", "");
1489
2229
        /* Selection should not be editable or viewed in toolbar */
1490
2230
        RNA_def_property_flag(prop, PROP_HIDDEN);