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