Fix: stroke spacing fails in image editor, we need to account for
[blender.git] / source / blender / editors / sculpt_paint / paint_stroke.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) 2009 by Nicholas Bishop
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Jason Wilkins, Tom Musgrove.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  *
27  */
28
29 /** \file blender/editors/sculpt_paint/paint_stroke.c
30  *  \ingroup edsculpt
31  */
32
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_brush_types.h"
42
43 #include "RNA_access.h"
44
45 #include "BKE_context.h"
46 #include "BKE_paint.h"
47 #include "BKE_brush.h"
48
49 #include "WM_api.h"
50 #include "WM_types.h"
51
52 #include "BIF_gl.h"
53 #include "BIF_glutil.h"
54
55 #include "ED_screen.h"
56 #include "ED_view3d.h"
57
58 #include "paint_intern.h"
59
60 #include <float.h>
61 #include <math.h>
62
63 typedef struct PaintSample {
64         float mouse[2];
65
66         /* TODO: other input properties, e.g. tablet pressure */
67 } PaintSample;
68
69 typedef struct PaintStroke {
70         void *mode_data;
71         void *smooth_stroke_cursor;
72         wmTimer *timer;
73
74         /* Cached values */
75         ViewContext vc;
76         bglMats mats;
77         Brush *brush;
78
79         /* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
80          * to smooth the stroke */
81         PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
82         int num_samples;
83         int cur_sample;
84
85         float last_mouse_position[2];
86
87         /* Set whether any stroke step has yet occurred
88          * e.g. in sculpt mode, stroke doesn't start until cursor
89          * passes over the mesh */
90         int stroke_started;
91         /* event that started stroke, for modal() return */
92         int event_type;
93         
94         StrokeGetLocation get_location;
95         StrokeTestStart test_start;
96         StrokeUpdateStep update_step;
97         StrokeDone done;
98 } PaintStroke;
99
100 /*** Cursor ***/
101 static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata) 
102 {
103         Paint *paint = paint_get_active_from_context(C);
104         Brush *brush = paint_brush(paint);
105         PaintStroke *stroke = customdata;
106
107         if (stroke && brush && (brush->flag & BRUSH_SMOOTH_STROKE)) {
108                 glColor4ubv(paint->paint_cursor_col);
109                 glEnable(GL_LINE_SMOOTH);
110                 glEnable(GL_BLEND);
111
112                 sdrawline(x, y, (int)stroke->last_mouse_position[0],
113                           (int)stroke->last_mouse_position[1]);
114                 glDisable(GL_BLEND);
115                 glDisable(GL_LINE_SMOOTH);
116         }
117 }
118
119 /* if this is a tablet event, return tablet pressure and set *pen_flip
120  * to 1 if the eraser tool is being used, 0 otherwise */
121 static float event_tablet_data(wmEvent *event, int *pen_flip)
122 {
123         int erasor = 0;
124         float pressure = 1;
125
126         if (event->tablet_data) {
127                 wmTabletData *wmtab = event->tablet_data;
128
129                 erasor = (wmtab->Active == EVT_TABLET_ERASER);
130                 pressure = (wmtab->Active != EVT_TABLET_NONE) ? wmtab->Pressure : 1;
131         }
132
133         if (pen_flip)
134                 (*pen_flip) = erasor;
135
136         return pressure;
137 }
138
139 /* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
140 static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, const float mouse_in[2])
141 {
142         Scene *scene = CTX_data_scene(C);
143         Paint *paint = paint_get_active_from_context(C);
144         PaintMode mode = paintmode_get_active_from_context(C);
145         Brush *brush = paint_brush(paint);
146         PaintStroke *stroke = op->customdata;
147         float mouse_out[2];
148         PointerRNA itemptr;
149         float location[3];
150         float pressure;
151         int pen_flip;
152
153         /* see if tablet affects event */
154         pressure = event_tablet_data(event, &pen_flip);
155
156 /* the following code is adapted from texture paint. It may not be needed but leaving here
157  * just in case for reference (code in texpaint removed as part of refactoring).
158  * It's strange that only texpaint had these guards. */
159 #if 0
160         /* special exception here for too high pressure values on first touch in
161          * windows for some tablets, then we just skip first touch ..  */
162         if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush)))
163                 return;
164
165         /* This can be removed once fixed properly in
166          * BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user)
167          * at zero pressure we should do nothing 1/2^12 is 0.0002 which is the sensitivity of the most sensitive pen tablet available */
168         if (tablet && (pressure < 0.0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush)))
169                 return;
170 #endif
171
172         /* TODO: as sculpt and other paint modes are unified, this
173          * separation will go away */
174         if (paint_supports_jitter(mode)) {
175                 float delta[2];
176
177                 BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out);
178
179                 /* XXX: meh, this is round about because
180                  * BKE_brush_jitter_pos isn't written in the best way to
181                  * be reused here */
182                 if (brush->flag & BRUSH_JITTER_PRESSURE) {
183                         sub_v2_v2v2(delta, mouse_out, mouse_in);
184                         mul_v2_fl(delta, pressure);
185                         add_v2_v2v2(mouse_out, mouse_in, delta);
186                 }
187         }
188         else {
189                 copy_v2_v2(mouse_out, mouse_in);
190         }
191
192         /* TODO: can remove the if statement once all modes have this */
193         if (stroke->get_location)
194                 stroke->get_location(C, location, mouse_out);
195         else
196                 zero_v3(location);
197
198         /* Add to stroke */
199         RNA_collection_add(op->ptr, "stroke", &itemptr);
200
201         RNA_float_set_array(&itemptr, "location", location);
202         RNA_float_set_array(&itemptr, "mouse", mouse_out);
203         RNA_boolean_set(&itemptr, "pen_flip", pen_flip);
204         RNA_float_set(&itemptr, "pressure", pressure);
205
206         copy_v2_v2(stroke->last_mouse_position, mouse_out);
207
208         stroke->update_step(C, stroke, &itemptr);
209 }
210
211 /* Returns zero if no sculpt changes should be made, non-zero otherwise */
212 static int paint_smooth_stroke(PaintStroke *stroke, float output[2],
213                                const PaintSample *sample)
214 {
215         output[0] = sample->mouse[0];
216         output[1] = sample->mouse[1];
217
218         if ((stroke->brush->flag & BRUSH_SMOOTH_STROKE) &&  
219             !ELEM4(stroke->brush->sculpt_tool,
220                    SCULPT_TOOL_GRAB,
221                    SCULPT_TOOL_THUMB,
222                    SCULPT_TOOL_ROTATE,
223                    SCULPT_TOOL_SNAKE_HOOK) &&
224             !(stroke->brush->flag & BRUSH_ANCHORED) &&
225             !(stroke->brush->flag & BRUSH_RESTORE_MESH))
226         {
227                 float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u;
228                 float dx = stroke->last_mouse_position[0] - sample->mouse[0];
229                 float dy = stroke->last_mouse_position[1] - sample->mouse[1];
230
231                 /* If the mouse is moving within the radius of the last move,
232                  * don't update the mouse position. This allows sharp turns. */
233                 if (dx * dx + dy * dy < stroke->brush->smooth_stroke_radius * stroke->brush->smooth_stroke_radius)
234                         return 0;
235
236                 output[0] = sample->mouse[0] * v + stroke->last_mouse_position[0] * u;
237                 output[1] = sample->mouse[1] * v + stroke->last_mouse_position[1] * u;
238         }
239
240         return 1;
241 }
242
243 /* For brushes with stroke spacing enabled, moves mouse in steps
244  * towards the final mouse location. */
245 static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const float final_mouse[2])
246 {
247         PaintStroke *stroke = op->customdata;
248         int cnt = 0;
249
250         if (paint_space_stroke_enabled(stroke->brush)) {
251                 float mouse[2];
252                 float vec[2];
253                 float length, scale;
254
255                 copy_v2_v2(mouse, stroke->last_mouse_position);
256                 sub_v2_v2v2(vec, final_mouse, mouse);
257
258                 length = len_v2(vec);
259
260                 if (length > FLT_EPSILON) {
261                         const Scene *scene = CTX_data_scene(C);
262                         int steps;
263                         int i;
264                         float size_pressure = 1.0f;
265                         float pressure = event_tablet_data(event, NULL);
266
267                         /* XXX mysterious :) what has 'use size' do with this here... if you don't check for it, pressure fails */
268                         if (BKE_brush_use_size_pressure(scene, stroke->brush))
269                                 size_pressure = pressure;
270                         
271                         if (size_pressure > FLT_EPSILON) {
272                                 float zoomx, zoomy;
273                                 /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
274                                  * causing very high step sizes, hanging blender [#32381] */
275                                 const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
276                                 float spacing = stroke->brush->spacing;
277
278                                 /* stroke system is used for 2d paint too, so we need to account for
279                                  * the fact that brush can be scaled there. */
280                                 get_imapaint_zoom(C, &zoomx, &zoomy);
281
282                                 if (stroke->brush->flag & BRUSH_SPACING_PRESSURE)
283                                         spacing = max_ff(1.0f, spacing * (1.5f - pressure));
284
285                                 spacing *= max_ff(zoomx, zoomy);
286
287                                 scale = (size_clamp * spacing / 50.0f) / length;
288                                 if (scale > FLT_EPSILON) {
289                                         mul_v2_fl(vec, scale);
290
291                                         steps = (int)(1.0f / scale);
292
293                                         for (i = 0; i < steps; ++i, ++cnt) {
294                                                 add_v2_v2(mouse, vec);
295                                                 paint_brush_stroke_add_step(C, op, event, mouse);
296                                         }
297                                 }
298                         }
299                 }
300         }
301
302         return cnt;
303 }
304
305 /**** Public API ****/
306
307 PaintStroke *paint_stroke_new(bContext *C,
308                               StrokeGetLocation get_location,
309                               StrokeTestStart test_start,
310                               StrokeUpdateStep update_step,
311                               StrokeDone done, int event_type)
312 {
313         PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke");
314
315         stroke->brush = paint_brush(paint_get_active_from_context(C));
316         view3d_set_viewcontext(C, &stroke->vc);
317         if (stroke->vc.v3d)
318                 view3d_get_transformation(stroke->vc.ar, stroke->vc.rv3d, stroke->vc.obact, &stroke->mats);
319
320         stroke->get_location = get_location;
321         stroke->test_start = test_start;
322         stroke->update_step = update_step;
323         stroke->done = done;
324         stroke->event_type = event_type; /* for modal, return event */
325         
326         return stroke;
327 }
328
329 void paint_stroke_data_free(struct wmOperator *op)
330 {
331         MEM_freeN(op->customdata);
332         op->customdata = NULL;
333 }
334
335 static void stroke_done(struct bContext *C, struct wmOperator *op)
336 {
337         struct PaintStroke *stroke = op->customdata;
338
339         if (stroke->stroke_started && stroke->done)
340                 stroke->done(C, stroke);
341
342         if (stroke->timer) {
343                 WM_event_remove_timer(
344                         CTX_wm_manager(C),
345                         CTX_wm_window(C),
346                         stroke->timer);
347         }
348
349         if (stroke->smooth_stroke_cursor)
350                 WM_paint_cursor_end(CTX_wm_manager(C), stroke->smooth_stroke_cursor);
351
352         paint_stroke_data_free(op);
353 }
354
355 /* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
356 bool paint_space_stroke_enabled(Brush *br)
357 {
358         return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br);
359 }
360
361 /* return true if the brush size can change during paint (normally used for pressure) */
362 bool paint_supports_dynamic_size(Brush *br)
363 {
364         return !(br->flag & BRUSH_ANCHORED) &&
365                !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK);
366 }
367
368 bool paint_supports_jitter(PaintMode mode)
369 {
370         return ELEM3(mode, PAINT_SCULPT, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D);
371 }
372
373 #define PAINT_STROKE_MODAL_CANCEL 1
374
375 /* called in paint_ops.c, on each regeneration of keymaps  */
376 struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf)
377 {
378         static struct EnumPropertyItem modal_items[] = {
379                 {PAINT_STROKE_MODAL_CANCEL, "CANCEL", 0,
380                 "Cancel",
381                 "Cancel and undo a stroke in progress"},
382
383                 { 0 }
384         };
385
386         static const char *name = "Paint Stroke Modal";
387
388         struct wmKeyMap *keymap = WM_modalkeymap_get(keyconf, name);
389
390         /* this function is called for each spacetype, only needs to add map once */
391         if (!keymap) {
392                 keymap = WM_modalkeymap_add(keyconf, name, modal_items);
393
394                 /* items for modal map */
395                 WM_modalkeymap_add_item(
396                         keymap, ESCKEY, KM_PRESS, KM_ANY, 0, PAINT_STROKE_MODAL_CANCEL);
397         }
398
399         return keymap;
400 }
401
402 static void paint_stroke_add_sample(const Paint *paint,
403                                     PaintStroke *stroke,
404                                     float x, float y)
405 {
406         PaintSample *sample = &stroke->samples[stroke->cur_sample];
407         int max_samples = MIN2(PAINT_MAX_INPUT_SAMPLES,
408                                MAX2(paint->num_input_samples, 1));
409
410         sample->mouse[0] = x;
411         sample->mouse[1] = y;
412
413         stroke->cur_sample++;
414         if (stroke->cur_sample >= max_samples)
415                 stroke->cur_sample = 0;
416         if (stroke->num_samples < max_samples)
417                 stroke->num_samples++;
418 }
419
420 static void paint_stroke_sample_average(const PaintStroke *stroke,
421                                         PaintSample *average)
422 {
423         int i;
424         
425         memset(average, 0, sizeof(*average));
426
427         BLI_assert(stroke->num_samples > 0);
428         
429         for (i = 0; i < stroke->num_samples; i++)
430                 add_v2_v2(average->mouse, stroke->samples[i].mouse);
431
432         mul_v2_fl(average->mouse, 1.0f / stroke->num_samples);
433
434         /*printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);*/
435 }
436
437 int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
438 {
439         Paint *p = paint_get_active_from_context(C);
440         PaintStroke *stroke = op->customdata;
441         PaintSample sample_average;
442         float mouse[2];
443         int first = 0;
444
445         paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1]);
446         paint_stroke_sample_average(stroke, &sample_average);
447
448         /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
449          * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
450          * since the 2D deltas are zero -- code in this file needs to be updated to use the
451          * post-NDOF_MOTION MOUSEMOVE */
452         if (event->type == NDOF_MOTION)
453                 return OPERATOR_PASS_THROUGH;
454
455         if (!stroke->stroke_started) {
456                 copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
457                 stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
458                 BLI_assert((stroke->stroke_started & ~1) == 0);  /* 0/1 */
459
460                 if (stroke->stroke_started) {
461                         stroke->smooth_stroke_cursor =
462                             WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_stroke, stroke);
463
464                         if (stroke->brush->flag & BRUSH_AIRBRUSH)
465                                 stroke->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
466                 }
467
468                 first = 1;
469                 //ED_region_tag_redraw(ar);
470         }
471
472         /* Cancel */
473         if (event->type == EVT_MODAL_MAP && event->val == PAINT_STROKE_MODAL_CANCEL) {
474                 if (op->type->cancel)
475                         return op->type->cancel(C, op);
476                 else
477                         return paint_stroke_cancel(C, op);
478         }
479
480         if (event->type == stroke->event_type && event->val == KM_RELEASE) {
481                 stroke_done(C, op);
482                 return OPERATOR_FINISHED;
483         }
484         else if ((first) ||
485                  (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) ||
486                  (event->type == TIMER && (event->customdata == stroke->timer)) )
487         {
488                 if (stroke->stroke_started) {
489                         if (paint_smooth_stroke(stroke, mouse, &sample_average)) {
490                                 if (paint_space_stroke_enabled(stroke->brush)) {
491                                         if (!paint_space_stroke(C, op, event, mouse)) {
492                                                 //ED_region_tag_redraw(ar);
493                                         }
494                                 }
495                                 else {
496                                         paint_brush_stroke_add_step(C, op, event, mouse);
497                                 }
498                         }
499                         else {
500                                 ; //ED_region_tag_redraw(ar);
501                         }
502                 }
503         }
504
505         /* we want the stroke to have the first daub at the start location
506          * instead of waiting till we have moved the space distance */
507         if (first &&
508             stroke->stroke_started &&
509             paint_space_stroke_enabled(stroke->brush) &&
510             !(stroke->brush->flag & BRUSH_ANCHORED) &&
511             !(stroke->brush->flag & BRUSH_SMOOTH_STROKE))
512         {
513                 paint_brush_stroke_add_step(C, op, event, mouse);
514         }
515         
516         return OPERATOR_RUNNING_MODAL;
517 }
518
519 int paint_stroke_exec(bContext *C, wmOperator *op)
520 {
521         PaintStroke *stroke = op->customdata;
522
523         /* only when executed for the first time */
524         if (stroke->stroke_started == 0) {
525                 /* XXX stroke->last_mouse_position is unset, this may cause problems */
526                 stroke->test_start(C, op, NULL);
527                 stroke->stroke_started = 1;
528         }
529
530         RNA_BEGIN (op->ptr, itemptr, "stroke")
531         {
532                 stroke->update_step(C, stroke, &itemptr);
533         }
534         RNA_END;
535
536         stroke_done(C, op);
537
538         return OPERATOR_FINISHED;
539 }
540
541 int paint_stroke_cancel(bContext *C, wmOperator *op)
542 {
543         stroke_done(C, op);
544         return OPERATOR_CANCELLED;
545 }
546
547 ViewContext *paint_stroke_view_context(PaintStroke *stroke)
548 {
549         return &stroke->vc;
550 }
551
552 void *paint_stroke_mode_data(struct PaintStroke *stroke)
553 {
554         return stroke->mode_data;
555 }
556
557 void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
558 {
559         stroke->mode_data = mode_data;
560 }
561
562 int paint_poll(bContext *C)
563 {
564         Paint *p = paint_get_active_from_context(C);
565         Object *ob = CTX_data_active_object(C);
566         ScrArea *sa = CTX_wm_area(C);
567         ARegion *ar = CTX_wm_region(C);
568
569         return p && ob && paint_brush(p) &&
570                (sa && sa->spacetype == SPACE_VIEW3D) &&
571                (ar && ar->regiontype == RGN_TYPE_WINDOW);
572 }