Blender V5.0
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
8
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#include "BKE_paint_types.hh"
29
30#include "ED_paint.hh"
31#include "ED_view3d.hh"
32
33#include "WM_api.hh"
34#include "WM_types.hh"
35
36#include "RNA_access.hh"
37#include "RNA_define.hh"
38
39#include "UI_view2d.hh"
40
41#include "paint_intern.hh"
42
43#define PAINT_CURVE_SELECT_THRESHOLD 40.0f
44#define PAINT_CURVE_POINT_SELECT(pcp, i) (*(&pcp->bez.f1 + i) = SELECT)
45
47{
50 SpaceImage *sima;
51
52 if (rv3d && !(ob && ((ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_SCULPT_CURVES)) != 0))) {
53 return false;
54 }
55
56 sima = CTX_wm_space_image(C);
57
58 if (sima && sima->mode != SI_MODE_PAINT) {
59 return false;
60 }
61
63 Brush *brush = (paint) ? BKE_paint_brush(paint) : nullptr;
64
65 if (brush && (brush->flag & BRUSH_CURVE)) {
66 return true;
67 }
68
69 return false;
70}
71
72#define SEL_F1 (1 << 0)
73#define SEL_F2 (1 << 1)
74#define SEL_F3 (1 << 2)
75
76/* returns 0, 1, or 2 in point according to handle 1, pivot or handle 2 */
78 PaintCurve *pc, const float pos[2], bool ignore_pivot, const float threshold, char *point)
79{
80 PaintCurvePoint *pcp, *closest = nullptr;
81 int i;
82 float closest_dist = threshold;
83
84 for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
85 float dist[3];
86 char point_sel = 0;
87
88 dist[0] = len_manhattan_v2v2(pos, pcp->bez.vec[0]);
89 dist[1] = len_manhattan_v2v2(pos, pcp->bez.vec[1]);
90 dist[2] = len_manhattan_v2v2(pos, pcp->bez.vec[2]);
91
92 if (dist[1] < closest_dist) {
93 closest_dist = dist[1];
94 point_sel = SEL_F2;
95 }
96 if (dist[0] < closest_dist) {
97 closest_dist = dist[0];
98 point_sel = SEL_F1;
99 }
100 if (dist[2] < closest_dist) {
101 closest_dist = dist[2];
102 point_sel = SEL_F3;
103 }
104 if (point_sel) {
105 closest = pcp;
106 if (point) {
107 if (ignore_pivot && point_sel == SEL_F2) {
108 point_sel = (dist[0] < dist[2]) ? SEL_F1 : SEL_F3;
109 }
110 *point = point_sel;
111 }
112 }
113 }
114
115 return closest;
116}
117
118static int paintcurve_point_co_index(char sel)
119{
120 char i = 0;
121 while (sel != 1) {
122 sel >>= 1;
123 i++;
124 }
125 return i;
126}
127
129 const bool is_first,
130 const char fallback)
131{
132 /* when matching, guess based on endpoint side */
133 if (BEZT_ISSEL_ANY(bezt)) {
134 if ((bezt->f1 & SELECT) == (bezt->f3 & SELECT)) {
135 return is_first ? SEL_F1 : SEL_F3;
136 }
137 if (bezt->f1 & SELECT) {
138 return SEL_F1;
139 }
140 if (bezt->f3 & SELECT) {
141 return SEL_F3;
142 }
143 return fallback;
144 }
145 return 0;
146}
147
148/******************* Operators *********************************/
149
150static PaintCurve *paintcurve_for_brush_add(Main *bmain, const char *name, const Brush *brush)
151{
152 PaintCurve *curve = BKE_paint_curve_add(bmain, name);
153 BKE_id_move_to_same_lib(*bmain, curve->id, brush->id);
154 return curve;
155}
156
158{
160 Brush *brush = (paint) ? BKE_paint_brush(paint) : nullptr;
161 Main *bmain = CTX_data_main(C);
162
163 if (brush) {
164 brush->paint_curve = paintcurve_for_brush_add(bmain, DATA_("PaintCurve"), brush);
166 }
167
169
170 return OPERATOR_FINISHED;
171}
172
174{
175 /* identifiers */
176 ot->name = "Add New Paint Curve";
177 ot->description = "Add new paint curve";
178 ot->idname = "PAINTCURVE_OT_new";
179
180 /* API callbacks. */
181 ot->exec = paintcurve_new_exec;
182 ot->poll = paint_curve_poll;
183
184 /* flags */
186}
187
188static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
189{
191 Brush *br = BKE_paint_brush(paint);
192 Main *bmain = CTX_data_main(C);
193 wmWindow *window = CTX_wm_window(C);
194 ARegion *region = CTX_wm_region(C);
195 const float vec[3] = {float(loc[0]), float(loc[1]), 0.0f};
196
197 PaintCurve *pc = br->paint_curve;
198 if (!pc) {
199 br->paint_curve = pc = paintcurve_for_brush_add(bmain, DATA_("PaintCurve"), br);
200 }
201
203
205 "PaintCurvePoint");
206 int add_index = pc->add_index;
207
208 if (pc->points) {
209 if (add_index > 0) {
210 memcpy(pcp, pc->points, add_index * sizeof(PaintCurvePoint));
211 }
212 if (add_index < pc->tot_points) {
213 memcpy(pcp + add_index + 1,
214 pc->points + add_index,
215 (pc->tot_points - add_index) * sizeof(PaintCurvePoint));
216 }
217
218 MEM_freeN(pc->points);
219 }
220 pc->points = pcp;
221 pc->tot_points++;
222
223 /* initialize new point */
224 pcp[add_index] = PaintCurvePoint{};
225 copy_v3_v3(pcp[add_index].bez.vec[0], vec);
226 copy_v3_v3(pcp[add_index].bez.vec[1], vec);
227 copy_v3_v3(pcp[add_index].bez.vec[2], vec);
228
229 /* last step, clear selection from all bezier handles expect the next */
230 for (int i = 0; i < pc->tot_points; i++) {
231 pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0;
232 }
233
235
236 if (pc->add_index != 0) {
237 pcp[add_index].bez.f3 = SELECT;
238 pcp[add_index].bez.h2 = HD_ALIGN;
239 }
240 else {
241 pcp[add_index].bez.f1 = SELECT;
242 pcp[add_index].bez.h1 = HD_ALIGN;
243 }
244
247
248 WM_paint_cursor_tag_redraw(window, region);
249}
250
252 wmOperator *op,
253 const wmEvent *event)
254{
255 const int loc[2] = {event->mval[0], event->mval[1]};
256 paintcurve_point_add(C, op, loc);
257 RNA_int_set_array(op->ptr, "location", loc);
258 return OPERATOR_FINISHED;
259}
260
262{
263 int loc[2];
264
265 if (RNA_struct_property_is_set(op->ptr, "location")) {
266 RNA_int_get_array(op->ptr, "location", loc);
267 paintcurve_point_add(C, op, loc);
268 return OPERATOR_FINISHED;
269 }
270
271 return OPERATOR_CANCELLED;
272}
273
275{
276 /* identifiers */
277 ot->name = "Add New Paint Curve Point";
278 ot->description = ot->name;
279 ot->idname = "PAINTCURVE_OT_add_point";
280
281 /* API callbacks. */
284 ot->poll = paint_curve_poll;
285
286 /* flags */
288
289 /* properties */
291 "location",
292 2,
293 nullptr,
294 0,
295 SHRT_MAX,
296 "Location",
297 "Location of vertex in area space",
298 0,
299 SHRT_MAX);
300}
301
303{
305 Brush *br = BKE_paint_brush(paint);
306 PaintCurve *pc;
307 PaintCurvePoint *pcp;
308 wmWindow *window = CTX_wm_window(C);
309 ARegion *region = CTX_wm_region(C);
310 int i;
311 int tot_del = 0;
312 pc = br->paint_curve;
313
314 if (!pc || pc->tot_points == 0) {
315 return OPERATOR_CANCELLED;
316 }
317
319
320#define DELETE_TAG 2
321
322 for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
323 if (BEZT_ISSEL_ANY(&pcp->bez)) {
324 pcp->bez.f2 |= DELETE_TAG;
325 tot_del++;
326 }
327 }
328
329 if (tot_del > 0) {
330 int j = 0;
331 int new_tot = pc->tot_points - tot_del;
332 PaintCurvePoint *points_new = nullptr;
333 if (new_tot > 0) {
334 points_new = MEM_malloc_arrayN<PaintCurvePoint>(new_tot, "PaintCurvePoint");
335 }
336
337 for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
338 if (!(pcp->bez.f2 & DELETE_TAG)) {
339 points_new[j] = pc->points[i];
340
341 if ((i + 1) == pc->add_index) {
343 }
344 j++;
345 }
346 else if ((i + 1) == pc->add_index) {
347 /* prefer previous point */
348 pc->add_index = j;
349 }
350 }
351 MEM_freeN(pc->points);
352
353 pc->points = points_new;
354 pc->tot_points = new_tot;
355 }
356
357#undef DELETE_TAG
358
361
362 WM_paint_cursor_tag_redraw(window, region);
363
364 return OPERATOR_FINISHED;
365}
366
368{
369 /* identifiers */
370 ot->name = "Remove Paint Curve Point";
371 ot->description = ot->name;
372 ot->idname = "PAINTCURVE_OT_delete_point";
373
374 /* API callbacks. */
376 ot->poll = paint_curve_poll;
377
378 /* flags */
379 ot->flag = OPTYPE_UNDO;
380}
381
383 bContext *C, wmOperator *op, const int loc[2], bool toggle, bool extend)
384{
385 wmWindow *window = CTX_wm_window(C);
386 ARegion *region = CTX_wm_region(C);
388 Brush *br = BKE_paint_brush(paint);
389 PaintCurve *pc;
390 int i;
391 const float loc_fl[2] = {float(loc[0]), float(loc[1])};
392
393 pc = br->paint_curve;
394
395 if (!pc) {
396 return false;
397 }
398
400
401 if (toggle) {
402 PaintCurvePoint *pcp;
403 char select = 0;
404 bool selected = false;
405
406 pcp = pc->points;
407
408 for (i = 0; i < pc->tot_points; i++) {
409 if (pcp[i].bez.f1 || pcp[i].bez.f2 || pcp[i].bez.f3) {
410 selected = true;
411 break;
412 }
413 }
414
415 if (!selected) {
416 select = SELECT;
417 }
418
419 for (i = 0; i < pc->tot_points; i++) {
420 pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = select;
421 }
422 }
423 else {
424 PaintCurvePoint *pcp;
425 char selflag;
426
427 pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag);
428
429 if (pcp) {
431
432 if (selflag == SEL_F2) {
433 if (extend) {
434 pcp->bez.f2 ^= SELECT;
435 }
436 else {
437 pcp->bez.f2 |= SELECT;
438 }
439 }
440 else if (selflag == SEL_F1) {
441 if (extend) {
442 pcp->bez.f1 ^= SELECT;
443 }
444 else {
445 pcp->bez.f1 |= SELECT;
446 }
447 }
448 else if (selflag == SEL_F3) {
449 if (extend) {
450 pcp->bez.f3 ^= SELECT;
451 }
452 else {
453 pcp->bez.f3 |= SELECT;
454 }
455 }
456 }
457
458 /* clear selection for unselected points if not extending and if a point has been selected */
459 if (!extend && pcp) {
460 for (i = 0; i < pc->tot_points; i++) {
461 pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = 0;
462
463 if ((pc->points + i) == pcp) {
464 char index = paintcurve_point_co_index(selflag);
465 PAINT_CURVE_POINT_SELECT(pcp, index);
466 }
467 }
468 }
469
470 if (!pcp) {
472 return false;
473 }
474 }
475
477
478 WM_paint_cursor_tag_redraw(window, region);
479
480 return true;
481}
482
484 wmOperator *op,
485 const wmEvent *event)
486{
487 const int loc[2] = {event->mval[0], event->mval[1]};
488 bool toggle = RNA_boolean_get(op->ptr, "toggle");
489 bool extend = RNA_boolean_get(op->ptr, "extend");
490 if (paintcurve_point_select(C, op, loc, toggle, extend)) {
491 RNA_int_set_array(op->ptr, "location", loc);
492 return OPERATOR_FINISHED;
493 }
494 return OPERATOR_CANCELLED;
495}
496
498{
499 int loc[2];
500
501 if (RNA_struct_property_is_set(op->ptr, "location")) {
502 bool toggle = RNA_boolean_get(op->ptr, "toggle");
503 bool extend = RNA_boolean_get(op->ptr, "extend");
504 RNA_int_get_array(op->ptr, "location", loc);
505 if (paintcurve_point_select(C, op, loc, toggle, extend)) {
506 return OPERATOR_FINISHED;
507 }
508 }
509
510 return OPERATOR_CANCELLED;
511}
512
514{
515 PropertyRNA *prop;
516
517 /* identifiers */
518 ot->name = "Select Paint Curve Point";
519 ot->description = "Select a paint curve point";
520 ot->idname = "PAINTCURVE_OT_select";
521
522 /* API callbacks. */
525 ot->poll = paint_curve_poll;
526
527 /* flags */
529
530 /* properties */
532 "location",
533 2,
534 nullptr,
535 0,
536 SHRT_MAX,
537 "Location",
538 "Location of vertex in area space",
539 0,
540 SHRT_MAX);
541 prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "(De)select all");
543 prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
545}
546
555
557{
559 const float loc_fl[2] = {float(event->mval[0]), float(event->mval[1])};
560 char select;
561 int i;
562 bool do_select = RNA_boolean_get(op->ptr, "select");
563 bool align = RNA_boolean_get(op->ptr, "align");
564 Brush *br = BKE_paint_brush(paint);
565 PaintCurve *pc = br->paint_curve;
566 PaintCurvePoint *pcp;
567
568 if (!pc) {
570 }
571
572 if (do_select) {
574 }
575 else {
576 pcp = nullptr;
577 /* just find first selected point */
578 for (i = 0; i < pc->tot_points; i++) {
579 if ((select = paintcurve_point_side_index(&pc->points[i].bez, i == 0, SEL_F3))) {
580 pcp = &pc->points[i];
581 break;
582 }
583 }
584 }
585
586 if (pcp) {
587 ARegion *region = CTX_wm_region(C);
588 wmWindow *window = CTX_wm_window(C);
589 PointSlideData *psd = MEM_mallocN<PointSlideData>("PointSlideData");
590 copy_v2_v2_int(psd->initial_loc, event->mval);
591 psd->event = event->type;
592 psd->pcp = pcp;
594 for (i = 0; i < 3; i++) {
595 copy_v2_v2(psd->point_initial_loc[i], pcp->bez.vec[i]);
596 }
597 psd->align = align;
598 op->customdata = psd;
599
600 /* first, clear all selection from points */
601 for (i = 0; i < pc->tot_points; i++) {
602 pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0;
603 }
604
605 /* only select the active point */
609
611 WM_paint_cursor_tag_redraw(window, region);
613 }
614
616}
617
619{
620 PointSlideData *psd = static_cast<PointSlideData *>(op->customdata);
621
622 if (event->type == psd->event && event->val == KM_RELEASE) {
623 MEM_freeN(psd);
626 return OPERATOR_FINISHED;
627 }
628
629 switch (event->type) {
630 case MOUSEMOVE: {
631 ARegion *region = CTX_wm_region(C);
632 wmWindow *window = CTX_wm_window(C);
633 float diff[2] = {float(event->mval[0] - psd->initial_loc[0]),
634 float(event->mval[1] - psd->initial_loc[1])};
635 if (psd->select == 1) {
636 int i;
637 for (i = 0; i < 3; i++) {
638 add_v2_v2v2(psd->pcp->bez.vec[i], diff, psd->point_initial_loc[i]);
639 }
640 }
641 else {
643 copy_v2_v2(psd->pcp->bez.vec[psd->select], diff);
644
645 if (psd->align) {
646 char opposite = (psd->select == 0) ? 2 : 0;
647 sub_v2_v2v2(diff, psd->pcp->bez.vec[1], psd->pcp->bez.vec[psd->select]);
648 add_v2_v2v2(psd->pcp->bez.vec[opposite], psd->pcp->bez.vec[1], diff);
649 }
650 }
651 WM_paint_cursor_tag_redraw(window, region);
652 break;
653 }
654 default:
655 break;
656 }
657
659}
660
662{
663 /* identifiers */
664 ot->name = "Slide Paint Curve Point";
665 ot->description = "Select and slide paint curve point";
666 ot->idname = "PAINTCURVE_OT_slide";
667
668 /* API callbacks. */
669 ot->invoke = paintcurve_slide_invoke;
670 ot->modal = paintcurve_slide_modal;
671 ot->poll = paint_curve_poll;
672
673 /* flags */
674 ot->flag = OPTYPE_UNDO;
675
676 /* properties */
678 ot->srna, "align", false, "Align Handles", "Aligns opposite point handle during transform");
680 ot->srna, "select", true, "Select", "Attempt to select a point handle before transform");
681}
682
684{
686 const char *name;
687
688 switch (mode) {
691 name = "PAINT_OT_image_paint";
692 break;
694 name = "PAINT_OT_weight_paint";
695 break;
697 name = "PAINT_OT_vertex_paint";
698 break;
700 name = "SCULPT_OT_brush_stroke";
701 break;
703 name = "SCULPT_CURVES_OT_brush_stroke";
704 break;
706 name = "GREASE_PENCIL_OT_brush_stroke";
707 break;
708 default:
710 }
711
714}
715
717{
718 /* identifiers */
719 ot->name = "Draw Curve";
720 ot->description = "Draw curve";
721 ot->idname = "PAINTCURVE_OT_draw";
722
723 /* API callbacks. */
724 ot->exec = paintcurve_draw_exec;
725 ot->poll = paint_curve_poll;
726
727 /* flags */
728 ot->flag = OPTYPE_UNDO;
729}
730
732 wmOperator * /*op*/,
733 const wmEvent *event)
734{
736
737 switch (mode) {
739 ARegion *region = CTX_wm_region(C);
741 float location[2];
742
743 if (!sima) {
744 return OPERATOR_CANCELLED;
745 }
746
748 &region->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
749 copy_v2_v2(sima->cursor, location);
751 break;
752 }
753 default:
755 break;
756 }
757
758 return OPERATOR_FINISHED;
759}
760
762{
763 /* identifiers */
764 ot->name = "Place Cursor";
765 ot->description = "Place cursor";
766 ot->idname = "PAINTCURVE_OT_cursor";
767
768 /* API callbacks. */
770 ot->poll = paint_curve_poll;
771
772 /* flags */
773 ot->flag = 0;
774}
void BKE_brush_tag_unsaved_changes(Brush *brush)
Definition brush.cc:764
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:879
PaintCurve * BKE_paint_curve_add(Main *bmain, const char *name)
Definition paint.cc:1369
void BKE_paint_curve_clamp_endpoint_add_index(PaintCurve *pc, int add_index)
Definition paint.cc:1389
Paint * BKE_paint_get_active_from_context(const bContext *C)
Definition paint.cc:476
Brush * BKE_paint_brush(Paint *paint)
Definition paint.cc:645
PaintMode BKE_paintmode_get_active_from_context(const bContext *C)
Definition paint.cc:505
PaintMode
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
@ HD_ALIGN
#define BEZT_ISSEL_ANY(bezt)
#define OB_MODE_ALL_PAINT
@ OB_MODE_SCULPT_CURVES
Object is a sort of wrapper for general info.
@ SI_MODE_PAINT
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ 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:96
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
#define C
Definition RandGen.cpp:29
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:1668
@ KM_RELEASE
Definition WM_types.hh:312
#define NC_PAINTCURVE
Definition WM_types.hh:396
#define NA_ADDED
Definition WM_types.hh:586
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define ND_SPACE_IMAGE
Definition WM_types.hh:522
#define NC_SPACE
Definition WM_types.hh:392
bool closest(btVector3 &v)
nullptr float
#define SEL_F1
Definition curve.cc:4011
#define SEL_F2
Definition curve.cc:4012
#define SEL_F3
Definition curve.cc:4013
#define SELECT
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
uint pos
#define select(A, B, C)
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static wmOperatorStatus paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus paintcurve_cursor_invoke(bContext *C, wmOperator *, const wmEvent *event)
bool paint_curve_poll(bContext *C)
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])
static wmOperatorStatus paintcurve_add_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#define PAINT_CURVE_POINT_SELECT(pcp, i)
static wmOperatorStatus paintcurve_select_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void PAINTCURVE_OT_add_point(wmOperatorType *ot)
void PAINTCURVE_OT_delete_point(wmOperatorType *ot)
static wmOperatorStatus paintcurve_new_exec(bContext *C, wmOperator *)
static wmOperatorStatus paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void PAINTCURVE_OT_draw(wmOperatorType *ot)
#define PAINT_CURVE_SELECT_THRESHOLD
static wmOperatorStatus paintcurve_add_point_exec(bContext *C, wmOperator *op)
static char paintcurve_point_side_index(const BezTriple *bezt, const bool is_first, const char fallback)
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)
void PAINTCURVE_OT_cursor(wmOperatorType *ot)
void PAINTCURVE_OT_slide(wmOperatorType *ot)
static wmOperatorStatus paintcurve_draw_exec(bContext *C, wmOperator *)
#define DELETE_TAG
static wmOperatorStatus paintcurve_select_point_exec(bContext *C, wmOperator *op)
static wmOperatorStatus paintcurve_delete_point_exec(bContext *C, wmOperator *op)
void PAINTCURVE_OT_select(wmOperatorType *ot)
const char * name
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
float cursor[2]
wmEventType type
Definition WM_types.hh:757
short val
Definition WM_types.hh:759
int mval[2]
Definition WM_types.hh:763
const char * name
Definition WM_types.hh:1033
struct wmOperatorType * type
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *)
Definition wm_draw.cc:1606
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorStatus WM_operator_name_call(bContext *C, const char *opstring, blender::wm::OpCallContext context, PointerRNA *properties, const wmEvent *event)
@ MOUSEMOVE
wmOperatorType * ot
Definition wm_files.cc:4237