Blender V4.3
paint_curve.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <climits>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "DNA_brush_types.h"
15#include "DNA_object_types.h"
16#include "DNA_screen_types.h"
17#include "DNA_space_types.h"
18#include "DNA_view3d_types.h"
19
20#include "BLI_math_vector.h"
21
22#include "BLT_translation.hh"
23
24#include "BKE_brush.hh"
25#include "BKE_context.hh"
26#include "BKE_lib_id.hh"
27#include "BKE_paint.hh"
28
29#include "ED_paint.hh"
30#include "ED_view3d.hh"
31
32#include "WM_api.hh"
33#include "WM_types.hh"
34
35#include "RNA_access.hh"
36#include "RNA_define.hh"
37
38#include "UI_view2d.hh"
39
40#include "paint_intern.hh"
41
42#define PAINT_CURVE_SELECT_THRESHOLD 40.0f
43#define PAINT_CURVE_POINT_SELECT(pcp, i) (*(&pcp->bez.f1 + i) = SELECT)
44
46{
49 SpaceImage *sima;
50
51 if (rv3d && !(ob && ((ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_SCULPT_CURVES)) != 0))) {
52 return false;
53 }
54
55 sima = CTX_wm_space_image(C);
56
57 if (sima && sima->mode != SI_MODE_PAINT) {
58 return false;
59 }
60
62 Brush *brush = (paint) ? BKE_paint_brush(paint) : nullptr;
63
64 if (brush && (brush->flag & BRUSH_CURVE)) {
65 return true;
66 }
67
68 return false;
69}
70
71#define SEL_F1 (1 << 0)
72#define SEL_F2 (1 << 1)
73#define SEL_F3 (1 << 2)
74
75/* returns 0, 1, or 2 in point according to handle 1, pivot or handle 2 */
77 PaintCurve *pc, const float pos[2], bool ignore_pivot, const float threshold, char *point)
78{
79 PaintCurvePoint *pcp, *closest = nullptr;
80 int i;
81 float closest_dist = threshold;
82
83 for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
84 float dist[3];
85 char point_sel = 0;
86
87 dist[0] = len_manhattan_v2v2(pos, pcp->bez.vec[0]);
88 dist[1] = len_manhattan_v2v2(pos, pcp->bez.vec[1]);
89 dist[2] = len_manhattan_v2v2(pos, pcp->bez.vec[2]);
90
91 if (dist[1] < closest_dist) {
92 closest_dist = dist[1];
93 point_sel = SEL_F2;
94 }
95 if (dist[0] < closest_dist) {
96 closest_dist = dist[0];
97 point_sel = SEL_F1;
98 }
99 if (dist[2] < closest_dist) {
100 closest_dist = dist[2];
101 point_sel = SEL_F3;
102 }
103 if (point_sel) {
104 closest = pcp;
105 if (point) {
106 if (ignore_pivot && point_sel == SEL_F2) {
107 point_sel = (dist[0] < dist[2]) ? SEL_F1 : SEL_F3;
108 }
109 *point = point_sel;
110 }
111 }
112 }
113
114 return closest;
115}
116
117static int paintcurve_point_co_index(char sel)
118{
119 char i = 0;
120 while (sel != 1) {
121 sel >>= 1;
122 i++;
123 }
124 return i;
125}
126
128 const bool is_first,
129 const char fallback)
130{
131 /* when matching, guess based on endpoint side */
132 if (BEZT_ISSEL_ANY(bezt)) {
133 if ((bezt->f1 & SELECT) == (bezt->f3 & SELECT)) {
134 return is_first ? SEL_F1 : SEL_F3;
135 }
136 if (bezt->f1 & SELECT) {
137 return SEL_F1;
138 }
139 if (bezt->f3 & SELECT) {
140 return SEL_F3;
141 }
142 return fallback;
143 }
144 return 0;
145}
146
147/******************* Operators *********************************/
148
149static PaintCurve *paintcurve_for_brush_add(Main *bmain, const char *name, const Brush *brush)
150{
151 PaintCurve *curve = BKE_paint_curve_add(bmain, name);
152 BKE_id_move_to_same_lib(*bmain, curve->id, brush->id);
153 return curve;
154}
155
157{
159 Brush *brush = (paint) ? BKE_paint_brush(paint) : nullptr;
160 Main *bmain = CTX_data_main(C);
161
162 if (brush) {
163 brush->paint_curve = paintcurve_for_brush_add(bmain, DATA_("PaintCurve"), brush);
165 }
166
168
169 return OPERATOR_FINISHED;
170}
171
173{
174 /* identifiers */
175 ot->name = "Add New Paint Curve";
176 ot->description = "Add new paint curve";
177 ot->idname = "PAINTCURVE_OT_new";
178
179 /* api callbacks */
182
183 /* flags */
185}
186
187static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
188{
190 Brush *br = BKE_paint_brush(paint);
191 Main *bmain = CTX_data_main(C);
192 wmWindow *window = CTX_wm_window(C);
193 ARegion *region = CTX_wm_region(C);
194 const float vec[3] = {float(loc[0]), float(loc[1]), 0.0f};
195
196 PaintCurve *pc = br->paint_curve;
197 if (!pc) {
198 br->paint_curve = pc = paintcurve_for_brush_add(bmain, DATA_("PaintCurve"), br);
199 }
200
202
203 PaintCurvePoint *pcp = static_cast<PaintCurvePoint *>(
204 MEM_mallocN((pc->tot_points + 1) * sizeof(PaintCurvePoint), "PaintCurvePoint"));
205 int add_index = pc->add_index;
206
207 if (pc->points) {
208 if (add_index > 0) {
209 memcpy(pcp, pc->points, add_index * sizeof(PaintCurvePoint));
210 }
211 if (add_index < pc->tot_points) {
212 memcpy(pcp + add_index + 1,
213 pc->points + add_index,
214 (pc->tot_points - add_index) * sizeof(PaintCurvePoint));
215 }
216
217 MEM_freeN(pc->points);
218 }
219 pc->points = pcp;
220 pc->tot_points++;
221
222 /* initialize new point */
223 memset(&pcp[add_index], 0, sizeof(PaintCurvePoint));
224 copy_v3_v3(pcp[add_index].bez.vec[0], vec);
225 copy_v3_v3(pcp[add_index].bez.vec[1], vec);
226 copy_v3_v3(pcp[add_index].bez.vec[2], vec);
227
228 /* last step, clear selection from all bezier handles expect the next */
229 for (int i = 0; i < pc->tot_points; i++) {
230 pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0;
231 }
232
234
235 if (pc->add_index != 0) {
236 pcp[add_index].bez.f3 = SELECT;
237 pcp[add_index].bez.h2 = HD_ALIGN;
238 }
239 else {
240 pcp[add_index].bez.f1 = SELECT;
241 pcp[add_index].bez.h1 = HD_ALIGN;
242 }
243
246
247 WM_paint_cursor_tag_redraw(window, region);
248}
249
251{
252 const int loc[2] = {event->mval[0], event->mval[1]};
253 paintcurve_point_add(C, op, loc);
254 RNA_int_set_array(op->ptr, "location", loc);
255 return OPERATOR_FINISHED;
256}
257
259{
260 int loc[2];
261
262 if (RNA_struct_property_is_set(op->ptr, "location")) {
263 RNA_int_get_array(op->ptr, "location", loc);
264 paintcurve_point_add(C, op, loc);
265 return OPERATOR_FINISHED;
266 }
267
268 return OPERATOR_CANCELLED;
269}
270
272{
273 /* identifiers */
274 ot->name = "Add New Paint Curve Point";
275 ot->description = ot->name;
276 ot->idname = "PAINTCURVE_OT_add_point";
277
278 /* api callbacks */
282
283 /* flags */
285
286 /* properties */
288 "location",
289 2,
290 nullptr,
291 0,
292 SHRT_MAX,
293 "Location",
294 "Location of vertex in area space",
295 0,
296 SHRT_MAX);
297}
298
300{
302 Brush *br = BKE_paint_brush(paint);
303 PaintCurve *pc;
304 PaintCurvePoint *pcp;
305 wmWindow *window = CTX_wm_window(C);
306 ARegion *region = CTX_wm_region(C);
307 int i;
308 int tot_del = 0;
309 pc = br->paint_curve;
310
311 if (!pc || pc->tot_points == 0) {
312 return OPERATOR_CANCELLED;
313 }
314
316
317#define DELETE_TAG 2
318
319 for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
320 if (BEZT_ISSEL_ANY(&pcp->bez)) {
321 pcp->bez.f2 |= DELETE_TAG;
322 tot_del++;
323 }
324 }
325
326 if (tot_del > 0) {
327 int j = 0;
328 int new_tot = pc->tot_points - tot_del;
329 PaintCurvePoint *points_new = nullptr;
330 if (new_tot > 0) {
331 points_new = static_cast<PaintCurvePoint *>(
332 MEM_mallocN(new_tot * sizeof(PaintCurvePoint), "PaintCurvePoint"));
333 }
334
335 for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
336 if (!(pcp->bez.f2 & DELETE_TAG)) {
337 points_new[j] = pc->points[i];
338
339 if ((i + 1) == pc->add_index) {
341 }
342 j++;
343 }
344 else if ((i + 1) == pc->add_index) {
345 /* prefer previous point */
346 pc->add_index = j;
347 }
348 }
349 MEM_freeN(pc->points);
350
351 pc->points = points_new;
352 pc->tot_points = new_tot;
353 }
354
355#undef DELETE_TAG
356
359
360 WM_paint_cursor_tag_redraw(window, region);
361
362 return OPERATOR_FINISHED;
363}
364
366{
367 /* identifiers */
368 ot->name = "Remove Paint Curve Point";
369 ot->description = ot->name;
370 ot->idname = "PAINTCURVE_OT_delete_point";
371
372 /* api callbacks */
375
376 /* flags */
378}
379
381 bContext *C, wmOperator *op, const int loc[2], bool toggle, bool extend)
382{
383 wmWindow *window = CTX_wm_window(C);
384 ARegion *region = CTX_wm_region(C);
386 Brush *br = BKE_paint_brush(paint);
387 PaintCurve *pc;
388 int i;
389 const float loc_fl[2] = {float(loc[0]), float(loc[1])};
390
391 pc = br->paint_curve;
392
393 if (!pc) {
394 return false;
395 }
396
398
399 if (toggle) {
400 PaintCurvePoint *pcp;
401 char select = 0;
402 bool selected = false;
403
404 pcp = pc->points;
405
406 for (i = 0; i < pc->tot_points; i++) {
407 if (pcp[i].bez.f1 || pcp[i].bez.f2 || pcp[i].bez.f3) {
408 selected = true;
409 break;
410 }
411 }
412
413 if (!selected) {
414 select = SELECT;
415 }
416
417 for (i = 0; i < pc->tot_points; i++) {
418 pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = select;
419 }
420 }
421 else {
422 PaintCurvePoint *pcp;
423 char selflag;
424
425 pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag);
426
427 if (pcp) {
429
430 if (selflag == SEL_F2) {
431 if (extend) {
432 pcp->bez.f2 ^= SELECT;
433 }
434 else {
435 pcp->bez.f2 |= SELECT;
436 }
437 }
438 else if (selflag == SEL_F1) {
439 if (extend) {
440 pcp->bez.f1 ^= SELECT;
441 }
442 else {
443 pcp->bez.f1 |= SELECT;
444 }
445 }
446 else if (selflag == SEL_F3) {
447 if (extend) {
448 pcp->bez.f3 ^= SELECT;
449 }
450 else {
451 pcp->bez.f3 |= SELECT;
452 }
453 }
454 }
455
456 /* clear selection for unselected points if not extending and if a point has been selected */
457 if (!extend && pcp) {
458 for (i = 0; i < pc->tot_points; i++) {
459 pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = 0;
460
461 if ((pc->points + i) == pcp) {
462 char index = paintcurve_point_co_index(selflag);
463 PAINT_CURVE_POINT_SELECT(pcp, index);
464 }
465 }
466 }
467
468 if (!pcp) {
470 return false;
471 }
472 }
473
475
476 WM_paint_cursor_tag_redraw(window, region);
477
478 return true;
479}
480
482{
483 const int loc[2] = {event->mval[0], event->mval[1]};
484 bool toggle = RNA_boolean_get(op->ptr, "toggle");
485 bool extend = RNA_boolean_get(op->ptr, "extend");
486 if (paintcurve_point_select(C, op, loc, toggle, extend)) {
487 RNA_int_set_array(op->ptr, "location", loc);
488 return OPERATOR_FINISHED;
489 }
490 return OPERATOR_CANCELLED;
491}
492
494{
495 int loc[2];
496
497 if (RNA_struct_property_is_set(op->ptr, "location")) {
498 bool toggle = RNA_boolean_get(op->ptr, "toggle");
499 bool extend = RNA_boolean_get(op->ptr, "extend");
500 RNA_int_get_array(op->ptr, "location", loc);
501 if (paintcurve_point_select(C, op, loc, toggle, extend)) {
502 return OPERATOR_FINISHED;
503 }
504 }
505
506 return OPERATOR_CANCELLED;
507}
508
510{
511 PropertyRNA *prop;
512
513 /* identifiers */
514 ot->name = "Select Paint Curve Point";
515 ot->description = "Select a paint curve point";
516 ot->idname = "PAINTCURVE_OT_select";
517
518 /* api callbacks */
522
523 /* flags */
525
526 /* properties */
528 "location",
529 2,
530 nullptr,
531 0,
532 SHRT_MAX,
533 "Location",
534 "Location of vertex in area space",
535 0,
536 SHRT_MAX);
537 prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "(De)select all");
539 prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
541}
542
551
552static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *event)
553{
555 const float loc_fl[2] = {float(event->mval[0]), float(event->mval[1])};
556 char select;
557 int i;
558 bool do_select = RNA_boolean_get(op->ptr, "select");
559 bool align = RNA_boolean_get(op->ptr, "align");
560 Brush *br = BKE_paint_brush(paint);
561 PaintCurve *pc = br->paint_curve;
562 PaintCurvePoint *pcp;
563
564 if (!pc) {
566 }
567
568 if (do_select) {
570 }
571 else {
572 pcp = nullptr;
573 /* just find first selected point */
574 for (i = 0; i < pc->tot_points; i++) {
575 if ((select = paintcurve_point_side_index(&pc->points[i].bez, i == 0, SEL_F3))) {
576 pcp = &pc->points[i];
577 break;
578 }
579 }
580 }
581
582 if (pcp) {
583 ARegion *region = CTX_wm_region(C);
584 wmWindow *window = CTX_wm_window(C);
585 PointSlideData *psd = static_cast<PointSlideData *>(
586 MEM_mallocN(sizeof(PointSlideData), "PointSlideData"));
587 copy_v2_v2_int(psd->initial_loc, event->mval);
588 psd->event = event->type;
589 psd->pcp = pcp;
591 for (i = 0; i < 3; i++) {
592 copy_v2_v2(psd->point_initial_loc[i], pcp->bez.vec[i]);
593 }
594 psd->align = align;
595 op->customdata = psd;
596
597 /* first, clear all selection from points */
598 for (i = 0; i < pc->tot_points; i++) {
599 pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0;
600 }
601
602 /* only select the active point */
606
608 WM_paint_cursor_tag_redraw(window, region);
610 }
611
613}
614
615static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
616{
617 PointSlideData *psd = static_cast<PointSlideData *>(op->customdata);
618
619 if (event->type == psd->event && event->val == KM_RELEASE) {
620 MEM_freeN(psd);
623 return OPERATOR_FINISHED;
624 }
625
626 switch (event->type) {
627 case MOUSEMOVE: {
628 ARegion *region = CTX_wm_region(C);
629 wmWindow *window = CTX_wm_window(C);
630 float diff[2] = {float(event->mval[0] - psd->initial_loc[0]),
631 float(event->mval[1] - psd->initial_loc[1])};
632 if (psd->select == 1) {
633 int i;
634 for (i = 0; i < 3; i++) {
635 add_v2_v2v2(psd->pcp->bez.vec[i], diff, psd->point_initial_loc[i]);
636 }
637 }
638 else {
640 copy_v2_v2(psd->pcp->bez.vec[psd->select], diff);
641
642 if (psd->align) {
643 char opposite = (psd->select == 0) ? 2 : 0;
644 sub_v2_v2v2(diff, psd->pcp->bez.vec[1], psd->pcp->bez.vec[psd->select]);
645 add_v2_v2v2(psd->pcp->bez.vec[opposite], psd->pcp->bez.vec[1], diff);
646 }
647 }
648 WM_paint_cursor_tag_redraw(window, region);
649 break;
650 }
651 default:
652 break;
653 }
654
656}
657
659{
660 /* identifiers */
661 ot->name = "Slide Paint Curve Point";
662 ot->description = "Select and slide paint curve point";
663 ot->idname = "PAINTCURVE_OT_slide";
664
665 /* api callbacks */
669
670 /* flags */
672
673 /* properties */
675 ot->srna, "align", false, "Align Handles", "Aligns opposite point handle during transform");
677 ot->srna, "select", true, "Select", "Attempt to select a point handle before transform");
678}
679
681{
683 const char *name;
684
685 switch (mode) {
688 name = "PAINT_OT_image_paint";
689 break;
691 name = "PAINT_OT_weight_paint";
692 break;
694 name = "PAINT_OT_vertex_paint";
695 break;
697 name = "SCULPT_OT_brush_stroke";
698 break;
700 name = "SCULPT_CURVES_OT_brush_stroke";
701 break;
703 name = "GREASE_PENCIL_OT_brush_stroke";
704 break;
706 name = "GREASE_PENCIL_OT_sculpt_paint";
707 break;
708 default:
710 }
711
712 return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, nullptr, nullptr);
713}
714
716{
717 /* identifiers */
718 ot->name = "Draw Curve";
719 ot->description = "Draw curve";
720 ot->idname = "PAINTCURVE_OT_draw";
721
722 /* api callbacks */
725
726 /* flags */
728}
729
730static int paintcurve_cursor_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *event)
731{
733
734 switch (mode) {
736 ARegion *region = CTX_wm_region(C);
738 float location[2];
739
740 if (!sima) {
741 return OPERATOR_CANCELLED;
742 }
743
745 &region->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
746 copy_v2_v2(sima->cursor, location);
748 break;
749 }
750 default:
752 break;
753 }
754
755 return OPERATOR_FINISHED;
756}
757
759{
760 /* identifiers */
761 ot->name = "Place Cursor";
762 ot->description = "Place cursor";
763 ot->idname = "PAINTCURVE_OT_cursor";
764
765 /* api callbacks */
768
769 /* flags */
770 ot->flag = 0;
771}
void BKE_brush_tag_unsaved_changes(Brush *brush)
Definition brush.cc:621
SpaceImage * CTX_wm_space_image(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
void BKE_id_move_to_same_lib(Main &bmain, ID &id, const ID &owner_id)
Definition lib_id.cc:862
PaintMode
Definition BKE_paint.hh:99
@ SculptGreasePencil
PaintCurve * BKE_paint_curve_add(Main *bmain, const char *name)
Definition paint.cc:1339
void BKE_paint_curve_clamp_endpoint_add_index(PaintCurve *pc, int add_index)
Definition paint.cc:1359
Paint * BKE_paint_get_active_from_context(const bContext *C)
Definition paint.cc:477
Brush * BKE_paint_brush(Paint *paint)
Definition paint.cc:649
PaintMode BKE_paintmode_get_active_from_context(const bContext *C)
Definition paint.cc:506
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
#define DATA_(msgid)
@ BRUSH_CURVE
#define BEZT_ISSEL_ANY(bezt)
@ HD_ALIGN
#define OB_MODE_ALL_PAINT
@ OB_MODE_SCULPT_CURVES
Object is a sort of wrapper for general info.
@ SI_MODE_PAINT
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_paintcurve_undo_push_begin(const char *name)
void ED_paintcurve_undo_push_end(bContext *C)
void ED_view3d_cursor3d_update(bContext *C, const int mval[2], bool use_depth, enum eV3DCursorOrient orientation)
@ V3D_CURSOR_ORIENT_VIEW
Definition ED_view3d.hh:92
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Definition view2d.cc:1663
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
@ KM_RELEASE
Definition WM_types.hh:285
#define NC_PAINTCURVE
Definition WM_types.hh:363
#define NA_ADDED
Definition WM_types.hh:552
#define ND_SPACE_IMAGE
Definition WM_types.hh:488
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:218
#define NC_SPACE
Definition WM_types.hh:359
bool closest(btVector3 &v)
#define SELECT
draw_view in_light_buf[] float
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool paint_curve_poll(bContext *C)
static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
static PaintCurve * paintcurve_for_brush_add(Main *bmain, const char *name, const Brush *brush)
void PAINTCURVE_OT_new(wmOperatorType *ot)
static int paintcurve_point_co_index(char sel)
static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
#define PAINT_CURVE_POINT_SELECT(pcp, i)
static int paintcurve_add_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void PAINTCURVE_OT_add_point(wmOperatorType *ot)
void PAINTCURVE_OT_delete_point(wmOperatorType *ot)
static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
static int paintcurve_select_point_exec(bContext *C, wmOperator *op)
static int paintcurve_new_exec(bContext *C, wmOperator *)
void PAINTCURVE_OT_draw(wmOperatorType *ot)
#define PAINT_CURVE_SELECT_THRESHOLD
#define SEL_F1
#define SEL_F2
static int paintcurve_draw_exec(bContext *C, wmOperator *)
static char paintcurve_point_side_index(const BezTriple *bezt, const bool is_first, const char fallback)
static int paintcurve_select_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2], bool toggle, bool extend)
static PaintCurvePoint * paintcurve_point_get_closest(PaintCurve *pc, const float pos[2], bool ignore_pivot, const float threshold, char *point)
#define SEL_F3
static int paintcurve_cursor_invoke(bContext *C, wmOperator *, const wmEvent *event)
void PAINTCURVE_OT_cursor(wmOperatorType *ot)
void PAINTCURVE_OT_slide(wmOperatorType *ot)
#define DELETE_TAG
static int paintcurve_add_point_exec(bContext *C, wmOperator *op)
void PAINTCURVE_OT_select(wmOperatorType *ot)
void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_int_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const int *default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
float vec[3][3]
struct PaintCurve * paint_curve
PaintCurvePoint * points
float point_initial_loc[3][2]
PaintCurvePoint * pcp
short val
Definition WM_types.hh:724
int mval[2]
Definition WM_types.hh:728
short type
Definition WM_types.hh:722
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
StructRNA * srna
Definition WM_types.hh:1080
struct wmOperatorType * type
struct PointerRNA * ptr
void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *)
Definition wm_draw.cc:1533
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
int WM_operator_name_call(bContext *C, const char *opstring, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
@ MOUSEMOVE
wmOperatorType * ot
Definition wm_files.cc:4125