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