Blender  V2.93
editcurve_paint.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include "DNA_object_types.h"
22 #include "DNA_scene_types.h"
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_blenlib.h"
27 #include "BLI_math.h"
28 #include "BLI_mempool.h"
29 
30 #include "BKE_context.h"
31 #include "BKE_curve.h"
32 #include "BKE_fcurve.h"
33 #include "BKE_report.h"
34 
35 #include "DEG_depsgraph.h"
36 
37 #include "WM_api.h"
38 #include "WM_types.h"
39 
40 #include "ED_curve.h"
41 #include "ED_screen.h"
42 #include "ED_space_api.h"
43 #include "ED_view3d.h"
44 
45 #include "GPU_batch.h"
46 #include "GPU_batch_presets.h"
47 #include "GPU_immediate.h"
48 #include "GPU_immediate_util.h"
49 #include "GPU_matrix.h"
50 #include "GPU_state.h"
51 
52 #include "curve_intern.h"
53 
54 #include "UI_resources.h"
55 
56 #include "RNA_access.h"
57 #include "RNA_define.h"
58 
59 #include "RNA_enum_types.h"
60 
61 #define USE_SPLINE_FIT
62 
63 #ifdef USE_SPLINE_FIT
64 # include "curve_fit_nd.h"
65 #endif
66 
67 /* Distance between input samples */
68 #define STROKE_SAMPLE_DIST_MIN_PX 1
69 #define STROKE_SAMPLE_DIST_MAX_PX 3
70 
71 /* Distance between start/end points to consider cyclic */
72 #define STROKE_CYCLIC_DIST_PX 8
73 
74 /* -------------------------------------------------------------------- */
78 struct StrokeElem {
79  float mval[2];
80  float location_world[3];
81  float location_local[3];
82 
83  /* surface normal, may be zero'd */
84  float normal_world[3];
85  float normal_local[3];
86 
87  float pressure;
88 };
89 
90 struct CurveDrawData {
92  short curve_type;
93 
94  /* projecting 2D into 3D space */
95  struct {
96  /* use a plane or project to the surface */
97  bool use_plane;
98  float plane[4];
99 
100  /* use 'rv3d->depths', note that this will become 'damaged' while drawing, but that's OK. */
101  bool use_depth;
102 
103  /* offset projection by this value */
105  float offset[3]; /* worldspace */
109 
110  /* cursor sampling */
111  struct {
112  /* use substeps, needed for nicely interpolating depth */
115 
116  struct {
117  float min, max, range;
119 
120  struct {
121  float mouse[2];
122  /* Used in case we can't calculate the depth. */
123  float location_world[3];
124 
126 
127  const struct StrokeElem *selem;
128  } prev;
129 
131  enum {
134  } state;
135 
136  /* StrokeElem */
138 
140 };
141 
142 static float stroke_elem_radius_from_pressure(const struct CurveDrawData *cdd,
143  const float pressure)
144 {
145  const Curve *cu = cdd->vc.obedit->data;
146  return ((pressure * cdd->radius.range) + cdd->radius.min) * cu->ext2;
147 }
148 
149 static float stroke_elem_radius(const struct CurveDrawData *cdd, const struct StrokeElem *selem)
150 {
151  return stroke_elem_radius_from_pressure(cdd, selem->pressure);
152 }
153 
154 static void stroke_elem_pressure_set(const struct CurveDrawData *cdd,
155  struct StrokeElem *selem,
156  float pressure)
157 {
158  if ((cdd->project.surface_offset != 0.0f) && !cdd->project.use_surface_offset_absolute &&
159  !is_zero_v3(selem->normal_local)) {
160  const float adjust = stroke_elem_radius_from_pressure(cdd, pressure) -
162  madd_v3_v3fl(selem->location_local, selem->normal_local, adjust);
163  mul_v3_m4v3(selem->location_world, cdd->vc.obedit->obmat, selem->location_local);
164  }
165  selem->pressure = pressure;
166 }
167 
168 static void stroke_elem_interp(struct StrokeElem *selem_out,
169  const struct StrokeElem *selem_a,
170  const struct StrokeElem *selem_b,
171  float t)
172 {
173  interp_v2_v2v2(selem_out->mval, selem_a->mval, selem_b->mval, t);
174  interp_v3_v3v3(selem_out->location_world, selem_a->location_world, selem_b->location_world, t);
175  interp_v3_v3v3(selem_out->location_local, selem_a->location_local, selem_b->location_local, t);
176  selem_out->pressure = interpf(selem_a->pressure, selem_b->pressure, t);
177 }
178 
182 static bool stroke_elem_project(const struct CurveDrawData *cdd,
183  const int mval_i[2],
184  const float mval_fl[2],
185  float surface_offset,
186  const float radius,
187  float r_location_world[3],
188  float r_normal_world[3])
189 {
190  ARegion *region = cdd->vc.region;
191  RegionView3D *rv3d = cdd->vc.rv3d;
192 
193  bool is_location_world_set = false;
194 
195  /* project to 'location_world' */
196  if (cdd->project.use_plane) {
197  /* get the view vector to 'location' */
199  region, cdd->project.plane, mval_fl, true, r_location_world)) {
200  if (r_normal_world) {
201  zero_v3(r_normal_world);
202  }
203  is_location_world_set = true;
204  }
205  }
206  else {
207  const ViewDepths *depths = rv3d->depths;
208  if (depths && ((uint)mval_i[0] < depths->w) && ((uint)mval_i[1] < depths->h)) {
209  float depth_fl = 1.0f;
210  ED_view3d_depth_read_cached(depths, mval_i, 0, &depth_fl);
211  const double depth = (double)depth_fl;
212  if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
213  if (ED_view3d_depth_unproject(region, mval_i, depth, r_location_world)) {
214  is_location_world_set = true;
215  if (r_normal_world) {
216  zero_v3(r_normal_world);
217  }
218 
219  if (surface_offset != 0.0f) {
220  const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius;
221  float normal[3];
222  if (ED_view3d_depth_read_cached_normal(&cdd->vc, mval_i, normal)) {
223  madd_v3_v3fl(r_location_world, normal, offset * surface_offset);
224  if (r_normal_world) {
225  copy_v3_v3(r_normal_world, normal);
226  }
227  }
228  }
229  }
230  }
231  }
232  }
233 
234  if (is_location_world_set) {
235  if (cdd->project.use_offset) {
236  add_v3_v3(r_location_world, cdd->project.offset);
237  }
238  }
239 
240  return is_location_world_set;
241 }
242 
243 static bool stroke_elem_project_fallback(const struct CurveDrawData *cdd,
244  const int mval_i[2],
245  const float mval_fl[2],
246  const float surface_offset,
247  const float radius,
248  const float location_fallback_depth[3],
249  float r_location_world[3],
250  float r_location_local[3],
251  float r_normal_world[3],
252  float r_normal_local[3])
253 {
254  bool is_depth_found = stroke_elem_project(
255  cdd, mval_i, mval_fl, surface_offset, radius, r_location_world, r_normal_world);
256  if (is_depth_found == false) {
258  cdd->vc.v3d, cdd->vc.region, location_fallback_depth, mval_fl, r_location_world);
259  zero_v3(r_normal_local);
260  }
261  mul_v3_m4v3(r_location_local, cdd->vc.obedit->imat, r_location_world);
262 
263  if (!is_zero_v3(r_normal_world)) {
264  copy_v3_v3(r_normal_local, r_normal_world);
265  mul_transposed_mat3_m4_v3(cdd->vc.obedit->obmat, r_normal_local);
266  normalize_v3(r_normal_local);
267  }
268  else {
269  zero_v3(r_normal_local);
270  }
271 
272  return is_depth_found;
273 }
274 
278 static bool stroke_elem_project_fallback_elem(const struct CurveDrawData *cdd,
279  const float location_fallback_depth[3],
280  struct StrokeElem *selem)
281 {
282  const int mval_i[2] = {UNPACK2(selem->mval)};
283  const float radius = stroke_elem_radius(cdd, selem);
284  return stroke_elem_project_fallback(cdd,
285  mval_i,
286  selem->mval,
287  cdd->project.surface_offset,
288  radius,
289  location_fallback_depth,
290  selem->location_world,
291  selem->location_local,
292  selem->normal_world,
293  selem->normal_local);
294 }
295 
298 /* -------------------------------------------------------------------- */
302 static void curve_draw_stroke_to_operator_elem(wmOperator *op, const struct StrokeElem *selem)
303 {
304  PointerRNA itemptr;
305  RNA_collection_add(op->ptr, "stroke", &itemptr);
306 
307  RNA_float_set_array(&itemptr, "mouse", selem->mval);
308  RNA_float_set_array(&itemptr, "location", selem->location_world);
309  RNA_float_set(&itemptr, "pressure", selem->pressure);
310 }
311 
313 {
314  struct CurveDrawData *cdd = op->customdata;
315 
316  struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool);
317 
318  RNA_float_get_array(itemptr, "mouse", selem->mval);
319  RNA_float_get_array(itemptr, "location", selem->location_world);
320  mul_v3_m4v3(selem->location_local, cdd->vc.obedit->imat, selem->location_world);
321  selem->pressure = RNA_float_get(itemptr, "pressure");
322 }
323 
325 {
326  struct CurveDrawData *cdd = op->customdata;
327 
328  BLI_mempool_iter iter;
329  const struct StrokeElem *selem;
330 
332  for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
334  }
335 }
336 
338 {
339  RNA_BEGIN (op->ptr, itemptr, "stroke") {
341  }
342  RNA_END;
343 }
344 
347 /* -------------------------------------------------------------------- */
351 static void curve_draw_stroke_3d(const struct bContext *UNUSED(C),
352  ARegion *UNUSED(region),
353  void *arg)
354 {
355  wmOperator *op = arg;
356  struct CurveDrawData *cdd = op->customdata;
357 
358  const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
359 
360  if (stroke_len == 0) {
361  return;
362  }
363 
364  Object *obedit = cdd->vc.obedit;
365  Curve *cu = obedit->data;
366 
367  if (cu->ext2 > 0.0f) {
368  BLI_mempool_iter iter;
369  const struct StrokeElem *selem;
370 
371  const float location_zero[3] = {0};
372  const float *location_prev = location_zero;
373 
374  float color[3];
376 
377  GPUBatch *sphere = GPU_batch_preset_sphere(0);
379  GPU_batch_uniform_3fv(sphere, "color", color);
380 
381  /* scale to edit-mode space */
382  GPU_matrix_push();
383  GPU_matrix_mul(obedit->obmat);
384 
386  for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
387  GPU_matrix_translate_3f(selem->location_local[0] - location_prev[0],
388  selem->location_local[1] - location_prev[1],
389  selem->location_local[2] - location_prev[2]);
390  location_prev = selem->location_local;
391 
392  const float radius = stroke_elem_radius(cdd, selem);
393 
394  GPU_matrix_push();
395  GPU_matrix_scale_1f(radius);
396  GPU_batch_draw(sphere);
397  GPU_matrix_pop();
398 
399  location_prev = selem->location_local;
400  }
401 
402  GPU_matrix_pop();
403  }
404 
405  if (stroke_len > 1) {
406  float(*coord_array)[3] = MEM_mallocN(sizeof(*coord_array) * stroke_len, __func__);
407 
408  {
409  BLI_mempool_iter iter;
410  const struct StrokeElem *selem;
411  int i;
413  for (selem = BLI_mempool_iterstep(&iter), i = 0; selem;
414  selem = BLI_mempool_iterstep(&iter), i++) {
415  copy_v3_v3(coord_array[i], selem->location_world);
416  }
417  }
418 
419  {
423 
426  GPU_line_smooth(true);
427  GPU_line_width(3.0f);
428 
429  imm_cpack(0x0);
430  immBegin(GPU_PRIM_LINE_STRIP, stroke_len);
431  for (int i = 0; i < stroke_len; i++) {
432  immVertex3fv(pos, coord_array[i]);
433  }
434  immEnd();
435 
436  GPU_line_width(1.0f);
437 
438  imm_cpack(0xffffffff);
439  immBegin(GPU_PRIM_LINE_STRIP, stroke_len);
440  for (int i = 0; i < stroke_len; i++) {
441  immVertex3fv(pos, coord_array[i]);
442  }
443  immEnd();
444 
445  /* Reset defaults */
448  GPU_line_smooth(false);
449 
451  }
452 
453  MEM_freeN(coord_array);
454  }
455 }
456 
457 static void curve_draw_event_add(wmOperator *op, const wmEvent *event)
458 {
459  struct CurveDrawData *cdd = op->customdata;
460  Object *obedit = cdd->vc.obedit;
461 
462  invert_m4_m4(obedit->imat, obedit->obmat);
463 
464  struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool);
465 
466  ARRAY_SET_ITEMS(selem->mval, event->mval[0], event->mval[1]);
467 
468  /* handle pressure sensitivity (which is supplied by tablets or otherwise 1.0) */
469  selem->pressure = event->tablet.pressure;
470 
471  bool is_depth_found = stroke_elem_project_fallback_elem(
472  cdd, cdd->prev.location_world_valid, selem);
473 
474  if (is_depth_found) {
475  /* use the depth if a fallback wasn't used */
477  }
479 
480  float len_sq = len_squared_v2v2(cdd->prev.mouse, selem->mval);
481  copy_v2_v2(cdd->prev.mouse, selem->mval);
482 
483  if (cdd->sample.use_substeps && cdd->prev.selem) {
484  const struct StrokeElem selem_target = *selem;
485  struct StrokeElem *selem_new_last = selem;
486  if (len_sq >= square_f(STROKE_SAMPLE_DIST_MAX_PX)) {
487  int n = (int)ceil(sqrt((double)len_sq)) / STROKE_SAMPLE_DIST_MAX_PX;
488 
489  for (int i = 1; i < n; i++) {
490  struct StrokeElem *selem_new = selem_new_last;
491  stroke_elem_interp(selem_new, cdd->prev.selem, &selem_target, (float)i / n);
492 
493  const bool is_depth_found_substep = stroke_elem_project_fallback_elem(
494  cdd, cdd->prev.location_world_valid, selem_new);
495  if (is_depth_found == false) {
496  if (is_depth_found_substep) {
498  }
499  }
500 
501  selem_new_last = BLI_mempool_calloc(cdd->stroke_elem_pool);
502  }
503  }
504  selem = selem_new_last;
505  *selem_new_last = selem_target;
506  }
507 
508  cdd->prev.selem = selem;
509 
511 }
512 
513 static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event)
514 {
515  struct CurveDrawData *cdd = op->customdata;
517 
518  /* add first point */
519  curve_draw_event_add(op, event);
520 
523  RegionView3D *rv3d = cdd->vc.rv3d;
524 
525  cdd->project.use_depth = false;
526  cdd->project.use_plane = true;
527 
528  float normal[3] = {0.0f};
529  if (ELEM(cps->surface_plane,
532  if (ED_view3d_depth_read_cached_normal(&cdd->vc, event->mval, normal)) {
534  float cross_a[3], cross_b[3];
535  cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal);
536  cross_v3_v3v3(cross_b, normal, cross_a);
537  copy_v3_v3(normal, cross_b);
538  }
539  }
540  }
541 
542  /* CURVE_PAINT_SURFACE_PLANE_VIEW or fallback */
543  if (is_zero_v3(normal)) {
544  copy_v3_v3(normal, rv3d->viewinv[2]);
545  }
546 
549 
550  /* Special case for when we only have offset applied on the first-hit,
551  * the remaining stroke must be offset too. */
552  if (cdd->project.surface_offset != 0.0f) {
553  const float mval_fl[2] = {UNPACK2(event->mval)};
554 
555  float location_no_offset[3];
556 
557  if (stroke_elem_project(cdd, event->mval, mval_fl, 0.0f, 0.0f, location_no_offset, NULL)) {
558  sub_v3_v3v3(cdd->project.offset, cdd->prev.location_world_valid, location_no_offset);
559  if (!is_zero_v3(cdd->project.offset)) {
560  cdd->project.use_offset = true;
561  }
562  }
563  }
564  /* end special case */
565  }
566 
567  cdd->init_event_type = event->type;
568  cdd->state = CURVE_DRAW_PAINTING;
569 }
570 
571 static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
572 {
573  BLI_assert(op->customdata == NULL);
574 
575  struct CurveDrawData *cdd = MEM_callocN(sizeof(*cdd), __func__);
577 
578  if (is_invoke) {
580  if (ELEM(NULL, cdd->vc.region, cdd->vc.rv3d, cdd->vc.v3d, cdd->vc.win, cdd->vc.scene)) {
581  MEM_freeN(cdd);
582  BKE_report(op->reports, RPT_ERROR, "Unable to access 3D viewport");
583  return false;
584  }
585  }
586  else {
587  cdd->vc.bmain = CTX_data_main(C);
588  cdd->vc.depsgraph = depsgraph;
589  cdd->vc.scene = CTX_data_scene(C);
592  }
593 
594  op->customdata = cdd;
595 
597 
598  cdd->curve_type = cps->curve_type;
599 
600  cdd->radius.min = cps->radius_min;
601  cdd->radius.max = cps->radius_max;
602  cdd->radius.range = cps->radius_max - cps->radius_min;
606 
608  sizeof(struct StrokeElem), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
609 
610  return true;
611 }
612 
613 static void curve_draw_exit(wmOperator *op)
614 {
615  struct CurveDrawData *cdd = op->customdata;
616  if (cdd) {
617  if (cdd->draw_handle_view) {
620  }
621 
622  if (cdd->stroke_elem_pool) {
624  }
625 
626  MEM_freeN(cdd);
627  op->customdata = NULL;
628  }
629 }
630 
635 {
636  struct CurveDrawData *cdd = op->customdata;
638  PropertyRNA *prop;
639 
640  prop = RNA_struct_find_property(op->ptr, "fit_method");
641  if (!RNA_property_is_set(op->ptr, prop)) {
642  RNA_property_enum_set(op->ptr, prop, cps->fit_method);
643  }
644 
645  prop = RNA_struct_find_property(op->ptr, "corner_angle");
646  if (!RNA_property_is_set(op->ptr, prop)) {
647  const float corner_angle = (cps->flag & CURVE_PAINT_FLAG_CORNERS_DETECT) ? cps->corner_angle :
648  (float)M_PI;
649  RNA_property_float_set(op->ptr, prop, corner_angle);
650  }
651 
652  prop = RNA_struct_find_property(op->ptr, "error_threshold");
653  if (!RNA_property_is_set(op->ptr, prop)) {
654 
655  /* Error isn't set so we'll have to calculate it from the pixel values. */
656  BLI_mempool_iter iter;
657  const struct StrokeElem *selem, *selem_prev;
658 
659  float len_3d = 0.0f, len_2d = 0.0f;
660  float scale_px; /* pixel to local space scale */
661 
662  int i = 0;
664  selem_prev = BLI_mempool_iterstep(&iter);
665  for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) {
666  len_3d += len_v3v3(selem->location_local, selem_prev->location_local);
667  len_2d += len_v2v2(selem->mval, selem_prev->mval);
668  selem_prev = selem;
669  }
670  scale_px = ((len_3d > 0.0f) && (len_2d > 0.0f)) ? (len_3d / len_2d) : 0.0f;
671  float error_threshold = (cps->error_threshold * U.dpi_fac) * scale_px;
672  RNA_property_float_set(op->ptr, prop, error_threshold);
673  }
674 
675  prop = RNA_struct_find_property(op->ptr, "use_cyclic");
676  if (!RNA_property_is_set(op->ptr, prop)) {
677  bool use_cyclic = false;
678 
679  if (BLI_mempool_len(cdd->stroke_elem_pool) > 2) {
680  BLI_mempool_iter iter;
681  const struct StrokeElem *selem, *selem_first, *selem_last;
682 
684  selem_first = selem_last = BLI_mempool_iterstep(&iter);
685  for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
686  selem_last = selem;
687  }
688 
689  if (len_squared_v2v2(selem_first->mval, selem_last->mval) <=
690  square_f(STROKE_CYCLIC_DIST_PX * U.dpi_fac)) {
691  use_cyclic = true;
692  }
693  }
694 
695  RNA_property_boolean_set(op->ptr, prop, use_cyclic);
696  }
697 
698  if ((cps->radius_taper_start != 0.0f) || (cps->radius_taper_end != 0.0f)) {
699  /* note, we could try to de-duplicate the length calculations above */
700  const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
701 
702  BLI_mempool_iter iter;
703  struct StrokeElem *selem, *selem_prev;
704 
705  float *lengths = MEM_mallocN(sizeof(float) * stroke_len, __func__);
706  struct StrokeElem **selem_array = MEM_mallocN(sizeof(*selem_array) * stroke_len, __func__);
707  lengths[0] = 0.0f;
708 
709  float len_3d = 0.0f;
710 
711  int i = 1;
713  selem_prev = BLI_mempool_iterstep(&iter);
714  selem_array[0] = selem_prev;
715  for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) {
716  const float len_3d_segment = len_v3v3(selem->location_local, selem_prev->location_local);
717  len_3d += len_3d_segment;
718  lengths[i] = len_3d;
719  selem_array[i] = selem;
720  selem_prev = selem;
721  }
722 
723  if (cps->radius_taper_start != 0.0f) {
724  const float len_taper_max = cps->radius_taper_start * len_3d;
725  for (i = 0; i < stroke_len && lengths[i] < len_taper_max; i++) {
726  const float pressure_new = selem_array[i]->pressure * (lengths[i] / len_taper_max);
727  stroke_elem_pressure_set(cdd, selem_array[i], pressure_new);
728  }
729  }
730 
731  if (cps->radius_taper_end != 0.0f) {
732  const float len_taper_max = cps->radius_taper_end * len_3d;
733  const float len_taper_min = len_3d - len_taper_max;
734  for (i = stroke_len - 1; i > 0 && lengths[i] > len_taper_min; i--) {
735  const float pressure_new = selem_array[i]->pressure *
736  ((len_3d - lengths[i]) / len_taper_max);
737  stroke_elem_pressure_set(cdd, selem_array[i], pressure_new);
738  }
739  }
740 
741  MEM_freeN(lengths);
742  MEM_freeN(selem_array);
743  }
744 }
745 
747 {
748  if (op->customdata == NULL) {
749  if (!curve_draw_init(C, op, false)) {
750  return OPERATOR_CANCELLED;
751  }
752  }
753 
754  struct CurveDrawData *cdd = op->customdata;
755 
757  Object *obedit = cdd->vc.obedit;
758  Curve *cu = obedit->data;
759  ListBase *nurblist = object_editcurve_get(obedit);
760 
761  int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
762 
763  const bool is_3d = (cu->flag & CU_3D) != 0;
764  invert_m4_m4(obedit->imat, obedit->obmat);
765 
766  if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) {
768  stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
769  }
770 
771  /* Deselect all existing curves. */
773 
774  const float radius_min = cps->radius_min;
775  const float radius_max = cps->radius_max;
776  const float radius_range = cps->radius_max - cps->radius_min;
777 
778  Nurb *nu = MEM_callocN(sizeof(Nurb), __func__);
779  nu->pntsv = 0;
780  nu->resolu = cu->resolu;
781  nu->resolv = cu->resolv;
782  nu->flag |= CU_SMOOTH;
783 
784  const bool use_pressure_radius = (cps->flag & CURVE_PAINT_FLAG_PRESSURE_RADIUS) ||
785  ((cps->radius_taper_start != 0.0f) ||
786  (cps->radius_taper_end != 0.0f));
787 
788  if (cdd->curve_type == CU_BEZIER) {
789  nu->type = CU_BEZIER;
790 
791 #ifdef USE_SPLINE_FIT
792 
793  /* Allow to interpolate multiple channels */
794  int dims = 3;
795  struct {
796  int radius;
797  } coords_indices;
798  coords_indices.radius = use_pressure_radius ? dims++ : -1;
799 
800  float *coords = MEM_mallocN(sizeof(*coords) * stroke_len * dims, __func__);
801 
802  float *cubic_spline = NULL;
803  uint cubic_spline_len = 0;
804 
805  /* error in object local space */
806  const int fit_method = RNA_enum_get(op->ptr, "fit_method");
807  const float error_threshold = RNA_float_get(op->ptr, "error_threshold");
808  const float corner_angle = RNA_float_get(op->ptr, "corner_angle");
809  const bool use_cyclic = RNA_boolean_get(op->ptr, "use_cyclic");
810 
811  {
812  BLI_mempool_iter iter;
813  const struct StrokeElem *selem;
814  float *co = coords;
815 
817  for (selem = BLI_mempool_iterstep(&iter); selem;
818  selem = BLI_mempool_iterstep(&iter), co += dims) {
819  copy_v3_v3(co, selem->location_local);
820  if (coords_indices.radius != -1) {
821  co[coords_indices.radius] = selem->pressure;
822  }
823 
824  /* remove doubles */
825  if ((co != coords) && UNLIKELY(memcmp(co, co - dims, sizeof(float) * dims) == 0)) {
826  co -= dims;
827  stroke_len--;
828  }
829  }
830  }
831 
832  uint *corners = NULL;
833  uint corners_len = 0;
834 
835  if ((fit_method == CURVE_PAINT_FIT_METHOD_SPLIT) && (corner_angle < (float)M_PI)) {
836  /* this could be configurable... */
837  const float corner_radius_min = error_threshold / 8;
838  const float corner_radius_max = error_threshold * 2;
839  const uint samples_max = 16;
840 
841  curve_fit_corners_detect_fl(coords,
842  stroke_len,
843  dims,
844  corner_radius_min,
845  corner_radius_max,
846  samples_max,
847  corner_angle,
848  &corners,
849  &corners_len);
850  }
851 
852  uint *corners_index = NULL;
853  uint corners_index_len = 0;
854  uint calc_flag = CURVE_FIT_CALC_HIGH_QUALIY;
855 
856  if ((stroke_len > 2) && use_cyclic) {
857  calc_flag |= CURVE_FIT_CALC_CYCLIC;
858  }
859 
860  int result;
861  if (fit_method == CURVE_PAINT_FIT_METHOD_REFIT) {
862  result = curve_fit_cubic_to_points_refit_fl(coords,
863  stroke_len,
864  dims,
865  error_threshold,
866  calc_flag,
867  NULL,
868  0,
869  corner_angle,
870  &cubic_spline,
871  &cubic_spline_len,
872  NULL,
873  &corners_index,
874  &corners_index_len);
875  }
876  else {
877  result = curve_fit_cubic_to_points_fl(coords,
878  stroke_len,
879  dims,
880  error_threshold,
881  calc_flag,
882  corners,
883  corners_len,
884  &cubic_spline,
885  &cubic_spline_len,
886  NULL,
887  &corners_index,
888  &corners_index_len);
889  }
890 
891  MEM_freeN(coords);
892  if (corners) {
893  free(corners);
894  }
895 
896  if (result == 0) {
897  nu->pntsu = cubic_spline_len;
898  nu->bezt = MEM_callocN(sizeof(BezTriple) * nu->pntsu, __func__);
899 
900  float *co = cubic_spline;
901  BezTriple *bezt = nu->bezt;
902  for (int j = 0; j < cubic_spline_len; j++, bezt++, co += (dims * 3)) {
903  const float *handle_l = co + (dims * 0);
904  const float *pt = co + (dims * 1);
905  const float *handle_r = co + (dims * 2);
906 
907  copy_v3_v3(bezt->vec[0], handle_l);
908  copy_v3_v3(bezt->vec[1], pt);
909  copy_v3_v3(bezt->vec[2], handle_r);
910 
911  if (coords_indices.radius != -1) {
912  bezt->radius = (pt[coords_indices.radius] * cdd->radius.range) + cdd->radius.min;
913  }
914  else {
915  bezt->radius = radius_max;
916  }
917 
918  bezt->h1 = bezt->h2 = HD_ALIGN; /* will set to free in second pass */
919  bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
920  }
921 
922  if (corners_index) {
923  /* ignore the first and last */
924  uint i_start = 0, i_end = corners_index_len;
925 
926  if ((corners_index_len >= 2) && (calc_flag & CURVE_FIT_CALC_CYCLIC) == 0) {
927  i_start += 1;
928  i_end -= 1;
929  }
930 
931  for (uint i = i_start; i < i_end; i++) {
932  bezt = &nu->bezt[corners_index[i]];
933  bezt->h1 = bezt->h2 = HD_FREE;
934  }
935  }
936 
937  if (calc_flag & CURVE_FIT_CALC_CYCLIC) {
938  nu->flagu |= CU_NURB_CYCLIC;
939  }
940  }
941 
942  if (corners_index) {
943  free(corners_index);
944  }
945 
946  if (cubic_spline) {
947  free(cubic_spline);
948  }
949 
950 #else
951  nu->pntsu = stroke_len;
952  nu->bezt = MEM_callocN(nu->pntsu * sizeof(BezTriple), __func__);
953 
954  BezTriple *bezt = nu->bezt;
955 
956  {
957  BLI_mempool_iter iter;
958  const struct StrokeElem *selem;
959 
961  for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
962  copy_v3_v3(bezt->vec[1], selem->location_local);
963  if (!is_3d) {
964  bezt->vec[1][2] = 0.0f;
965  }
966 
967  if (use_pressure_radius) {
968  bezt->radius = selem->pressure;
969  }
970  else {
971  bezt->radius = radius_max;
972  }
973 
974  bezt->h1 = bezt->h2 = HD_AUTO;
975 
976  bezt->f1 |= SELECT;
977  bezt->f2 |= SELECT;
978  bezt->f3 |= SELECT;
979 
980  bezt++;
981  }
982  }
983 #endif
984 
986  }
987  else { /* CU_POLY */
988  BLI_mempool_iter iter;
989  const struct StrokeElem *selem;
990 
991  nu->pntsu = stroke_len;
992  nu->pntsv = 1;
993  nu->type = CU_POLY;
994  nu->bp = MEM_callocN(nu->pntsu * sizeof(BPoint), __func__);
995 
996  /* Misc settings. */
997  nu->resolu = cu->resolu;
998  nu->resolv = 1;
999  nu->orderu = 4;
1000  nu->orderv = 1;
1001 
1002  BPoint *bp = nu->bp;
1003 
1005  for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
1006  copy_v3_v3(bp->vec, selem->location_local);
1007  if (!is_3d) {
1008  bp->vec[2] = 0.0f;
1009  }
1010 
1011  if (use_pressure_radius) {
1012  bp->radius = (selem->pressure * radius_range) + radius_min;
1013  }
1014  else {
1015  bp->radius = cps->radius_max;
1016  }
1017  bp->f1 = SELECT;
1018  bp->vec[3] = 1.0f;
1019 
1020  bp++;
1021  }
1022 
1024  }
1025 
1026  BLI_addtail(nurblist, nu);
1027 
1028  BKE_curve_nurb_active_set(cu, nu);
1029  cu->actvert = nu->pntsu - 1;
1030 
1032  DEG_id_tag_update(obedit->data, 0);
1033 
1034  curve_draw_exit(op);
1035 
1036  return OPERATOR_FINISHED;
1037 }
1038 
1039 static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1040 {
1041  if (RNA_struct_property_is_set(op->ptr, "stroke")) {
1042  return curve_draw_exec(C, op);
1043  }
1044 
1045  if (!curve_draw_init(C, op, true)) {
1046  return OPERATOR_CANCELLED;
1047  }
1048 
1049  struct CurveDrawData *cdd = op->customdata;
1050 
1052 
1053  const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
1054 
1055  /* Fallback (in case we can't find the depth on first test). */
1056  {
1057  const float mval_fl[2] = {UNPACK2(event->mval)};
1058  float center[3];
1059  negate_v3_v3(center, cdd->vc.rv3d->ofs);
1060  ED_view3d_win_to_3d(cdd->vc.v3d, cdd->vc.region, center, mval_fl, cdd->prev.location_world);
1062  }
1063 
1067 
1068  {
1069  View3D *v3d = cdd->vc.v3d;
1070  RegionView3D *rv3d = cdd->vc.rv3d;
1071  Object *obedit = cdd->vc.obedit;
1072  Curve *cu = obedit->data;
1073 
1074  const float *plane_no = NULL;
1075  const float *plane_co = NULL;
1076 
1077  if (CU_IS_2D(cu)) {
1078  /* 2D overrides other options */
1079  plane_co = obedit->obmat[3];
1080  plane_no = obedit->obmat[2];
1081  cdd->project.use_plane = true;
1082  }
1083  else {
1084  if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && (v3d->shading.type > OB_WIRE)) {
1085  /* needed or else the draw matrix can be incorrect */
1087 
1089  cdd->vc.depsgraph, cdd->vc.region, cdd->vc.v3d, NULL, V3D_DEPTH_NO_GPENCIL, true);
1090 
1091  if (cdd->vc.rv3d->depths != NULL) {
1092  cdd->project.use_depth = true;
1093  }
1094  else {
1095  BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
1096  cdd->project.use_depth = false;
1097  }
1098  }
1099 
1100  /* use view plane (when set or as fallback when surface can't be found) */
1101  if (cdd->project.use_depth == false) {
1102  plane_co = cdd->vc.scene->cursor.location;
1103  plane_no = rv3d->viewinv[2];
1104  cdd->project.use_plane = true;
1105  }
1106 
1107  if (cdd->project.use_depth && (cdd->curve_type != CU_POLY)) {
1108  cdd->sample.use_substeps = true;
1109  }
1110  }
1111 
1112  if (cdd->project.use_plane) {
1113  normalize_v3_v3(cdd->project.plane, plane_no);
1114  cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, plane_co);
1115  }
1116  }
1117 
1118  if (is_modal == false) {
1119  curve_draw_event_add_first(op, event);
1120  }
1121 
1122  /* add temp handler */
1124 
1125  return OPERATOR_RUNNING_MODAL;
1126 }
1127 
1129 {
1130  curve_draw_exit(op);
1131 }
1132 
1133 /* Modal event handling of frame changing */
1134 static int curve_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
1135 {
1137  struct CurveDrawData *cdd = op->customdata;
1138 
1139  UNUSED_VARS(C, op);
1140 
1141  if (event->type == cdd->init_event_type) {
1142  if (event->val == KM_RELEASE) {
1144 
1146 
1148 
1149  curve_draw_exec(C, op);
1150 
1151  return OPERATOR_FINISHED;
1152  }
1153  }
1154  else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
1156  curve_draw_cancel(C, op);
1157  return OPERATOR_CANCELLED;
1158  }
1159  else if (ELEM(event->type, LEFTMOUSE)) {
1160  if (event->val == KM_PRESS) {
1161  curve_draw_event_add_first(op, event);
1162  }
1163  }
1164  else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
1165  if (cdd->state == CURVE_DRAW_PAINTING) {
1166  const float mval_fl[2] = {UNPACK2(event->mval)};
1168  curve_draw_event_add(op, event);
1169  }
1170  }
1171  }
1172 
1173  return ret;
1174 }
1175 
1177 {
1178  /* identifiers */
1179  ot->name = "Draw Curve";
1180  ot->idname = "CURVE_OT_draw";
1181  ot->description = "Draw a freehand spline";
1182 
1183  /* api callbacks */
1184  ot->exec = curve_draw_exec;
1189 
1190  /* flags */
1192 
1193  /* properties */
1194  PropertyRNA *prop;
1195 
1196  prop = RNA_def_float_distance(ot->srna,
1197  "error_threshold",
1198  0.0f,
1199  0.0f,
1200  10.0f,
1201  "Error",
1202  "Error distance threshold (in object units)",
1203  0.0001f,
1204  10.0f);
1205  RNA_def_property_ui_range(prop, 0.0, 10, 1, 4);
1206 
1207  RNA_def_enum(ot->srna,
1208  "fit_method",
1211  "Fit Method",
1212  "");
1213 
1214  prop = RNA_def_float_distance(
1215  ot->srna, "corner_angle", DEG2RADF(70.0f), 0.0f, M_PI, "Corner Angle", "", 0.0f, M_PI);
1217 
1218  prop = RNA_def_boolean(ot->srna, "use_cyclic", true, "Cyclic", "");
1220 
1221  prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
1223 
1224  prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
1226 }
1227 
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
void BKE_nurb_handles_calc(struct Nurb *nu)
Definition: curve.c:4092
#define CU_IS_2D(cu)
Definition: BKE_curve.h:83
void BKE_nurb_knot_calc_u(struct Nurb *nu)
Definition: curve.c:1303
void BKE_curve_nurb_active_set(struct Curve *cu, const struct Nurb *nu)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
#define BLI_assert(a)
Definition: BLI_assert.h:58
sqrt(x)+1/max(0
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:116
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
MINLINE float square_f(float a)
MINLINE float interpf(float a, float b, float t)
#define M_PI
Definition: BLI_math_base.h:38
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:950
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
#define DEG2RADF(_deg)
void interp_v2_v2v2(float r[2], const float a[2], const float b[2], const float t)
Definition: math_vector.c:32
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void * BLI_mempool_calloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_mempool.c:362
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL()
Definition: BLI_mempool.c:537
@ BLI_MEMPOOL_ALLOW_ITER
Definition: BLI_mempool.h:85
void * BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_mempool.c:645
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int totelem, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_mempool.c:268
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:757
int BLI_mempool_len(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:454
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNPACK2(a)
#define UNUSED_VARS(...)
#define ARRAY_SET_ITEMS(...)
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
typedef double(DMatrix)[4][4]
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
@ CU_BEZIER
@ CU_POLY
@ CU_SMOOTH
@ CU_NURB_CYCLIC
@ HD_FREE
@ HD_AUTO
@ HD_ALIGN
@ CU_3D
@ OB_WIRE
Object is a sort of wrapper for general info.
@ CURVE_PAINT_PROJECT_SURFACE
@ CURVE_PAINT_FLAG_DEPTH_STROKE_ENDPOINTS
@ CURVE_PAINT_FLAG_DEPTH_STROKE_OFFSET_ABS
@ CURVE_PAINT_FLAG_CORNERS_DETECT
@ CURVE_PAINT_FLAG_PRESSURE_RADIUS
@ CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE
@ CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW
@ CURVE_PAINT_FIT_METHOD_REFIT
@ CURVE_PAINT_FIT_METHOD_SPLIT
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
bool ED_operator_editcurve(struct bContext *C)
Definition: screen_ops.c:560
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:667
#define REGION_DRAW_POST_VIEW
Definition: ED_space_api.h:66
void * ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *customdata, int type)
Definition: spacetypes.c:238
void ED_region_draw_cb_exit(struct ARegionType *, void *)
Definition: spacetypes.c:253
bool ED_view3d_win_to_3d_on_plane(const struct ARegion *region, const float plane[4], const float mval[2], const bool do_clip, float r_out[3])
bool ED_view3d_depth_read_cached(const ViewDepths *vd, const int mval[2], int margin, float *r_depth)
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc, struct Depsgraph *depsgraph)
bool ED_view3d_depth_read_cached_normal(const ViewContext *vc, const int mval[2], float r_normal[3])
bool ED_view3d_depth_unproject(const struct ARegion *region, const int mval[2], const double depth, float r_location_world[3])
@ V3D_DEPTH_NO_GPENCIL
Definition: ED_view3d.h:148
void ED_view3d_depth_override(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, struct Object *obact, eV3DDepthOverrideMode mode, bool update_cache)
Definition: view3d_draw.c:2331
void ED_view3d_win_to_3d(const struct View3D *v3d, const struct ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
void view3d_operator_needs_opengl(const struct bContext *C)
NSNotificationCenter * center
GPUBatch
Definition: GPU_batch.h:93
void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id)
Definition: gpu_batch.cc:299
void GPU_batch_draw(GPUBatch *batch)
Definition: gpu_batch.cc:234
#define GPU_batch_uniform_3fv(batch, name, val)
Definition: GPU_batch.h:141
struct GPUBatch * GPU_batch_preset_sphere(int lod) ATTR_WARN_UNUSED_RESULT
void immUnbindProgram(void)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
GPUVertFormat * immVertexFormat(void)
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
void imm_cpack(uint x)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:142
#define GPU_matrix_mul(x)
Definition: GPU_matrix.h:223
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:135
void GPU_matrix_scale_1f(float factor)
Definition: gpu_matrix.cc:225
void GPU_matrix_translate_3f(float x, float y, float z)
Definition: gpu_matrix.cc:204
@ GPU_PRIM_LINE_STRIP
Definition: GPU_primitive.h:38
@ GPU_SHADER_3D_UNIFORM_COLOR
Definition: GPU_shader.h:200
@ GPU_BLEND_NONE
Definition: GPU_state.h:55
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:57
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:55
void GPU_line_width(float width)
Definition: gpu_state.cc:173
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:85
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:81
@ GPU_DEPTH_NONE
Definition: GPU_state.h:78
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:75
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
#define RNA_BEGIN(sptr, itemptr, propname)
Definition: RNA_access.h:1248
StructRNA RNA_OperatorStrokeElement
#define RNA_END
Definition: RNA_access.h:1255
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
@ PROP_HIDDEN
Definition: RNA_types.h:202
@ PROP_ANGLE
Definition: RNA_types.h:132
#define C
Definition: RandGen.cpp:39
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1191
@ TH_WIRE
Definition: UI_resources.h:85
#define NC_GEOM
Definition: WM_types.h:294
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define KM_PRESS
Definition: WM_types.h:242
#define KM_RELEASE
Definition: WM_types.h:243
unsigned int U
Definition: btGjkEpa3.h:78
#define SELECT
const Depsgraph * depsgraph
ListBase * object_editcurve_get(Object *ob)
Definition: editcurve.c:89
static bool stroke_elem_project(const struct CurveDrawData *cdd, const int mval_i[2], const float mval_fl[2], float surface_offset, const float radius, float r_location_world[3], float r_normal_world[3])
static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
#define STROKE_CYCLIC_DIST_PX
static void curve_draw_exec_precalc(wmOperator *op)
static void curve_draw_cancel(bContext *UNUSED(C), wmOperator *op)
static int curve_draw_exec(bContext *C, wmOperator *op)
static bool stroke_elem_project_fallback_elem(const struct CurveDrawData *cdd, const float location_fallback_depth[3], struct StrokeElem *selem)
static bool stroke_elem_project_fallback(const struct CurveDrawData *cdd, const int mval_i[2], const float mval_fl[2], const float surface_offset, const float radius, const float location_fallback_depth[3], float r_location_world[3], float r_location_local[3], float r_normal_world[3], float r_normal_local[3])
static float stroke_elem_radius(const struct CurveDrawData *cdd, const struct StrokeElem *selem)
#define STROKE_SAMPLE_DIST_MIN_PX
static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void curve_draw_stroke_to_operator_elem(wmOperator *op, const struct StrokeElem *selem)
static void stroke_elem_pressure_set(const struct CurveDrawData *cdd, struct StrokeElem *selem, float pressure)
static void curve_draw_event_add(wmOperator *op, const wmEvent *event)
void CURVE_OT_draw(wmOperatorType *ot)
static void curve_draw_stroke_from_operator_elem(wmOperator *op, PointerRNA *itemptr)
static void curve_draw_stroke_to_operator(wmOperator *op)
static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
static void stroke_elem_interp(struct StrokeElem *selem_out, const struct StrokeElem *selem_a, const struct StrokeElem *selem_b, float t)
static float stroke_elem_radius_from_pressure(const struct CurveDrawData *cdd, const float pressure)
static int curve_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void curve_draw_stroke_from_operator(wmOperator *op)
#define STROKE_SAMPLE_DIST_MAX_PX
static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event)
static void curve_draw_exit(wmOperator *op)
bool ED_curve_deselect_all_multi(struct bContext *C)
uint pos
IconTextureDrawCall normal
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
return ret
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:6655
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:3562
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
Definition: rna_access.c:6378
void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
Definition: rna_access.c:6610
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
Definition: rna_access.c:2358
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:6366
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
Definition: rna_access.c:2964
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:6685
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
Definition: rna_access.c:6390
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
PropertyRNA * RNA_def_float_distance(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:4041
PropertyRNA * RNA_def_collection_runtime(StructOrFunctionRNA *cont_, const char *identifier, StructRNA *type, const char *ui_name, const char *ui_description)
Definition: rna_define.c:4210
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
Definition: rna_define.c:1563
void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double step, int precision)
Definition: rna_define.c:1706
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
const EnumPropertyItem rna_enum_curve_fit_method_items[]
Definition: rna_scene.c:244
struct ARegionType * type
uint8_t f1
float vec[4]
float radius
float vec[3][3]
struct CurveDrawData::@311 project
const struct StrokeElem * selem
bool use_surface_offset_absolute
struct CurveDrawData::@313 radius
enum CurveDrawData::@315 state
struct CurveDrawData::@312 sample
struct CurveDrawData::@314 prev
float location_world[3]
void * draw_handle_view
float location_world_valid[3]
ViewContext vc
BLI_mempool * stroke_elem_pool
short resolv
short resolu
float ext2
short flagu
short orderu
short orderv
short flag
short type
BezTriple * bezt
BPoint * bp
short resolu
short resolv
float imat[4][4]
float obmat[4][4]
void * data
struct ViewDepths * depths
float viewinv[4][4]
struct ToolSettings * toolsettings
View3DCursor cursor
float normal_world[3]
float normal_local[3]
float mval[2]
float location_local[3]
float location_world[3]
struct CurvePaintSettings curve_paint_settings
View3DShading shading
struct Depsgraph * depsgraph
Definition: ED_view3d.h:75
struct Scene * scene
Definition: ED_view3d.h:76
struct ARegion * region
Definition: ED_view3d.h:80
struct ViewLayer * view_layer
Definition: ED_view3d.h:77
struct Main * bmain
Definition: ED_view3d.h:70
struct Object * obedit
Definition: ED_view3d.h:79
struct wmWindow * win
Definition: ED_view3d.h:82
struct View3D * v3d
Definition: ED_view3d.h:81
struct RegionView3D * rv3d
Definition: ED_view3d.h:83
unsigned short w
Definition: ED_view3d.h:89
double depth_range[2]
Definition: ED_view3d.h:92
unsigned short h
Definition: ED_view3d.h:89
short val
Definition: WM_types.h:579
int mval[2]
Definition: WM_types.h:583
short type
Definition: WM_types.h:577
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct ReportList * reports
struct PointerRNA * ptr
ccl_device_inline float3 ceil(const float3 &a)
void WM_cursor_modal_set(wmWindow *win, int val)
Definition: wm_cursors.c:207
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:216
@ WM_CURSOR_PAINT_BRUSH
Definition: wm_cursors.h:49
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ RIGHTMOUSE
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
@ INBETWEEN_MOUSEMOVE
wmOperatorType * ot
Definition: wm_files.c:3156