Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / curve / editcurve_paint.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  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/editors/curve/editcurve_paint.c
22  *  \ingroup edcurve
23  */
24
25 #include "DNA_object_types.h"
26 #include "DNA_scene_types.h"
27
28 #include "MEM_guardedalloc.h"
29
30 #include "BLI_blenlib.h"
31 #include "BLI_math.h"
32 #include "BLI_mempool.h"
33
34 #include "BKE_context.h"
35 #include "BKE_curve.h"
36 #include "BKE_fcurve.h"
37 #include "BKE_main.h"
38 #include "BKE_report.h"
39
40 #include "DEG_depsgraph.h"
41
42 #include "WM_api.h"
43 #include "WM_types.h"
44
45 #include "ED_space_api.h"
46 #include "ED_screen.h"
47 #include "ED_view3d.h"
48 #include "ED_curve.h"
49
50 #include "BIF_gl.h"
51
52 #include "GPU_batch.h"
53 #include "GPU_immediate.h"
54 #include "GPU_immediate_util.h"
55 #include "GPU_matrix.h"
56
57 #include "curve_intern.h"
58
59 #include "UI_resources.h"
60
61 #include "RNA_access.h"
62 #include "RNA_define.h"
63
64 #include "RNA_enum_types.h"
65
66 #define USE_SPLINE_FIT
67
68 #ifdef USE_SPLINE_FIT
69 #include "curve_fit_nd.h"
70 #endif
71
72 /* Distance between input samples */
73 #define STROKE_SAMPLE_DIST_MIN_PX 1
74 #define STROKE_SAMPLE_DIST_MAX_PX 3
75
76 /* Distance between start/end points to consider cyclic */
77 #define STROKE_CYCLIC_DIST_PX     8
78
79 /* -------------------------------------------------------------------- */
80
81 /** \name StrokeElem / #RNA_OperatorStrokeElement Conversion Functions
82  * \{ */
83
84 struct StrokeElem {
85         float mval[2];
86         float location_world[3];
87         float location_local[3];
88
89         /* surface normal, may be zero'd */
90         float normal_world[3];
91         float normal_local[3];
92
93         float pressure;
94 };
95
96 struct CurveDrawData {
97         Depsgraph *depsgraph;
98
99         short init_event_type;
100         short curve_type;
101
102         /* projecting 2D into 3D space */
103         struct {
104                 /* use a plane or project to the surface */
105                 bool use_plane;
106                 float    plane[4];
107
108                 /* use 'rv3d->depths', note that this will become 'damaged' while drawing, but thats OK. */
109                 bool use_depth;
110
111                 /* offset projection by this value */
112                 bool use_offset;
113                 float    offset[3];  /* worldspace */
114                 float    surface_offset;
115                 bool     use_surface_offset_absolute;
116         } project;
117
118         /* cursor sampling */
119         struct {
120                 /* use substeps, needed for nicely interpolating depth */
121                 bool use_substeps;
122         } sample;
123
124         struct {
125                 float min, max, range;
126         } radius;
127
128         struct {
129                 float mouse[2];
130                 /* used incase we can't calculate the depth */
131                 float location_world[3];
132
133                 float location_world_valid[3];
134
135                 const struct StrokeElem *selem;
136         } prev;
137
138         ViewContext vc;
139         enum {
140                 CURVE_DRAW_IDLE = 0,
141                 CURVE_DRAW_PAINTING = 1,
142         } state;
143
144         /* StrokeElem */
145         BLI_mempool *stroke_elem_pool;
146
147         void *draw_handle_view;
148 };
149
150 static float stroke_elem_radius_from_pressure(const struct CurveDrawData *cdd, const float pressure)
151 {
152         const Curve *cu = cdd->vc.obedit->data;
153         return ((pressure * cdd->radius.range) + cdd->radius.min) * cu->ext2;
154 }
155
156 static float stroke_elem_radius(const struct CurveDrawData *cdd, const struct StrokeElem *selem)
157 {
158         return stroke_elem_radius_from_pressure(cdd, selem->pressure);
159 }
160
161 static void stroke_elem_pressure_set(const struct CurveDrawData *cdd, struct StrokeElem *selem, float pressure)
162 {
163         if ((cdd->project.surface_offset != 0.0f) &&
164             !cdd->project.use_surface_offset_absolute &&
165             !is_zero_v3(selem->normal_local))
166         {
167                 const float adjust = stroke_elem_radius_from_pressure(cdd, pressure) -
168                                      stroke_elem_radius_from_pressure(cdd, selem->pressure);
169                 madd_v3_v3fl(selem->location_local, selem->normal_local, adjust);
170                 mul_v3_m4v3(selem->location_world, cdd->vc.obedit->obmat, selem->location_local);
171         }
172         selem->pressure = pressure;
173 }
174
175 static void stroke_elem_interp(
176         struct StrokeElem *selem_out,
177         const struct StrokeElem *selem_a,  const struct StrokeElem *selem_b, float t)
178 {
179         interp_v2_v2v2(selem_out->mval, selem_a->mval, selem_b->mval, t);
180         interp_v3_v3v3(selem_out->location_world, selem_a->location_world, selem_b->location_world, t);
181         interp_v3_v3v3(selem_out->location_local, selem_a->location_local, selem_b->location_local, t);
182         selem_out->pressure = interpf(selem_a->pressure, selem_b->pressure, t);
183 }
184
185
186 /**
187  * Sets the depth from #StrokeElem.mval
188  */
189 static bool stroke_elem_project(
190         const struct CurveDrawData *cdd,
191         const int mval_i[2], const float mval_fl[2],
192         float surface_offset, const float radius,
193         float r_location_world[3], float r_normal_world[3])
194 {
195         View3D *v3d = cdd->vc.v3d;
196         ARegion *ar = cdd->vc.ar;
197         RegionView3D *rv3d = cdd->vc.rv3d;
198
199         bool is_location_world_set = false;
200
201         /* project to 'location_world' */
202         if (cdd->project.use_plane) {
203                 /* get the view vector to 'location' */
204                 float ray_origin[3], ray_direction[3];
205                 ED_view3d_win_to_ray(cdd->depsgraph, cdd->vc.ar, v3d, mval_fl, ray_origin, ray_direction, false);
206
207                 float lambda;
208                 if (isect_ray_plane_v3(ray_origin, ray_direction, cdd->project.plane, &lambda, true)) {
209                         madd_v3_v3v3fl(r_location_world, ray_origin, ray_direction, lambda);
210                         if (r_normal_world) {
211                                 zero_v3(r_normal_world);
212                         }
213                         is_location_world_set = true;
214                 }
215         }
216         else {
217                 const ViewDepths *depths = rv3d->depths;
218                 if (depths &&
219                     ((unsigned int)mval_i[0] < depths->w) &&
220                     ((unsigned int)mval_i[1] < depths->h))
221                 {
222                         const double depth = (double)ED_view3d_depth_read_cached(&cdd->vc, mval_i);
223                         if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
224                                 if (ED_view3d_depth_unproject(ar, mval_i, depth, r_location_world)) {
225                                         is_location_world_set = true;
226                                         if (r_normal_world) {
227                                                 zero_v3(r_normal_world);
228                                         }
229
230                                         if (surface_offset != 0.0f) {
231                                                 const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius;
232                                                 float normal[3];
233                                                 if (ED_view3d_depth_read_cached_normal(&cdd->vc, mval_i, normal)) {
234                                                         madd_v3_v3fl(r_location_world, normal, offset * surface_offset);
235                                                         if (r_normal_world) {
236                                                                 copy_v3_v3(r_normal_world, normal);
237                                                         }
238                                                 }
239                                         }
240                                 }
241                         }
242                 }
243         }
244
245         if (is_location_world_set) {
246                 if (cdd->project.use_offset) {
247                         add_v3_v3(r_location_world, cdd->project.offset);
248                 }
249         }
250
251         return is_location_world_set;
252 }
253
254 static bool stroke_elem_project_fallback(
255         const struct CurveDrawData *cdd,
256         const int mval_i[2], const float mval_fl[2],
257         const float surface_offset, const float radius,
258         const float location_fallback_depth[3],
259         float r_location_world[3], float r_location_local[3],
260         float r_normal_world[3], float r_normal_local[3])
261 {
262         bool is_depth_found = stroke_elem_project(
263                 cdd, mval_i, mval_fl,
264                 surface_offset, radius,
265                 r_location_world, r_normal_world);
266         if (is_depth_found == false) {
267                 ED_view3d_win_to_3d(cdd->vc.v3d, cdd->vc.ar, location_fallback_depth, mval_fl, r_location_world);
268                 zero_v3(r_normal_local);
269         }
270         mul_v3_m4v3(r_location_local, cdd->vc.obedit->imat, r_location_world);
271
272         if (!is_zero_v3(r_normal_world)) {
273                 copy_v3_v3(r_normal_local, r_normal_world);
274                 mul_transposed_mat3_m4_v3(cdd->vc.obedit->obmat, r_normal_local);
275                 normalize_v3(r_normal_local);
276         }
277         else {
278                 zero_v3(r_normal_local);
279         }
280
281         return is_depth_found;
282 }
283
284 /**
285  * \note #StrokeElem.mval & #StrokeElem.pressure must be set first.
286  */
287 static bool stroke_elem_project_fallback_elem(
288         const struct CurveDrawData *cdd,
289         const float location_fallback_depth[3],
290         struct StrokeElem *selem)
291 {
292         const int mval_i[2] = {UNPACK2(selem->mval)};
293         const float radius = stroke_elem_radius(cdd, selem);
294         return stroke_elem_project_fallback(
295                 cdd, mval_i, selem->mval,
296                 cdd->project.surface_offset, radius,
297                 location_fallback_depth,
298                 selem->location_world, selem->location_local,
299                 selem->normal_world, selem->normal_local);
300 }
301
302 /** \} */
303
304
305 /* -------------------------------------------------------------------- */
306
307 /** \name Operator/Stroke Conversion
308  * \{ */
309
310 static void curve_draw_stroke_to_operator_elem(
311         wmOperator *op, const struct StrokeElem *selem)
312 {
313         PointerRNA itemptr;
314         RNA_collection_add(op->ptr, "stroke", &itemptr);
315
316         RNA_float_set_array(&itemptr, "mouse", selem->mval);
317         RNA_float_set_array(&itemptr, "location", selem->location_world);
318         RNA_float_set(&itemptr, "pressure", selem->pressure);
319 }
320
321 static void curve_draw_stroke_from_operator_elem(
322         wmOperator *op, PointerRNA *itemptr)
323 {
324         struct CurveDrawData *cdd = op->customdata;
325
326         struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool);
327
328         RNA_float_get_array(itemptr, "mouse", selem->mval);
329         RNA_float_get_array(itemptr, "location", selem->location_world);
330         mul_v3_m4v3(selem->location_local, cdd->vc.obedit->imat, selem->location_world);
331         selem->pressure = RNA_float_get(itemptr, "pressure");
332 }
333
334 static void curve_draw_stroke_to_operator(wmOperator *op)
335 {
336         struct CurveDrawData *cdd = op->customdata;
337
338         BLI_mempool_iter iter;
339         const struct StrokeElem *selem;
340
341         BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
342         for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
343                 curve_draw_stroke_to_operator_elem(op, selem);
344         }
345 }
346
347 static void curve_draw_stroke_from_operator(wmOperator *op)
348 {
349         RNA_BEGIN (op->ptr, itemptr, "stroke")
350         {
351                 curve_draw_stroke_from_operator_elem(op, &itemptr);
352         }
353         RNA_END;
354 }
355
356 /** \} */
357
358
359 /* -------------------------------------------------------------------- */
360
361 /** \name Operator Callbacks & Helpers
362  * \{ */
363
364 static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
365 {
366         wmOperator *op = arg;
367         struct CurveDrawData *cdd = op->customdata;
368
369         const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
370
371         if (stroke_len == 0) {
372                 return;
373         }
374
375         View3D *v3d = cdd->vc.v3d;
376         Object *obedit = cdd->vc.obedit;
377         Curve *cu = obedit->data;
378
379         if (cu->ext2 > 0.0f) {
380                 BLI_mempool_iter iter;
381                 const struct StrokeElem *selem;
382
383                 const float  location_zero[3] = {0};
384                 const float *location_prev = location_zero;
385
386                 float color[3];
387                 UI_GetThemeColor3fv(TH_WIRE, color);
388
389                 Gwn_Batch *sphere = GPU_batch_preset_sphere(0);
390                 GWN_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
391                 GWN_batch_uniform_3fv(sphere, "color", color);
392
393                 /* scale to edit-mode space */
394                 gpuPushMatrix();
395                 gpuMultMatrix(obedit->obmat);
396
397                 BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
398                 for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
399                         gpuTranslate3f(
400                                 selem->location_local[0] - location_prev[0],
401                                 selem->location_local[1] - location_prev[1],
402                                 selem->location_local[2] - location_prev[2]);
403                         location_prev = selem->location_local;
404
405                         const float radius = stroke_elem_radius(cdd, selem);
406
407                         gpuPushMatrix();
408                         gpuScaleUniform(radius);
409                         GWN_batch_draw(sphere);
410                         gpuPopMatrix();
411
412                         location_prev = selem->location_local;
413                 }
414
415                 gpuPopMatrix();
416         }
417
418         if (stroke_len > 1) {
419                 float (*coord_array)[3] = MEM_mallocN(sizeof(*coord_array) * stroke_len, __func__);
420
421                 {
422                         BLI_mempool_iter iter;
423                         const struct StrokeElem *selem;
424                         int i;
425                         BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
426                         for (selem = BLI_mempool_iterstep(&iter), i = 0; selem; selem = BLI_mempool_iterstep(&iter), i++) {
427                                 copy_v3_v3(coord_array[i], selem->location_world);
428                         }
429                 }
430
431                 {
432                         Gwn_VertFormat *format = immVertexFormat();
433                         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
434                         immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
435
436                         glEnable(GL_BLEND);
437                         glEnable(GL_LINE_SMOOTH);
438
439                         imm_cpack(0x0);
440                         immBegin(GWN_PRIM_LINE_STRIP, stroke_len);
441                         glLineWidth(3.0f);
442
443                         if (v3d->zbuf) {
444                                 glDisable(GL_DEPTH_TEST);
445                         }
446
447                         for (int i = 0; i < stroke_len; i++) {
448                                 immVertex3fv(pos, coord_array[i]);
449                         }
450
451                         immEnd();
452
453                         imm_cpack(0xffffffff);
454                         immBegin(GWN_PRIM_LINE_STRIP, stroke_len);
455                         glLineWidth(1.0f);
456
457                         for (int i = 0; i < stroke_len; i++) {
458                                 immVertex3fv(pos, coord_array[i]);
459                         }
460
461                         immEnd();
462
463                         if (v3d->zbuf) {
464                                 glEnable(GL_DEPTH_TEST);
465                         }
466
467                         glDisable(GL_BLEND);
468                         glDisable(GL_LINE_SMOOTH);
469
470                         immUnbindProgram();
471                 }
472
473                 MEM_freeN(coord_array);
474         }
475 }
476
477 static void curve_draw_event_add(wmOperator *op, const wmEvent *event)
478 {
479         struct CurveDrawData *cdd = op->customdata;
480         Object *obedit = cdd->vc.obedit;
481
482         invert_m4_m4(obedit->imat, obedit->obmat);
483
484         struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool);
485
486         ARRAY_SET_ITEMS(selem->mval, event->mval[0], event->mval[1]);
487
488         /* handle pressure sensitivity (which is supplied by tablets) */
489         if (event->tablet_data) {
490                 const wmTabletData *wmtab = event->tablet_data;
491                 selem->pressure = wmtab->Pressure;
492         }
493         else {
494                 selem->pressure = 1.0f;
495         }
496
497         bool is_depth_found = stroke_elem_project_fallback_elem(
498                 cdd, cdd->prev.location_world_valid, selem);
499
500         if (is_depth_found) {
501                 /* use the depth if a fallback wasn't used */
502                 copy_v3_v3(cdd->prev.location_world_valid, selem->location_world);
503         }
504         copy_v3_v3(cdd->prev.location_world, selem->location_world);
505
506         float len_sq = len_squared_v2v2(cdd->prev.mouse, selem->mval);
507         copy_v2_v2(cdd->prev.mouse, selem->mval);
508
509         if (cdd->sample.use_substeps && cdd->prev.selem) {
510                 const struct StrokeElem selem_target = *selem;
511                 struct StrokeElem *selem_new_last = selem;
512                 if (len_sq >= SQUARE(STROKE_SAMPLE_DIST_MAX_PX)) {
513                         int n = (int)ceil(sqrt((double)len_sq)) / STROKE_SAMPLE_DIST_MAX_PX ;
514
515                         for (int i = 1; i < n; i++) {
516                                 struct StrokeElem *selem_new = selem_new_last;
517                                 stroke_elem_interp(selem_new, cdd->prev.selem, &selem_target, (float)i / n);
518
519                                 const bool is_depth_found_substep = stroke_elem_project_fallback_elem(
520                                         cdd, cdd->prev.location_world_valid, selem_new);
521                                 if (is_depth_found == false) {
522                                         if (is_depth_found_substep) {
523                                                 copy_v3_v3(cdd->prev.location_world_valid, selem_new->location_world);
524                                         }
525                                 }
526
527                                 selem_new_last = BLI_mempool_calloc(cdd->stroke_elem_pool);
528                         }
529                 }
530                 selem = selem_new_last;
531                 *selem_new_last = selem_target;
532         }
533
534         cdd->prev.selem = selem;
535
536         ED_region_tag_redraw(cdd->vc.ar);
537 }
538
539 static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event)
540 {
541         struct CurveDrawData *cdd = op->customdata;
542         const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
543
544         /* add first point */
545         curve_draw_event_add(op, event);
546
547         if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && cdd->project.use_depth &&
548             (cps->flag & CURVE_PAINT_FLAG_DEPTH_STROKE_ENDPOINTS))
549         {
550                 RegionView3D *rv3d = cdd->vc.rv3d;
551
552                 cdd->project.use_depth = false;
553                 cdd->project.use_plane = true;
554
555                 float normal[3] = {0.0f};
556                 if (ELEM(cps->surface_plane,
557                          CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW,
558                          CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE))
559                 {
560                         if (ED_view3d_depth_read_cached_normal(&cdd->vc, event->mval, normal)) {
561                                 if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) {
562                                         float cross_a[3], cross_b[3];
563                                         cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal);
564                                         cross_v3_v3v3(cross_b, normal, cross_a);
565                                         copy_v3_v3(normal, cross_b);
566                                 }
567                         }
568                 }
569
570                 /* CURVE_PAINT_SURFACE_PLANE_VIEW or fallback */
571                 if (is_zero_v3(normal)) {
572                         copy_v3_v3(normal, rv3d->viewinv[2]);
573                 }
574
575                 normalize_v3_v3(cdd->project.plane, normal);
576                 cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, cdd->prev.location_world_valid);
577
578                 /* Special case for when we only have offset applied on the first-hit,
579                  * the remaining stroke must be offset too. */
580                 if (cdd->project.surface_offset != 0.0f) {
581                         const float mval_fl[2] = {UNPACK2(event->mval)};
582
583                         float location_no_offset[3];
584
585                         if (stroke_elem_project(
586                                 cdd, event->mval, mval_fl, 0.0f, 0.0f,
587                                 location_no_offset, NULL))
588                         {
589                                 sub_v3_v3v3(cdd->project.offset, cdd->prev.location_world_valid, location_no_offset);
590                                 if (!is_zero_v3(cdd->project.offset)) {
591                                         cdd->project.use_offset = true;
592                                 }
593                         }
594                 }
595                 /* end special case */
596
597         }
598
599         cdd->init_event_type = event->type;
600         cdd->state = CURVE_DRAW_PAINTING;
601 }
602
603 static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
604 {
605         BLI_assert(op->customdata == NULL);
606
607         struct CurveDrawData *cdd = MEM_callocN(sizeof(*cdd), __func__);
608
609         cdd->depsgraph = CTX_data_depsgraph(C);
610
611         if (is_invoke) {
612                 ED_view3d_viewcontext_init(C, &cdd->vc);
613                 if (ELEM(NULL, cdd->vc.ar, cdd->vc.rv3d, cdd->vc.v3d, cdd->vc.win, cdd->vc.scene)) {
614                         MEM_freeN(cdd);
615                         BKE_report(op->reports, RPT_ERROR, "Unable to access 3D viewport");
616                         return false;
617                 }
618         }
619         else {
620                 cdd->vc.bmain = CTX_data_main(C);
621                 cdd->vc.depsgraph = CTX_data_depsgraph(C);
622                 cdd->vc.scene = CTX_data_scene(C);
623                 cdd->vc.view_layer = CTX_data_view_layer(C);
624                 cdd->vc.obedit = CTX_data_edit_object(C);
625         }
626
627         op->customdata = cdd;
628
629         const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
630
631         cdd->curve_type = cps->curve_type;
632
633         cdd->radius.min = cps->radius_min;
634         cdd->radius.max = cps->radius_max;
635         cdd->radius.range = cps->radius_max - cps->radius_min;
636         cdd->project.surface_offset = cps->surface_offset;
637         cdd->project.use_surface_offset_absolute = (cps->flag & CURVE_PAINT_FLAG_DEPTH_STROKE_OFFSET_ABS) != 0;
638
639         cdd->stroke_elem_pool = BLI_mempool_create(
640                 sizeof(struct StrokeElem), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
641
642         return true;
643 }
644
645
646 static void curve_draw_exit(wmOperator *op)
647 {
648         struct CurveDrawData *cdd = op->customdata;
649         if (cdd) {
650                 if (cdd->draw_handle_view) {
651                         ED_region_draw_cb_exit(cdd->vc.ar->type, cdd->draw_handle_view);
652                         WM_cursor_modal_restore(cdd->vc.win);
653                 }
654
655                 if (cdd->stroke_elem_pool) {
656                         BLI_mempool_destroy(cdd->stroke_elem_pool);
657                 }
658
659                 MEM_freeN(cdd);
660                 op->customdata = NULL;
661         }
662 }
663
664 /**
665  * Initialize values before calling 'exec' (when running interactively).
666  */
667 static void curve_draw_exec_precalc(wmOperator *op)
668 {
669         struct CurveDrawData *cdd = op->customdata;
670         const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
671         PropertyRNA *prop;
672
673         prop = RNA_struct_find_property(op->ptr, "fit_method");
674         if (!RNA_property_is_set(op->ptr, prop)) {
675                 RNA_property_enum_set(op->ptr, prop, cps->fit_method);
676         }
677
678         prop = RNA_struct_find_property(op->ptr, "corner_angle");
679         if (!RNA_property_is_set(op->ptr, prop)) {
680                 const float corner_angle = (cps->flag & CURVE_PAINT_FLAG_CORNERS_DETECT) ? cps->corner_angle : (float)M_PI;
681                 RNA_property_float_set(op->ptr, prop, corner_angle);
682         }
683
684         prop = RNA_struct_find_property(op->ptr, "error_threshold");
685         if (!RNA_property_is_set(op->ptr, prop)) {
686
687                 /* error isnt set so we'll have to calculate it from the pixel values */
688                 BLI_mempool_iter iter;
689                 const struct StrokeElem *selem, *selem_prev;
690
691                 float len_3d = 0.0f, len_2d = 0.0f;
692                 float scale_px;  /* pixel to local space scale */
693
694                 int i = 0;
695                 BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
696                 selem_prev = BLI_mempool_iterstep(&iter);
697                 for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) {
698                         len_3d += len_v3v3(selem->location_local, selem_prev->location_local);
699                         len_2d += len_v2v2(selem->mval, selem_prev->mval);
700                         selem_prev = selem;
701                 }
702                 scale_px = ((len_3d > 0.0f) && (len_2d > 0.0f)) ?  (len_3d / len_2d) : 0.0f;
703                 float error_threshold = (cps->error_threshold * U.pixelsize) * scale_px;
704                 RNA_property_float_set(op->ptr, prop, error_threshold);
705         }
706
707         prop = RNA_struct_find_property(op->ptr, "use_cyclic");
708         if (!RNA_property_is_set(op->ptr, prop)) {
709                 bool use_cyclic = false;
710
711                 if (BLI_mempool_len(cdd->stroke_elem_pool) > 2) {
712                         BLI_mempool_iter iter;
713                         const struct StrokeElem *selem, *selem_first, *selem_last;
714
715                         BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
716                         selem_first = selem_last = BLI_mempool_iterstep(&iter);
717                         for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
718                                 selem_last = selem;
719                         }
720
721                         if (len_squared_v2v2(
722                                 selem_first->mval,
723                                 selem_last->mval) <= SQUARE(STROKE_CYCLIC_DIST_PX * U.pixelsize))
724                         {
725                                 use_cyclic = true;
726                         }
727                 }
728
729                 RNA_property_boolean_set(op->ptr, prop, use_cyclic);
730         }
731
732
733         if ((cps->radius_taper_start != 0.0f) ||
734             (cps->radius_taper_end   != 0.0f))
735         {
736                 /* note, we could try to de-duplicate the length calculations above */
737                 const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
738
739                 BLI_mempool_iter iter;
740                 struct StrokeElem *selem, *selem_prev;
741
742                 float *lengths = MEM_mallocN(sizeof(float) * stroke_len, __func__);
743                 struct StrokeElem **selem_array = MEM_mallocN(sizeof(*selem_array) * stroke_len, __func__);
744                 lengths[0] = 0.0f;
745
746                 float len_3d = 0.0f;
747
748                 int i = 1;
749                 BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
750                 selem_prev = BLI_mempool_iterstep(&iter);
751                 selem_array[0] = selem_prev;
752                 for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) {
753                         const float len_3d_segment = len_v3v3(selem->location_local, selem_prev->location_local);
754                         len_3d += len_3d_segment;
755                         lengths[i] = len_3d;
756                         selem_array[i] = selem;
757                         selem_prev = selem;
758                 }
759
760                 if (cps->radius_taper_start != 0.0f) {
761                         const float len_taper_max = cps->radius_taper_start * len_3d;
762                         for (i = 0; i < stroke_len && lengths[i] < len_taper_max; i++) {
763                                 const float pressure_new = selem_array[i]->pressure * (lengths[i] / len_taper_max);
764                                 stroke_elem_pressure_set(cdd, selem_array[i], pressure_new);
765                         }
766                 }
767
768                 if (cps->radius_taper_end != 0.0f) {
769                         const float len_taper_max = cps->radius_taper_end * len_3d;
770                         const float len_taper_min = len_3d - len_taper_max;
771                         for (i = stroke_len - 1; i > 0 && lengths[i] > len_taper_min; i--) {
772                                 const float pressure_new = selem_array[i]->pressure * ((len_3d - lengths[i]) / len_taper_max);
773                                 stroke_elem_pressure_set(cdd, selem_array[i], pressure_new);
774                         }
775                 }
776
777                 MEM_freeN(lengths);
778                 MEM_freeN(selem_array);
779         }
780 }
781
782 static int curve_draw_exec(bContext *C, wmOperator *op)
783 {
784         if (op->customdata == NULL) {
785                 if (!curve_draw_init(C, op, false)) {
786                         return OPERATOR_CANCELLED;
787                 }
788         }
789
790         struct CurveDrawData *cdd = op->customdata;
791
792         const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
793         Object *obedit = cdd->vc.obedit;
794         Curve *cu = obedit->data;
795         ListBase *nurblist = object_editcurve_get(obedit);
796
797         int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
798
799         const bool is_3d = (cu->flag & CU_3D) != 0;
800         invert_m4_m4(obedit->imat, obedit->obmat);
801
802         if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) {
803                 curve_draw_stroke_from_operator(op);
804                 stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
805         }
806
807         ED_curve_deselect_all(cu->editnurb);
808
809         const float radius_min = cps->radius_min;
810         const float radius_max = cps->radius_max;
811         const float radius_range = cps->radius_max - cps->radius_min;
812
813         Nurb *nu = MEM_callocN(sizeof(Nurb), __func__);
814         nu->pntsv = 0;
815         nu->resolu = cu->resolu;
816         nu->resolv = cu->resolv;
817         nu->flag |= CU_SMOOTH;
818
819         const bool use_pressure_radius =
820                 (cps->flag & CURVE_PAINT_FLAG_PRESSURE_RADIUS) ||
821                 ((cps->radius_taper_start != 0.0f) ||
822                  (cps->radius_taper_end   != 0.0f));
823
824         if (cdd->curve_type == CU_BEZIER) {
825                 nu->type = CU_BEZIER;
826
827 #ifdef USE_SPLINE_FIT
828
829                 /* Allow to interpolate multiple channels */
830                 int dims = 3;
831                 struct {
832                         int radius;
833                 } coords_indices;
834                 coords_indices.radius = use_pressure_radius ? dims++ : -1;
835
836                 float *coords = MEM_mallocN(sizeof(*coords) * stroke_len * dims, __func__);
837
838                 float       *cubic_spline = NULL;
839                 unsigned int cubic_spline_len = 0;
840
841                 /* error in object local space */
842                 const int fit_method = RNA_enum_get(op->ptr, "fit_method");
843                 const float error_threshold = RNA_float_get(op->ptr, "error_threshold");
844                 const float corner_angle = RNA_float_get(op->ptr, "corner_angle");
845                 const bool use_cyclic = RNA_boolean_get(op->ptr, "use_cyclic");
846
847                 {
848                         BLI_mempool_iter iter;
849                         const struct StrokeElem *selem;
850                         float *co = coords;
851
852                         BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
853                         for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), co += dims) {
854                                 copy_v3_v3(co, selem->location_local);
855                                 if (coords_indices.radius != -1) {
856                                         co[coords_indices.radius] = selem->pressure;
857                                 }
858
859                                 /* remove doubles */
860                                 if ((co != coords) && UNLIKELY(memcmp(co, co - dims, sizeof(float) * dims) == 0)) {
861                                         co -= dims;
862                                         stroke_len--;
863                                 }
864                         }
865                 }
866
867                 unsigned int *corners = NULL;
868                 unsigned int  corners_len = 0;
869
870                 if ((fit_method == CURVE_PAINT_FIT_METHOD_SPLIT) && (corner_angle < (float)M_PI)) {
871                         /* this could be configurable... */
872                         const float corner_radius_min = error_threshold / 8;
873                         const float corner_radius_max = error_threshold * 2;
874                         const unsigned int samples_max = 16;
875
876                         curve_fit_corners_detect_fl(
877                                 coords, stroke_len, dims,
878                                 corner_radius_min, corner_radius_max,
879                                 samples_max, corner_angle,
880                                 &corners, &corners_len);
881                 }
882
883                 unsigned int *corners_index = NULL;
884                 unsigned int  corners_index_len = 0;
885                 unsigned int  calc_flag = CURVE_FIT_CALC_HIGH_QUALIY;
886
887                 if ((stroke_len > 2) && use_cyclic) {
888                         calc_flag |= CURVE_FIT_CALC_CYCLIC;
889                 }
890
891                 int result;
892                 if (fit_method == CURVE_PAINT_FIT_METHOD_REFIT) {
893                         result = curve_fit_cubic_to_points_refit_fl(
894                                 coords, stroke_len, dims, error_threshold, calc_flag,
895                                 NULL, 0, corner_angle,
896                                 &cubic_spline, &cubic_spline_len,
897                                 NULL,
898                                 &corners_index, &corners_index_len);
899                 }
900                 else {
901                         result = curve_fit_cubic_to_points_fl(
902                                 coords, stroke_len, dims, error_threshold, calc_flag,
903                                 corners, corners_len,
904                                 &cubic_spline, &cubic_spline_len,
905                                 NULL,
906                                 &corners_index, &corners_index_len);
907                 }
908
909                 MEM_freeN(coords);
910                 if (corners) {
911                         free(corners);
912                 }
913
914                 if (result == 0) {
915                         nu->pntsu = cubic_spline_len;
916                         nu->bezt = MEM_callocN(sizeof(BezTriple) * nu->pntsu, __func__);
917
918                         float *co = cubic_spline;
919                         BezTriple *bezt = nu->bezt;
920                         for (int j = 0; j < cubic_spline_len; j++, bezt++, co += (dims * 3)) {
921                                 const float *handle_l = co + (dims * 0);
922                                 const float *pt       = co + (dims * 1);
923                                 const float *handle_r = co + (dims * 2);
924
925                                 copy_v3_v3(bezt->vec[0], handle_l);
926                                 copy_v3_v3(bezt->vec[1], pt);
927                                 copy_v3_v3(bezt->vec[2], handle_r);
928
929                                 if (coords_indices.radius != -1) {
930                                         bezt->radius = (pt[coords_indices.radius] * cdd->radius.range) + cdd->radius.min;
931                                 }
932                                 else {
933                                         bezt->radius = radius_max;
934                                 }
935
936                                 bezt->h1 = bezt->h2 = HD_ALIGN;  /* will set to free in second pass */
937                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
938                         }
939
940                         if (corners_index) {
941                                 /* ignore the first and last */
942                                 unsigned int i_start = 0, i_end = corners_index_len;
943
944                                 if ((corners_index_len >= 2) &&
945                                     (calc_flag & CURVE_FIT_CALC_CYCLIC) == 0)
946                                 {
947                                         i_start += 1;
948                                         i_end   -= 1;
949                                 }
950
951                                 for (unsigned int i = i_start; i < i_end; i++) {
952                                         bezt = &nu->bezt[corners_index[i]];
953                                         bezt->h1 = bezt->h2 = HD_FREE;
954                                 }
955                         }
956
957                         if (calc_flag & CURVE_FIT_CALC_CYCLIC) {
958                                 nu->flagu |= CU_NURB_CYCLIC;
959                         }
960                 }
961
962                 if (corners_index) {
963                         free(corners_index);
964                 }
965
966                 if (cubic_spline) {
967                         free(cubic_spline);
968                 }
969
970 #else
971                 nu->pntsu = stroke_len;
972                 nu->bezt = MEM_callocN(nu->pntsu * sizeof(BezTriple), __func__);
973
974                 BezTriple *bezt = nu->bezt;
975
976                 {
977                         BLI_mempool_iter iter;
978                         const struct StrokeElem *selem;
979
980                         BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
981                         for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
982                                 copy_v3_v3(bezt->vec[1], selem->location_local);
983                                 if (!is_3d) {
984                                         bezt->vec[1][2] = 0.0f;
985                                 }
986
987                                 if (use_pressure_radius) {
988                                         bezt->radius = selem->pressure;
989                                 }
990                                 else {
991                                         bezt->radius = radius_max;
992                                 }
993
994                                 bezt->h1 = bezt->h2 = HD_AUTO;
995
996                                 bezt->f1 |= SELECT;
997                                 bezt->f2 |= SELECT;
998                                 bezt->f3 |= SELECT;
999
1000                                 bezt++;
1001                         }
1002                 }
1003 #endif
1004
1005                 BKE_nurb_handles_calc(nu);
1006         }
1007         else {  /* CU_POLY */
1008                 BLI_mempool_iter iter;
1009                 const struct StrokeElem *selem;
1010
1011                 nu->pntsu = stroke_len;
1012                 nu->pntsv = 1;
1013                 nu->type = CU_POLY;
1014                 nu->bp = MEM_callocN(nu->pntsu * sizeof(BPoint), __func__);
1015
1016                 /* Misc settings. */
1017                 nu->resolu = cu->resolu;
1018                 nu->resolv = 1;
1019                 nu->orderu = 4;
1020                 nu->orderv = 1;
1021
1022                 BPoint *bp = nu->bp;
1023
1024                 BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
1025                 for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
1026                         copy_v3_v3(bp->vec, selem->location_local);
1027                         if (!is_3d) {
1028                                 bp->vec[2] = 0.0f;
1029                         }
1030
1031                         if (use_pressure_radius) {
1032                                 bp->radius = (selem->pressure * radius_range) + radius_min;
1033                         }
1034                         else {
1035                                 bp->radius = cps->radius_max;
1036                         }
1037                         bp->f1 = SELECT;
1038                         bp->vec[3] = 1.0f;
1039
1040                         bp++;
1041                 }
1042
1043                 BKE_nurb_knot_calc_u(nu);
1044         }
1045
1046         BLI_addtail(nurblist, nu);
1047
1048         BKE_curve_nurb_active_set(cu, nu);
1049         cu->actvert = nu->pntsu - 1;
1050
1051         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1052         DEG_id_tag_update(obedit->data, 0);
1053
1054         curve_draw_exit(op);
1055
1056         return OPERATOR_FINISHED;
1057 }
1058
1059 static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1060 {
1061         if (RNA_struct_property_is_set(op->ptr, "stroke")) {
1062                 return curve_draw_exec(C, op);
1063         }
1064
1065         if (!curve_draw_init(C, op, true)) {
1066                 return OPERATOR_CANCELLED;
1067         }
1068
1069         struct CurveDrawData *cdd = op->customdata;
1070
1071         const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings;
1072
1073         const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
1074
1075         /* fallback (incase we can't find the depth on first test) */
1076         {
1077                 const float mval_fl[2] = {UNPACK2(event->mval)};
1078                 float center[3];
1079                 negate_v3_v3(center, cdd->vc.rv3d->ofs);
1080                 ED_view3d_win_to_3d(cdd->vc.v3d, cdd->vc.ar, center, mval_fl, cdd->prev.location_world);
1081                 copy_v3_v3(cdd->prev.location_world_valid, cdd->prev.location_world);
1082         }
1083
1084         cdd->draw_handle_view = ED_region_draw_cb_activate(
1085                 cdd->vc.ar->type, curve_draw_stroke_3d, op, REGION_DRAW_POST_VIEW);
1086         WM_cursor_modal_set(cdd->vc.win, BC_PAINTBRUSHCURSOR);
1087
1088         {
1089                 View3D *v3d = cdd->vc.v3d;
1090                 RegionView3D *rv3d = cdd->vc.rv3d;
1091                 Object *obedit = cdd->vc.obedit;
1092                 Curve *cu = obedit->data;
1093
1094                 const float *plane_no = NULL;
1095                 const float *plane_co = NULL;
1096
1097                 if ((cu->flag & CU_3D) == 0) {
1098                         /* 2D overrides other options */
1099                         plane_co = obedit->obmat[3];
1100                         plane_no = obedit->obmat[2];
1101                         cdd->project.use_plane = true;
1102                 }
1103                 else {
1104                         if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) &&
1105                             (v3d->drawtype > OB_WIRE))
1106                         {
1107                                 /* needed or else the draw matrix can be incorrect */
1108                                 view3d_operator_needs_opengl(C);
1109
1110                                 ED_view3d_autodist_init(cdd->vc.depsgraph, cdd->vc.ar, cdd->vc.v3d, 0);
1111
1112                                 if (cdd->vc.rv3d->depths) {
1113                                         cdd->vc.rv3d->depths->damaged = true;
1114                                 }
1115
1116                                 ED_view3d_depth_update(cdd->vc.ar);
1117
1118                                 if (cdd->vc.rv3d->depths != NULL) {
1119                                         cdd->project.use_depth = true;
1120                                 }
1121                                 else {
1122                                         BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
1123                                         cdd->project.use_depth = false;
1124                                 }
1125                         }
1126
1127                         /* use view plane (when set or as fallback when surface can't be found) */
1128                         if (cdd->project.use_depth == false) {
1129                                 plane_co = ED_view3d_cursor3d_get(cdd->vc.scene, v3d)->location;
1130                                 plane_no = rv3d->viewinv[2];
1131                                 cdd->project.use_plane = true;
1132                         }
1133
1134                         if (cdd->project.use_depth && (cdd->curve_type != CU_POLY)) {
1135                                 cdd->sample.use_substeps = true;
1136                         }
1137                 }
1138
1139                 if (cdd->project.use_plane) {
1140                         normalize_v3_v3(cdd->project.plane, plane_no);
1141                         cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, plane_co);
1142                 }
1143         }
1144
1145         if (is_modal == false) {
1146                 curve_draw_event_add_first(op, event);
1147         }
1148
1149         /* add temp handler */
1150         WM_event_add_modal_handler(C, op);
1151
1152         return OPERATOR_RUNNING_MODAL;
1153 }
1154
1155 static void curve_draw_cancel(bContext *UNUSED(C), wmOperator *op)
1156 {
1157         curve_draw_exit(op);
1158 }
1159
1160
1161 /* Modal event handling of frame changing */
1162 static int curve_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
1163 {
1164         int ret = OPERATOR_RUNNING_MODAL;
1165         struct CurveDrawData *cdd = op->customdata;
1166
1167         UNUSED_VARS(C, op);
1168
1169         if (event->type == cdd->init_event_type) {
1170                 if (event->val == KM_RELEASE) {
1171                         ED_region_tag_redraw(cdd->vc.ar);
1172
1173                         curve_draw_exec_precalc(op);
1174
1175                         curve_draw_stroke_to_operator(op);
1176
1177                         curve_draw_exec(C, op);
1178
1179                         return OPERATOR_FINISHED;
1180                 }
1181         }
1182         else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
1183                 ED_region_tag_redraw(cdd->vc.ar);
1184                 curve_draw_cancel(C, op);
1185                 return OPERATOR_CANCELLED;
1186         }
1187         else if (ELEM(event->type, LEFTMOUSE)) {
1188                 if (event->val == KM_PRESS) {
1189                         curve_draw_event_add_first(op, event);
1190                 }
1191         }
1192         else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
1193                 if (cdd->state == CURVE_DRAW_PAINTING) {
1194                         const float mval_fl[2] = {UNPACK2(event->mval)};
1195                         if (len_squared_v2v2(mval_fl, cdd->prev.mouse) > SQUARE(STROKE_SAMPLE_DIST_MIN_PX)) {
1196                                 curve_draw_event_add(op, event);
1197                         }
1198                 }
1199         }
1200
1201         return ret;
1202 }
1203
1204 void CURVE_OT_draw(wmOperatorType *ot)
1205 {
1206         /* identifiers */
1207         ot->name = "Draw Curve";
1208         ot->idname = "CURVE_OT_draw";
1209         ot->description = "Draw a freehand spline";
1210
1211         /* api callbacks */
1212         ot->exec = curve_draw_exec;
1213         ot->invoke = curve_draw_invoke;
1214         ot->cancel = curve_draw_cancel;
1215         ot->modal = curve_draw_modal;
1216         ot->poll = ED_operator_editcurve;
1217
1218         /* flags */
1219         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1220
1221         /* properties */
1222         PropertyRNA *prop;
1223
1224         prop = RNA_def_float_distance(
1225                 ot->srna, "error_threshold", 0.0f, 0.0f, 10.0f, "Error",
1226                 "Error distance threshold (in object units)",
1227                 0.0001f, 10.0f);
1228         RNA_def_property_ui_range(prop, 0.0, 10, 1, 4);
1229
1230         RNA_def_enum(ot->srna, "fit_method", rna_enum_curve_fit_method_items, CURVE_PAINT_FIT_METHOD_REFIT,
1231                      "Fit Method", "");
1232
1233         prop = RNA_def_float_distance(
1234                 ot->srna, "corner_angle", DEG2RADF(70.0f), 0.0f, M_PI, "Corner Angle", "", 0.0f, M_PI);
1235         RNA_def_property_subtype(prop, PROP_ANGLE);
1236
1237         prop = RNA_def_boolean(ot->srna, "use_cyclic", true, "Cyclic", "");
1238         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1239
1240         prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
1241         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
1242
1243         prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
1244         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
1245 }
1246
1247 /** \} */