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