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