Change !BLI_ghashIterator_isDone to BLI_ghashIterator_notDone. It is
[blender.git] / source / blender / editors / sculpt_paint / sculpt_uv.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software  Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) Blender Foundation, 2002-2009
19  * All rights reserved.
20  *
21  * Contributor(s): Antony Riakiotakis
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  *
25  * UV Sculpt tools
26  *
27  */
28
29 /** \file blender/editors/sculpt_paint/sculpt_uv.c
30  *  \ingroup edsculpt
31  */
32
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_utildefines.h"
37 #include "BLI_math.h"
38 #include "BLI_ghash.h"
39
40 #include "DNA_object_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_brush_types.h"
43 #include "DNA_mesh_types.h"
44 #include "DNA_meshdata_types.h"
45
46 #include "BKE_brush.h"
47 #include "BKE_paint.h"
48 #include "BKE_context.h"
49 #include "BKE_main.h"
50 #include "BKE_depsgraph.h"
51 #include "BKE_mesh.h"
52 #include "BKE_customdata.h"
53 #include "BKE_tessmesh.h"
54
55 #include "ED_screen.h"
56 #include "ED_image.h"
57 #include "ED_mesh.h"
58
59 #include "WM_api.h"
60 #include "WM_types.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64 #include "RNA_enum_types.h"
65
66 #include "paint_intern.h"
67 #include "uvedit_intern.h"
68
69 #include "UI_view2d.h"
70
71 #define MARK_BOUNDARY   1
72
73 typedef struct UvAdjacencyElement {
74         /* pointer to original uvelement */
75         UvElement *element;
76         /* uv pointer for convenience. Caution, this points to the original UVs! */
77         float *uv;
78         /* general use flag (Used to check if Element is boundary here) */
79         char flag;
80 } UvAdjacencyElement;
81
82 typedef struct UvEdge {
83         unsigned int uv1;
84         unsigned int uv2;
85         /* general use flag (Used to check if edge is boundary here, and propagates to adjacency elements) */
86         char flag;
87 } UvEdge;
88
89 typedef struct UVInitialStrokeElement {
90         /* index to unique uv */
91         int uv;
92
93         /* strength of brush on initial position */
94         float strength;
95
96         /* initial uv position */
97         float initial_uv[2];
98 } UVInitialStrokeElement;
99
100 typedef struct UVInitialStroke {
101         /* Initial Selection,for grab brushes for instance */
102         UVInitialStrokeElement *initialSelection;
103
104         /* total initially selected UVs*/
105         int totalInitialSelected;
106
107         /* initial mouse coordinates */
108         float init_coord[2];
109 } UVInitialStroke;
110
111
112 /* custom data for uv smoothing brush */
113 typedef struct UvSculptData {
114         /* Contains the first of each set of coincident uvs.
115          * These will be used to perform smoothing on and propagate the changes
116          * to their coincident uvs */
117         UvAdjacencyElement *uv;
118
119         /* ...Is what it says */
120         int totalUniqueUvs;
121
122         /* Edges used for adjacency info, used with laplacian smoothing */
123         UvEdge *uvedges;
124
125         /* need I say more? */
126         int totalUvEdges;
127
128         /* data for initial stroke, used by tools like grab */
129         UVInitialStroke *initial_stroke;
130
131         /* timer to be used for airbrush-type brush */
132         wmTimer *timer;
133
134         /* to determine quickly adjacent uvs */
135         UvElementMap *elementMap;
136
137         /* uvsmooth Paint for fast reference */
138         Paint *uvsculpt;
139         
140         /* tool to use. duplicating here to change if modifier keys are pressed */
141         char tool;
142
143         /* store invert flag here */
144         char invert;
145 } UvSculptData;
146
147
148 static Brush *uv_sculpt_brush(bContext *C)
149 {
150         Scene *scene = CTX_data_scene(C);
151         ToolSettings *settings = scene->toolsettings;
152
153         if (!settings->uvsculpt)
154                 return NULL;
155         return paint_brush(&settings->uvsculpt->paint);
156 }
157
158
159 static int uv_sculpt_brush_poll(bContext *C)
160 {
161         BMEditMesh *em;
162         int ret;
163         Object *obedit = CTX_data_edit_object(C);
164         SpaceImage *sima = CTX_wm_space_image(C);
165         Scene *scene = CTX_data_scene(C);
166         ToolSettings *toolsettings = scene->toolsettings;
167
168         if (!uv_sculpt_brush(C) || !obedit || obedit->type != OB_MESH)
169                 return 0;
170
171         em = BMEdit_FromObject(obedit);
172         ret = EDBM_mtexpoly_check(em);
173
174         if (ret && sima) {
175                 ARegion *ar = CTX_wm_region(C);
176                 if ((toolsettings->use_uv_sculpt) && ar->regiontype == RGN_TYPE_WINDOW)
177                         return 1;
178         }
179
180         return 0;
181 }
182
183
184 void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings)
185 {
186         if (settings->use_uv_sculpt) {
187                 if (!settings->uvsculpt) {
188                         settings->uvsculpt = MEM_callocN(sizeof(*settings->uvsculpt), "UV Smooth paint");
189                         settings->uv_sculpt_tool = UV_SCULPT_TOOL_GRAB;
190                         settings->uv_sculpt_settings = UV_SCULPT_LOCK_BORDERS | UV_SCULPT_ALL_ISLANDS;
191                         settings->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN;
192                 }
193
194                 BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
195
196                 WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
197                                          brush_drawcursor_texpaint_uvsculpt, NULL);
198         }
199         else {
200                 if (settings->uvsculpt)
201                         settings->uvsculpt->paint.flags &= ~PAINT_SHOW_BRUSH;
202         }
203 }
204
205 int uv_sculpt_poll(bContext *C)
206 {
207         return uv_sculpt_brush_poll(C);
208 }
209
210 /*********** Improved Laplacian Relaxation Operator ************************/
211 /* original code by Raul Fernandez Hernandez "farsthary"                   *
212  * adapted to uv smoothing by Antony Riakiatakis                           *
213  ***************************************************************************/
214
215 typedef struct Temp_UvData {
216         float sum_co[2], p[2], b[2], sum_b[2];
217         int ncounter;
218 } Temp_UVData;
219
220
221
222 static void HC_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, float mouse_coord[2],
223                                        float alpha, float radius, float aspectRatio)
224 {
225         Temp_UVData *tmp_uvdata;
226         float diff[2];
227         int i;
228         float radius_root = sqrt(radius);
229         Brush *brush = paint_brush(sculptdata->uvsculpt);
230
231         tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data");
232
233         /* counting neighbors */
234         for (i = 0; i < sculptdata->totalUvEdges; i++) {
235                 UvEdge *tmpedge = sculptdata->uvedges + i;
236                 tmp_uvdata[tmpedge->uv1].ncounter++;
237                 tmp_uvdata[tmpedge->uv2].ncounter++;
238
239                 add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv);
240                 add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv);
241         }
242
243         for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
244                 copy_v2_v2(diff, tmp_uvdata[i].sum_co);
245                 mul_v2_fl(diff, 1.f / tmp_uvdata[i].ncounter);
246                 copy_v2_v2(tmp_uvdata[i].p, diff);
247
248                 tmp_uvdata[i].b[0] = diff[0] - sculptdata->uv[i].uv[0];
249                 tmp_uvdata[i].b[1] = diff[1] - sculptdata->uv[i].uv[1];
250         }
251
252         for (i = 0; i < sculptdata->totalUvEdges; i++) {
253                 UvEdge *tmpedge = sculptdata->uvedges + i;
254                 add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_b, tmp_uvdata[tmpedge->uv2].b);
255                 add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_b, tmp_uvdata[tmpedge->uv1].b);
256         }
257
258         for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
259                 float dist;
260                 /* This is supposed to happen only if "Pin Edges" is on, since we have initialization on stroke start
261                  * If ever uv brushes get their own mode we should check for toolsettings option too */
262                 if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) {
263                         continue;
264                 }
265
266                 sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord);
267                 diff[1] /= aspectRatio;
268                 if ((dist = dot_v2v2(diff, diff)) <= radius) {
269                         UvElement *element;
270                         float strength;
271                         strength = alpha * BKE_brush_curve_strength(brush, sqrt(dist), radius_root);
272
273                         sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] + strength * (tmp_uvdata[i].p[0] - 0.5f * (tmp_uvdata[i].b[0] + tmp_uvdata[i].sum_b[0] / tmp_uvdata[i].ncounter));
274                         sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] + strength * (tmp_uvdata[i].p[1] - 0.5f * (tmp_uvdata[i].b[1] + tmp_uvdata[i].sum_b[1] / tmp_uvdata[i].ncounter));
275
276                         for (element = sculptdata->uv[i].element; element; element = element->next) {
277                                 MLoopUV *luv;
278                                 BMLoop *l;
279
280                                 if (element->separate && element != sculptdata->uv[i].element)
281                                         break;
282
283                                 l = element->l;
284                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
285                                 copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
286                         }
287                 }
288         }
289
290         MEM_freeN(tmp_uvdata);
291
292         return;
293 }
294
295 static void laplacian_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, float mouse_coord[2], float alpha, float radius, float aspectRatio)
296 {
297         Temp_UVData *tmp_uvdata;
298         float diff[2];
299         int i;
300         float radius_root = sqrt(radius);
301         Brush *brush = paint_brush(sculptdata->uvsculpt);
302
303         tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data");
304
305         /* counting neighbors */
306         for (i = 0; i < sculptdata->totalUvEdges; i++) {
307                 UvEdge *tmpedge = sculptdata->uvedges + i;
308                 tmp_uvdata[tmpedge->uv1].ncounter++;
309                 tmp_uvdata[tmpedge->uv2].ncounter++;
310
311                 add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv);
312                 add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv);
313         }
314
315         /* Original Lacplacian algorithm included removal of normal component of translation. here it is not
316          * needed since we translate along the UV plane always.*/
317         for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
318                 copy_v2_v2(tmp_uvdata[i].p, tmp_uvdata[i].sum_co);
319                 mul_v2_fl(tmp_uvdata[i].p, 1.f / tmp_uvdata[i].ncounter);
320         }
321
322         for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
323                 float dist;
324                 /* This is supposed to happen only if "Pin Edges" is on, since we have initialization on stroke start
325                  * If ever uv brushes get their own mode we should check for toolsettings option too */
326                 if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) {
327                         continue;
328                 }
329
330                 sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord);
331                 diff[1] /= aspectRatio;
332                 if ((dist = dot_v2v2(diff, diff)) <= radius) {
333                         UvElement *element;
334                         float strength;
335                         strength = alpha * BKE_brush_curve_strength(brush, sqrt(dist), radius_root);
336
337                         sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] + strength * tmp_uvdata[i].p[0];
338                         sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] + strength * tmp_uvdata[i].p[1];
339
340                         for (element = sculptdata->uv[i].element; element; element = element->next) {
341                                 MLoopUV *luv;
342                                 BMLoop *l;
343
344                                 if (element->separate && element != sculptdata->uv[i].element)
345                                         break;
346
347                                 l = element->l;
348                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
349                                 copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
350                         }
351                 }
352         }
353
354         MEM_freeN(tmp_uvdata);
355
356         return;
357 }
358
359
360 static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, wmEvent *event, Object *obedit)
361 {
362         float co[2], radius, radius_root;
363         Scene *scene = CTX_data_scene(C);
364         ARegion *ar = CTX_wm_region(C);
365         BMEditMesh *em = BMEdit_FromObject(obedit);
366         unsigned int tool;
367         UvSculptData *sculptdata = (UvSculptData *)op->customdata;
368         SpaceImage *sima;
369         int invert;
370         int width, height;
371         float aspectRatio;
372         float alpha, zoomx, zoomy;
373         Brush *brush = paint_brush(sculptdata->uvsculpt);
374         ToolSettings *toolsettings = CTX_data_tool_settings(C);
375         tool = sculptdata->tool;
376         invert = sculptdata->invert ? -1 : 1;
377         alpha = BKE_brush_alpha_get(scene, brush);
378         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
379
380         sima = CTX_wm_space_image(C);
381         ED_space_image_get_size(sima, &width, &height);
382         ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
383
384         radius = BKE_brush_size_get(scene, brush) / (width * zoomx);
385         aspectRatio = width / (float)height;
386
387         /* We will compare squares to save some computation */
388         radius = radius * radius;
389         radius_root = sqrt(radius);
390
391         /*
392          * Pinch Tool
393          */
394         if (tool == UV_SCULPT_TOOL_PINCH) {
395                 int i;
396                 alpha *= invert;
397                 for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
398                         float dist, diff[2];
399                         /* This is supposed to happen only if "Lock Borders" is on, since we have initialization on stroke start
400                          * If ever uv brushes get their own mode we should check for toolsettings option too */
401                         if (sculptdata->uv[i].flag & MARK_BOUNDARY) {
402                                 continue;
403                         }
404
405                         sub_v2_v2v2(diff, sculptdata->uv[i].uv, co);
406                         diff[1] /= aspectRatio;
407                         if ((dist = dot_v2v2(diff, diff)) <= radius) {
408                                 UvElement *element;
409                                 float strength;
410                                 strength = alpha * BKE_brush_curve_strength(brush, sqrt(dist), radius_root);
411                                 normalize_v2(diff);
412
413                                 sculptdata->uv[i].uv[0] -= strength * diff[0] * 0.001f;
414                                 sculptdata->uv[i].uv[1] -= strength * diff[1] * 0.001f;
415
416                                 for (element = sculptdata->uv[i].element; element; element = element->next) {
417                                         MLoopUV *luv;
418                                         BMLoop *l;
419
420                                         if (element->separate && element != sculptdata->uv[i].element)
421                                                 break;
422
423                                         l = element->l;
424                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
425                                         copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
426                                 }
427                         }
428                 }
429         }
430
431         /*
432          * Smooth Tool
433          */
434         else if (tool == UV_SCULPT_TOOL_RELAX) {
435                 unsigned int method = toolsettings->uv_relax_method;
436                 if (method == UV_SCULPT_TOOL_RELAX_HC) {
437                         HC_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio);
438                 }
439                 else {
440                         laplacian_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio);
441                 }
442         }
443
444         /*
445          * Grab Tool
446          */
447         else if (tool == UV_SCULPT_TOOL_GRAB) {
448                 int i;
449                 float diff[2];
450                 sub_v2_v2v2(diff, co, sculptdata->initial_stroke->init_coord);
451
452                 for (i = 0; i < sculptdata->initial_stroke->totalInitialSelected; i++) {
453                         UvElement *element;
454                         int uvindex = sculptdata->initial_stroke->initialSelection[i].uv;
455                         float strength = sculptdata->initial_stroke->initialSelection[i].strength;
456                         sculptdata->uv[uvindex].uv[0] = sculptdata->initial_stroke->initialSelection[i].initial_uv[0] + strength * diff[0];
457                         sculptdata->uv[uvindex].uv[1] = sculptdata->initial_stroke->initialSelection[i].initial_uv[1] + strength * diff[1];
458
459                         for (element = sculptdata->uv[uvindex].element; element; element = element->next) {
460                                 MLoopUV *luv;
461                                 BMLoop *l;
462
463                                 if (element->separate && element != sculptdata->uv[uvindex].element)
464                                         break;
465
466                                 l = element->l;
467                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
468                                 copy_v2_v2(luv->uv, sculptdata->uv[uvindex].uv);
469                         }
470                 }
471         }
472 }
473
474
475 static void uv_sculpt_stroke_exit(bContext *C, wmOperator *op)
476 {
477         UvSculptData *data = op->customdata;
478         if (data->timer) {
479                 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), data->timer);
480         }
481         if (data->elementMap) {
482                 EDBM_uv_element_map_free(data->elementMap);
483         }
484         if (data->uv) {
485                 MEM_freeN(data->uv);
486         }
487         if (data->uvedges) {
488                 MEM_freeN(data->uvedges);
489         }
490         if (data->initial_stroke) {
491                 if (data->initial_stroke->initialSelection) {
492                         MEM_freeN(data->initial_stroke->initialSelection);
493                 }
494                 MEM_freeN(data->initial_stroke);
495         }
496
497         MEM_freeN(data);
498         op->customdata = NULL;
499 }
500
501 static int uv_element_offset_from_face_get(UvElementMap *map, BMFace *efa, BMLoop *l, int island_index, int doIslands)
502 {
503         UvElement *element = ED_uv_element_get(map, efa, l);
504         if (!element || (doIslands && element->island != island_index)) {
505                 return -1;
506         }
507         return element - map->buf;
508 }
509
510
511 static unsigned int uv_edge_hash(const void *key)
512 {
513         UvEdge *edge = (UvEdge *)key;
514         return (BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv2)) +
515                 BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv1)));
516 }
517
518 static int uv_edge_compare(const void *a, const void *b)
519 {
520         UvEdge *edge1 = (UvEdge *)a;
521         UvEdge *edge2 = (UvEdge *)b;
522
523         if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
524                 return 0;
525         }
526         return 1;
527 }
528
529
530 static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, wmEvent *event)
531 {
532         Scene *scene = CTX_data_scene(C);
533         Object *obedit = CTX_data_edit_object(C);
534         ToolSettings *ts = scene->toolsettings;
535         UvSculptData *data = MEM_callocN(sizeof(*data), "UV Smooth Brush Data");
536         BMEditMesh *em = BMEdit_FromObject(obedit);
537         BMesh *bm = em->bm;
538
539         op->customdata = data;
540
541         if (data) {
542                 int counter = 0, i;
543                 ARegion *ar = CTX_wm_region(C);
544                 float co[2];
545                 BMFace *efa;
546                 MLoopUV *luv;
547                 BMLoop *l;
548                 BMIter iter, liter;
549
550                 UvEdge *edges;
551                 GHash *edgeHash;
552                 GHashIterator *ghi;
553
554                 int do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS);
555                 int island_index = 0;
556                 /* Holds, for each UvElement in elementMap, a pointer to its unique uv.*/
557                 int *uniqueUv;
558                 data->tool = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_SMOOTH) ? UV_SCULPT_TOOL_RELAX : ts->uv_sculpt_tool;
559                 data->invert = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_INVERT) ? 1 : 0;
560
561                 data->uvsculpt = &ts->uvsculpt->paint;
562
563                 if (do_island_optimization) {
564                         /* We will need island information */
565                         if (ts->uv_flag & UV_SYNC_SELECTION) {
566                                 data->elementMap = EDBM_uv_element_map_create(em, 0, 1);
567                         }
568                         else {
569                                 data->elementMap = EDBM_uv_element_map_create(em, 1, 1);
570                         }
571                 }
572                 else {
573                         if (ts->uv_flag & UV_SYNC_SELECTION) {
574                                 data->elementMap = EDBM_uv_element_map_create(em, 0, 0);
575                         }
576                         else {
577                                 data->elementMap = EDBM_uv_element_map_create(em, 1, 0);
578                         }
579                 }
580
581                 if (!data->elementMap) {
582                         uv_sculpt_stroke_exit(C, op);
583                         return NULL;
584                 }
585
586                 /* Mouse coordinates, useful for some functions like grab and sculpt all islands */
587                 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
588
589                 /* we need to find the active island here */
590                 if (do_island_optimization) {
591                         UvElement *element;
592                         NearestHit hit;
593                         Image *ima = CTX_data_edit_image(C);
594                         uv_find_nearest_vert(scene, ima, em, co, NULL, &hit);
595
596                         element = ED_uv_element_get(data->elementMap, hit.efa, hit.l);
597                         island_index = element->island;
598                 }
599
600
601                 /* Count 'unique' uvs */
602                 for (i = 0; i < data->elementMap->totalUVs; i++) {
603                         if (data->elementMap->buf[i].separate &&
604                             (!do_island_optimization || data->elementMap->buf[i].island == island_index))
605                         {
606                                 counter++;
607                         }
608                 }
609
610                 /* Allocate the unique uv buffers */
611                 data->uv = MEM_mallocN(sizeof(*data->uv) * counter, "uv_brush_unique_uvs");
612                 uniqueUv = MEM_mallocN(sizeof(*uniqueUv) * data->elementMap->totalUVs, "uv_brush_unique_uv_map");
613                 edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "uv_brush_edge_hash");
614                 /* we have at most totalUVs edges */
615                 edges = MEM_mallocN(sizeof(*edges) * data->elementMap->totalUVs, "uv_brush_all_edges");
616                 if (!data->uv || !uniqueUv || !edgeHash || !edges) {
617                         if (edges) {
618                                 MEM_freeN(edges);
619                         }
620                         if (uniqueUv) {
621                                 MEM_freeN(uniqueUv);
622                         }
623                         if (edgeHash) {
624                                 MEM_freeN(edgeHash);
625                         }
626                         uv_sculpt_stroke_exit(C, op);
627                         return NULL;
628                 }
629
630                 data->totalUniqueUvs = counter;
631                 /* So that we can use this as index for the UvElements */
632                 counter = -1;
633                 /* initialize the unique UVs */
634                 for (i = 0; i < bm->totvert; i++) {
635                         UvElement *element = data->elementMap->vert[i];
636                         for (; element; element = element->next) {
637                                 if (element->separate) {
638                                         if (do_island_optimization && (element->island != island_index)) {
639                                                 /* skip this uv if not on the active island */
640                                                 for (; element->next && !(element->next->separate); element = element->next)
641                                                         ;
642                                                 continue;
643                                         }
644
645                                         l = element->l;
646                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
647
648                                         counter++;
649                                         data->uv[counter].element = element;
650                                         data->uv[counter].flag = 0;
651                                         data->uv[counter].uv = luv->uv;
652                                 }
653                                 /* pointer arithmetic to the rescue, as always :)*/
654                                 uniqueUv[element - data->elementMap->buf] = counter;
655                         }
656                 }
657
658
659                 /* Now, on to generate our uv connectivity data */
660                 counter = 0;
661                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
662                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
663                                 int offset1, itmp1 = uv_element_offset_from_face_get(data->elementMap, efa, l, island_index, do_island_optimization);
664                                 int offset2, itmp2 = uv_element_offset_from_face_get(data->elementMap, efa, l->next, island_index, do_island_optimization);
665
666                                 /* Skip edge if not found(unlikely) or not on valid island */
667                                 if (itmp1 == -1 || itmp2 == -1)
668                                         continue;
669
670                                 offset1 = uniqueUv[itmp1];
671                                 offset2 = uniqueUv[itmp2];
672
673                                 edges[counter].flag = 0;
674                                 /* using an order policy, sort uvs according to address space. This avoids
675                                  * Having two different UvEdges with the same uvs on different positions  */
676                                 if (offset1 < offset2) {
677                                         edges[counter].uv1 = offset1;
678                                         edges[counter].uv2 = offset2;
679                                 }
680                                 else {
681                                         edges[counter].uv1 = offset2;
682                                         edges[counter].uv2 = offset1;
683                                 }
684                                 /* Hack! Set the value of the key to its flag. Now we can set the flag when an edge exists twice :) */
685                                 if (BLI_ghash_haskey(edgeHash, &edges[counter])) {
686                                         char *flag = BLI_ghash_lookup(edgeHash, &edges[counter]);
687                                         *flag = 1;
688                                 }
689                                 else {
690                                         /* Hack mentioned */
691                                         BLI_ghash_insert(edgeHash, &edges[counter], &edges[counter].flag);
692                                 }
693                                 counter++;
694                         }
695                 }
696
697                 MEM_freeN(uniqueUv);
698
699                 /* Allocate connectivity data, we allocate edges once */
700                 data->uvedges = MEM_mallocN(sizeof(*data->uvedges) * BLI_ghash_size(edgeHash), "uv_brush_edge_connectivity_data");
701                 if (!data->uvedges) {
702                         BLI_ghash_free(edgeHash, NULL, NULL);
703                         MEM_freeN(edges);
704                         uv_sculpt_stroke_exit(C, op);
705                         return NULL;
706                 }
707                 ghi = BLI_ghashIterator_new(edgeHash);
708                 if (!ghi) {
709                         BLI_ghash_free(edgeHash, NULL, NULL);
710                         MEM_freeN(edges);
711                         uv_sculpt_stroke_exit(C, op);
712                         return NULL;
713                 }
714                 /* fill the edges with data */
715                 for (i = 0; BLI_ghashIterator_notDone(ghi); BLI_ghashIterator_step(ghi)) {
716                         data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
717                 }
718                 data->totalUvEdges = BLI_ghash_size(edgeHash);
719
720                 /* cleanup temporary stuff */
721                 BLI_ghashIterator_free(ghi);
722                 BLI_ghash_free(edgeHash, NULL, NULL);
723                 MEM_freeN(edges);
724
725                 /* transfer boundary edge property to uvs */
726                 if (ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS) {
727                         for (i = 0; i < data->totalUvEdges; i++) {
728                                 if (!data->uvedges[i].flag) {
729                                         data->uv[data->uvedges[i].uv1].flag |= MARK_BOUNDARY;
730                                         data->uv[data->uvedges[i].uv2].flag |= MARK_BOUNDARY;
731                                 }
732                         }
733                 }
734
735                 /* Allocate initial selection for grab tool */
736                 if (data->tool == UV_SCULPT_TOOL_GRAB) {
737                         float radius, radius_root;
738                         UvSculptData *sculptdata = (UvSculptData *)op->customdata;
739                         SpaceImage *sima;
740                         int width, height;
741                         float aspectRatio;
742                         float alpha, zoomx, zoomy;
743                         Brush *brush = paint_brush(sculptdata->uvsculpt);
744
745                         alpha = BKE_brush_alpha_get(scene, brush);
746
747                         radius = BKE_brush_size_get(scene, brush);
748                         sima = CTX_wm_space_image(C);
749                         ED_space_image_get_size(sima, &width, &height);
750                         ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
751
752                         aspectRatio = width / (float)height;
753                         radius /= (width * zoomx);
754                         radius = radius * radius;
755                         radius_root = sqrt(radius);
756
757                         /* Allocate selection stack */
758                         data->initial_stroke = MEM_mallocN(sizeof(*data->initial_stroke), "uv_sculpt_initial_stroke");
759                         if (!data->initial_stroke) {
760                                 uv_sculpt_stroke_exit(C, op);
761                         }
762                         data->initial_stroke->initialSelection = MEM_mallocN(sizeof(*data->initial_stroke->initialSelection) * data->totalUniqueUvs, "uv_sculpt_initial_selection");
763                         if (!data->initial_stroke->initialSelection) {
764                                 uv_sculpt_stroke_exit(C, op);
765                         }
766
767                         copy_v2_v2(data->initial_stroke->init_coord, co);
768
769                         counter = 0;
770
771                         for (i = 0; i < data->totalUniqueUvs; i++) {
772                                 float dist, diff[2];
773                                 if (data->uv[i].flag & MARK_BOUNDARY) {
774                                         continue;
775                                 }
776
777                                 sub_v2_v2v2(diff, data->uv[i].uv, co);
778                                 diff[1] /= aspectRatio;
779                                 if ((dist = dot_v2v2(diff, diff)) <= radius) {
780                                         float strength;
781                                         strength = alpha * BKE_brush_curve_strength(brush, sqrt(dist), radius_root);
782
783                                         data->initial_stroke->initialSelection[counter].uv = i;
784                                         data->initial_stroke->initialSelection[counter].strength = strength;
785                                         copy_v2_v2(data->initial_stroke->initialSelection[counter].initial_uv, data->uv[i].uv);
786                                         counter++;
787                                 }
788                         }
789
790                         data->initial_stroke->totalInitialSelected = counter;
791                 }
792         }
793
794         return op->customdata;
795 }
796
797 static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
798 {
799         UvSculptData *data;
800         Object *obedit = CTX_data_edit_object(C);
801
802         if (!(data = uv_sculpt_stroke_init(C, op, event))) {
803                 return OPERATOR_CANCELLED;
804         }
805
806         uv_sculpt_stroke_apply(C, op, event, obedit);
807
808         data->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.001f);
809
810         if (!data->timer) {
811                 uv_sculpt_stroke_exit(C, op);
812                 return OPERATOR_CANCELLED;
813         }
814         WM_event_add_modal_handler(C, op);
815
816         return OPERATOR_RUNNING_MODAL;
817 }
818
819
820 static int uv_sculpt_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
821 {
822         UvSculptData *data = (UvSculptData *)op->customdata;
823         Object *obedit = CTX_data_edit_object(C);
824
825         switch (event->type) {
826                 case LEFTMOUSE:
827                 case MIDDLEMOUSE:
828                 case RIGHTMOUSE:
829                         uv_sculpt_stroke_exit(C, op);
830                         return OPERATOR_FINISHED;
831
832                 case MOUSEMOVE:
833                 case INBETWEEN_MOUSEMOVE:
834                         uv_sculpt_stroke_apply(C, op, event, obedit);
835                         break;
836                 case TIMER:
837                         if (event->customdata == data->timer)
838                                 uv_sculpt_stroke_apply(C, op, event, obedit);
839                         break;
840                 default:
841                         return OPERATOR_RUNNING_MODAL;
842         }
843
844         ED_region_tag_redraw(CTX_wm_region(C));
845         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
846         DAG_id_tag_update(obedit->data, 0);
847         return OPERATOR_RUNNING_MODAL;
848 }
849
850 void SCULPT_OT_uv_sculpt_stroke(wmOperatorType *ot)
851 {
852         static EnumPropertyItem stroke_mode_items[] = {
853                 {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Normal", "Apply brush normally"},
854                 {BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"},
855                 {BRUSH_STROKE_SMOOTH, "RELAX", 0, "Relax", "Switch brush to relax mode for duration of stroke"},
856                 {0}
857         };
858
859         /* identifiers */
860         ot->name = "Sculpt UVs";
861         ot->description = "Sculpt UVs using a brush";
862         ot->idname = "SCULPT_OT_uv_sculpt_stroke";
863
864         /* api callbacks */
865         ot->invoke = uv_sculpt_stroke_invoke;
866         ot->modal = uv_sculpt_stroke_modal;
867         ot->poll = uv_sculpt_poll;
868
869         /* flags */
870         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
871
872         /* props */
873         RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL, "Mode", "Stroke Mode");
874 }