Blender V4.3
paint_cursor.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 by Nicholas Bishop. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11#include "BLI_math_rotation.h"
12#include "BLI_rect.h"
13#include "BLI_task.h"
14#include "BLI_utildefines.h"
15
16#include "DNA_brush_types.h"
17#include "DNA_material_types.h"
18#include "DNA_mesh_types.h"
19#include "DNA_object_types.h"
20#include "DNA_scene_types.h"
21#include "DNA_screen_types.h"
22#include "DNA_space_types.h"
23#include "DNA_userdef_types.h"
24#include "DNA_view3d_types.h"
25
26#include "BKE_brush.hh"
27#include "BKE_colortools.hh"
28#include "BKE_context.hh"
29#include "BKE_curve.hh"
30#include "BKE_grease_pencil.hh"
31#include "BKE_image.hh"
32#include "BKE_node_runtime.hh"
33#include "BKE_object.hh"
34#include "BKE_paint.hh"
35
36#include "NOD_texture.h"
37
38#include "WM_api.hh"
39#include "wm_cursors.hh"
40
42#include "IMB_imbuf_types.hh"
43
44#include "ED_grease_pencil.hh"
45#include "ED_image.hh"
46#include "ED_view3d.hh"
47
48#include "GPU_immediate.hh"
49#include "GPU_immediate_util.hh"
50#include "GPU_matrix.hh"
51#include "GPU_state.hh"
52#include "GPU_texture.hh"
53
54#include "UI_resources.hh"
55
56#include "paint_intern.hh"
57#include "sculpt_boundary.hh"
58#include "sculpt_cloth.hh"
59#include "sculpt_expand.hh"
60/* still needed for sculpt_stroke_get_location, should be
61 * removed eventually (TODO) */
62#include "sculpt_intern.hh"
63#include "sculpt_pose.hh"
64
65#include "bmesh.hh"
66
67/* Needed for determining tool material/vcolor pinning. */
69
70/* TODOs:
71 *
72 * Some of the cursor drawing code is doing non-draw stuff
73 * (e.g. updating the brush rake angle). This should be cleaned up
74 * still.
75 *
76 * There is also some ugliness with sculpt-specific code.
77 */
78
80 GPUTexture *overlay_texture;
81 int winx;
82 int winy;
84 float old_zoom;
85 bool old_col;
86};
87
89 GPUTexture *overlay_texture;
90 int size;
91 int zoom;
93};
94
95static TexSnapshot primary_snap = {nullptr};
96static TexSnapshot secondary_snap = {nullptr};
97static CursorSnapshot cursor_snap = {nullptr};
98
100{
101 if (primary_snap.overlay_texture) {
102 GPU_texture_free(primary_snap.overlay_texture);
103 }
104 if (secondary_snap.overlay_texture) {
105 GPU_texture_free(secondary_snap.overlay_texture);
106 }
107 if (cursor_snap.overlay_texture) {
108 GPU_texture_free(cursor_snap.overlay_texture);
109 }
110
111 memset(&primary_snap, 0, sizeof(TexSnapshot));
112 memset(&secondary_snap, 0, sizeof(TexSnapshot));
113 memset(&cursor_snap, 0, sizeof(CursorSnapshot));
114
116}
117
119
120static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool col, float zoom)
121{
122 return (/* make brush smaller shouldn't cause a resample */
123 //(mtex->brush_map_mode != MTEX_MAP_MODE_VIEW ||
124 //(BKE_brush_size_get(vc->scene, brush) <= snap->BKE_brush_size_get)) &&
125
127 (vc->region->winx == snap->winx && vc->region->winy == snap->winy)) &&
128 (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL || snap->old_zoom == zoom) &&
129 snap->old_col == col);
130}
131
132static void make_tex_snap(TexSnapshot *snap, ViewContext *vc, float zoom)
133{
134 snap->old_zoom = zoom;
135 snap->winx = vc->region->winx;
136 snap->winy = vc->region->winy;
137}
138
152
153static void load_tex_task_cb_ex(void *__restrict userdata,
154 const int j,
155 const TaskParallelTLS *__restrict tls)
156{
157 LoadTexData *data = static_cast<LoadTexData *>(userdata);
158 Brush *br = data->br;
159 ViewContext *vc = data->vc;
160
161 MTex *mtex = data->mtex;
162 uchar *buffer = data->buffer;
163 const bool col = data->col;
164
165 ImagePool *pool = data->pool;
166 const int size = data->size;
167 const float rotation = data->rotation;
168 const float radius = data->radius;
169
170 bool convert_to_linear = false;
171 ColorSpace *colorspace = nullptr;
172
173 const int thread_id = BLI_task_parallel_thread_id(tls);
174
175 if (mtex->tex && mtex->tex->type == TEX_IMAGE && mtex->tex->ima) {
176 ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(mtex->tex->ima, &mtex->tex->iuser, pool);
177 /* For consistency, sampling always returns color in linear space. */
178 if (tex_ibuf && tex_ibuf->float_buffer.data == nullptr) {
179 convert_to_linear = true;
180 colorspace = tex_ibuf->byte_buffer.colorspace;
181 }
182 BKE_image_pool_release_ibuf(mtex->tex->ima, tex_ibuf, pool);
183 }
184
185 for (int i = 0; i < size; i++) {
186 /* Largely duplicated from tex_strength. */
187
188 int index = j * size + i;
189
190 float x = float(i) / size;
191 float y = float(j) / size;
192 float len;
193
194 if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
195 x *= vc->region->winx / radius;
196 y *= vc->region->winy / radius;
197 }
198 else {
199 x = (x - 0.5f) * 2.0f;
200 y = (y - 0.5f) * 2.0f;
201 }
202
203 len = sqrtf(x * x + y * y);
204
206 /* It is probably worth optimizing for those cases where the texture is not rotated by
207 * skipping the calls to atan2, sqrtf, sin, and cos. */
208 if (mtex->tex && (rotation > 0.001f || rotation < -0.001f)) {
209 const float angle = atan2f(y, x) + rotation;
210
211 x = len * cosf(angle);
212 y = len * sinf(angle);
213 }
214
215 float avg;
216 float rgba[4];
217 paint_get_tex_pixel(mtex, x, y, pool, thread_id, &avg, rgba);
218
219 if (col) {
220 if (convert_to_linear) {
222 }
223
224 linearrgb_to_srgb_v3_v3(rgba, rgba);
225
226 clamp_v4(rgba, 0.0f, 1.0f);
227
228 buffer[index * 4] = rgba[0] * 255;
229 buffer[index * 4 + 1] = rgba[1] * 255;
230 buffer[index * 4 + 2] = rgba[2] * 255;
231 buffer[index * 4 + 3] = rgba[3] * 255;
232 }
233 else {
234 avg += br->texture_sample_bias;
235
236 /* Clamp to avoid precision overflow. */
237 CLAMP(avg, 0.0f, 1.0f);
238 buffer[index] = 255 - uchar(255 * avg);
239 }
240 }
241 else {
242 if (col) {
243 buffer[index * 4] = 0;
244 buffer[index * 4 + 1] = 0;
245 buffer[index * 4 + 2] = 0;
246 buffer[index * 4 + 3] = 0;
247 }
248 else {
249 buffer[index] = 0;
250 }
251 }
252 }
253}
254
255static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool primary)
256{
257 bool init;
258 TexSnapshot *target;
259
260 MTex *mtex = (primary) ? &br->mtex : &br->mask_mtex;
262 uchar *buffer = nullptr;
263
264 int size;
265 bool refresh;
269 target = (primary) ? &primary_snap : &secondary_snap;
270
271 refresh = !target->overlay_texture || (invalid != 0) ||
272 !same_tex_snap(target, mtex, vc, col, zoom);
273
274 init = (target->overlay_texture != nullptr);
275
276 if (refresh) {
277 ImagePool *pool = nullptr;
278 /* Stencil is rotated later. */
279 const float rotation = (mtex->brush_map_mode != MTEX_MAP_MODE_STENCIL) ? -mtex->rot : 0.0f;
280 const float radius = BKE_brush_size_get(vc->scene, br) * zoom;
281
282 make_tex_snap(target, vc, zoom);
283
284 if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
285 int s = BKE_brush_size_get(vc->scene, br);
286 int r = 1;
287
288 for (s >>= 1; s > 0; s >>= 1) {
289 r++;
290 }
291
292 size = (1 << r);
293
294 if (size < 256) {
295 size = 256;
296 }
297
298 if (size < target->old_size) {
299 size = target->old_size;
300 }
301 }
302 else {
303 size = 512;
304 }
305
306 if (target->old_size != size || target->old_col != col) {
307 if (target->overlay_texture) {
309 target->overlay_texture = nullptr;
310 }
311 init = false;
312
313 target->old_size = size;
314 target->old_col = col;
315 }
316 if (col) {
317 buffer = static_cast<uchar *>(MEM_mallocN(sizeof(uchar) * size * size * 4, "load_tex"));
318 }
319 else {
320 buffer = static_cast<uchar *>(MEM_mallocN(sizeof(uchar) * size * size, "load_tex"));
321 }
322
323 pool = BKE_image_pool_new();
324
325 if (mtex->tex && mtex->tex->nodetree) {
326 /* Has internal flag to detect it only does it once. */
328 }
329
331 data.br = br;
332 data.vc = vc;
333 data.mtex = mtex;
334 data.buffer = buffer;
335 data.col = col;
336 data.pool = pool;
337 data.size = size;
338 data.rotation = rotation;
339 data.radius = radius;
340
341 TaskParallelSettings settings;
344
345 if (mtex->tex && mtex->tex->nodetree) {
346 ntreeTexEndExecTree(mtex->tex->nodetree->runtime->execdata);
347 }
348
349 if (pool) {
351 }
352
353 if (!target->overlay_texture) {
357 "paint_cursor_overlay", size, size, 1, format, usage, nullptr);
359
360 if (!col) {
362 }
363 }
364
365 if (init) {
367 }
368
369 if (buffer) {
370 MEM_freeN(buffer);
371 }
372 }
373 else {
374 size = target->old_size;
375 }
376
378
379 return 1;
380}
381
382static void load_tex_cursor_task_cb(void *__restrict userdata,
383 const int j,
384 const TaskParallelTLS *__restrict /*tls*/)
385{
386 LoadTexData *data = static_cast<LoadTexData *>(userdata);
387 Brush *br = data->br;
388
389 uchar *buffer = data->buffer;
390
391 const int size = data->size;
392
393 for (int i = 0; i < size; i++) {
394 /* Largely duplicated from tex_strength. */
395
396 const int index = j * size + i;
397 const float x = ((float(i) / size) - 0.5f) * 2.0f;
398 const float y = ((float(j) / size) - 0.5f) * 2.0f;
399 const float len = sqrtf(x * x + y * y);
400
401 if (len <= 1.0f) {
402
403 /* Falloff curve. */
404 float avg = BKE_brush_curve_strength_clamped(br, len, 1.0f);
405
406 buffer[index] = uchar(255 * avg);
407 }
408 else {
409 buffer[index] = 0;
410 }
411 }
412}
413
414static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
415{
416 bool init;
417
419 uchar *buffer = nullptr;
420
421 int size;
422 const bool refresh = !cursor_snap.overlay_texture ||
424 cursor_snap.curve_preset != br->curve_preset;
425
426 init = (cursor_snap.overlay_texture != nullptr);
427
428 if (refresh) {
429 int s, r;
430
431 cursor_snap.zoom = zoom;
432
433 s = BKE_brush_size_get(vc->scene, br);
434 r = 1;
435
436 for (s >>= 1; s > 0; s >>= 1) {
437 r++;
438 }
439
440 size = (1 << r);
441
442 if (size < 256) {
443 size = 256;
444 }
445
446 if (size < cursor_snap.size) {
447 size = cursor_snap.size;
448 }
449
450 if (cursor_snap.size != size) {
451 if (cursor_snap.overlay_texture) {
452 GPU_texture_free(cursor_snap.overlay_texture);
453 cursor_snap.overlay_texture = nullptr;
454 }
455
456 init = false;
457
458 cursor_snap.size = size;
459 }
460 buffer = static_cast<uchar *>(MEM_mallocN(sizeof(uchar) * size * size, "load_tex"));
461
463
465 data.br = br;
466 data.buffer = buffer;
467 data.size = size;
468
469 TaskParallelSettings settings;
472
473 if (!cursor_snap.overlay_texture) {
475 cursor_snap.overlay_texture = GPU_texture_create_2d(
476 "cursor_snap_overaly", size, size, 1, GPU_R8, usage, nullptr);
477 GPU_texture_update(cursor_snap.overlay_texture, GPU_DATA_UBYTE, buffer);
478
479 GPU_texture_swizzle_set(cursor_snap.overlay_texture, "rrrr");
480 }
481
482 if (init) {
483 GPU_texture_update(cursor_snap.overlay_texture, GPU_DATA_UBYTE, buffer);
484 }
485
486 if (buffer) {
487 MEM_freeN(buffer);
488 }
489 }
490 else {
491 size = cursor_snap.size;
492 }
493
494 cursor_snap.curve_preset = br->curve_preset;
496
497 return 1;
498}
499
500static int project_brush_radius(ViewContext *vc, float radius, const float location[3])
501{
502 float view[3], nonortho[3], ortho[3], offset[3], p1[2], p2[2];
503
504 ED_view3d_global_to_vector(vc->rv3d, location, view);
505
506 /* Create a vector that is not orthogonal to view. */
507
508 if (fabsf(view[0]) < 0.1f) {
509 nonortho[0] = view[0] + 1.0f;
510 nonortho[1] = view[1];
511 nonortho[2] = view[2];
512 }
513 else if (fabsf(view[1]) < 0.1f) {
514 nonortho[0] = view[0];
515 nonortho[1] = view[1] + 1.0f;
516 nonortho[2] = view[2];
517 }
518 else {
519 nonortho[0] = view[0];
520 nonortho[1] = view[1];
521 nonortho[2] = view[2] + 1.0f;
522 }
523
524 /* Get a vector in the plane of the view. */
525 cross_v3_v3v3(ortho, nonortho, view);
526 normalize_v3(ortho);
527
528 /* Make a point on the surface of the brush tangent to the view. */
529 mul_v3_fl(ortho, radius);
530 add_v3_v3v3(offset, location, ortho);
531
532 /* Project the center of the brush, and the tangent point to the view onto the screen. */
537 {
538 /* The distance between these points is the size of the projected brush in pixels. */
539 return len_v2v2(p1, p2);
540 }
541 /* Assert because the code that sets up the vectors should disallow this. */
542 BLI_assert(0);
543 return 0;
544}
545
546/* Draw an overlay that shows what effect the brush's texture will
547 * have on brush strength. */
549 Brush *brush,
550 ViewContext *vc,
551 int x,
552 int y,
553 float zoom,
554 const PaintMode mode,
555 bool col,
556 bool primary)
557{
558 rctf quad;
559 /* Check for overlay mode. */
560
561 MTex *mtex = (primary) ? &brush->mtex : &brush->mask_mtex;
562 bool valid = ((primary) ? (brush->overlay_flags & BRUSH_OVERLAY_PRIMARY) != 0 :
563 (brush->overlay_flags & BRUSH_OVERLAY_SECONDARY) != 0);
564 int overlay_alpha = (primary) ? brush->texture_overlay_alpha : brush->mask_overlay_alpha;
565
566 if (mode == PaintMode::Texture3D) {
567 if (primary && brush->image_brush_type != IMAGE_PAINT_BRUSH_TYPE_DRAW) {
568 /* All non-draw tools don't use the primary texture (clone, smear, soften.. etc). */
569 return false;
570 }
571 }
572
573 if (!(mtex->tex) ||
576 {
577 return false;
578 }
579
580 if (load_tex(brush, vc, zoom, col, primary)) {
581 GPU_color_mask(true, true, true, true);
583
584 if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
586
587 float center[2] = {
588 ups->draw_anchored ? ups->anchored_initial_mouse[0] : x,
589 ups->draw_anchored ? ups->anchored_initial_mouse[1] : y,
590 };
591
592 /* Brush rotation. */
595 GPU_matrix_translate_2f(-center[0], -center[1]);
596
597 /* Scale based on tablet pressure. */
598 if (primary && ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
599 const float scale = ups->size_pressure_value;
601 GPU_matrix_scale_2f(scale, scale);
602 GPU_matrix_translate_2f(-center[0], -center[1]);
603 }
604
605 if (ups->draw_anchored) {
606 quad.xmin = center[0] - ups->anchored_size;
607 quad.ymin = center[1] - ups->anchored_size;
608 quad.xmax = center[0] + ups->anchored_size;
609 quad.ymax = center[1] + ups->anchored_size;
610 }
611 else {
612 const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
613 quad.xmin = center[0] - radius;
614 quad.ymin = center[1] - radius;
615 quad.xmax = center[0] + radius;
616 quad.ymax = center[1] + radius;
617 }
618 }
619 else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
620 quad.xmin = 0;
621 quad.ymin = 0;
622 quad.xmax = BLI_rcti_size_x(&vc->region->winrct);
623 quad.ymax = BLI_rcti_size_y(&vc->region->winrct);
624 }
625 /* Stencil code goes here. */
626 else {
627 if (primary) {
628 quad.xmin = -brush->stencil_dimension[0];
629 quad.ymin = -brush->stencil_dimension[1];
630 quad.xmax = brush->stencil_dimension[0];
631 quad.ymax = brush->stencil_dimension[1];
632 }
633 else {
634 quad.xmin = -brush->mask_stencil_dimension[0];
635 quad.ymin = -brush->mask_stencil_dimension[1];
636 quad.xmax = brush->mask_stencil_dimension[0];
637 quad.ymax = brush->mask_stencil_dimension[1];
638 }
640 if (primary) {
642 }
643 else {
645 }
647 }
648
649 /* Set quad color. Colored overlay does not get blending. */
653
654 /* Premultiplied alpha blending. */
656
658
659 float final_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
660 if (!col) {
661 copy_v3_v3(final_color, U.sculpt_paint_overlay_col);
662 }
663 mul_v4_fl(final_color, overlay_alpha * 0.01f);
664 immUniformColor4fv(final_color);
665
666 GPUTexture *texture = (primary) ? primary_snap.overlay_texture :
667 secondary_snap.overlay_texture;
668
673 "image", texture, {GPU_SAMPLER_FILTERING_LINEAR, extend_mode, extend_mode});
674
675 /* Draw textured quad. */
677 immAttr2f(texCoord, 0.0f, 0.0f);
678 immVertex2f(pos, quad.xmin, quad.ymin);
679 immAttr2f(texCoord, 1.0f, 0.0f);
680 immVertex2f(pos, quad.xmax, quad.ymin);
681 immAttr2f(texCoord, 1.0f, 1.0f);
682 immVertex2f(pos, quad.xmax, quad.ymax);
683 immAttr2f(texCoord, 0.0f, 1.0f);
684 immVertex2f(pos, quad.xmin, quad.ymax);
685 immEnd();
686
688
690
693 }
694 }
695 return true;
696}
697
698/* Draw an overlay that shows what effect the brush's texture will
699 * have on brush strength. */
701 UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom)
702{
703 rctf quad;
704 /* Check for overlay mode. */
705
706 if (!(brush->overlay_flags & BRUSH_OVERLAY_CURSOR)) {
707 return false;
708 }
709
710 if (load_tex_cursor(brush, vc, zoom)) {
711 bool do_pop = false;
712 float center[2];
713
714 GPU_color_mask(true, true, true, true);
716
717 if (ups->draw_anchored) {
719 quad.xmin = ups->anchored_initial_mouse[0] - ups->anchored_size;
720 quad.ymin = ups->anchored_initial_mouse[1] - ups->anchored_size;
721 quad.xmax = ups->anchored_initial_mouse[0] + ups->anchored_size;
722 quad.ymax = ups->anchored_initial_mouse[1] + ups->anchored_size;
723 }
724 else {
725 const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
726 center[0] = x;
727 center[1] = y;
728
729 quad.xmin = x - radius;
730 quad.ymin = y - radius;
731 quad.xmax = x + radius;
732 quad.ymax = y + radius;
733 }
734
735 /* Scale based on tablet pressure. */
736 if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
737 do_pop = true;
741 GPU_matrix_translate_2f(-center[0], -center[1]);
742 }
743
747
749
751
752 float final_color[4] = {UNPACK3(U.sculpt_paint_overlay_col), 1.0f};
753 mul_v4_fl(final_color, brush->cursor_overlay_alpha * 0.01f);
754 immUniformColor4fv(final_color);
755
756 /* Draw textured quad. */
757 immBindTextureSampler("image",
758 cursor_snap.overlay_texture,
759 {GPU_SAMPLER_FILTERING_LINEAR,
760 GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER,
761 GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER});
762
764 immAttr2f(texCoord, 0.0f, 0.0f);
765 immVertex2f(pos, quad.xmin, quad.ymin);
766 immAttr2f(texCoord, 1.0f, 0.0f);
767 immVertex2f(pos, quad.xmax, quad.ymin);
768 immAttr2f(texCoord, 1.0f, 1.0f);
769 immVertex2f(pos, quad.xmax, quad.ymax);
770 immAttr2f(texCoord, 0.0f, 1.0f);
771 immVertex2f(pos, quad.xmin, quad.ymax);
772 immEnd();
773
774 GPU_texture_unbind(cursor_snap.overlay_texture);
775
777
778 if (do_pop) {
780 }
781 }
782 return true;
783}
784
786 Brush *brush,
787 ViewContext *vc,
788 int x,
789 int y,
790 float zoom,
791 PaintMode mode)
792{
793 /* Color means that primary brush texture is colored and
794 * secondary is used for alpha/mask control. */
796
797 bool alpha_overlay_active = false;
798
800 eGPUBlend blend_state = GPU_blend_get();
801 eGPUDepthTest depth_test = GPU_depth_test_get();
802
803 /* Translate to region. */
806 x -= vc->region->winrct.xmin;
807 y -= vc->region->winrct.ymin;
808
809 /* Colored overlay should be drawn separately. */
810 if (col) {
811 if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY)) {
812 alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, mode, true, true);
813 }
814 if (!(flags & PAINT_OVERLAY_OVERRIDE_SECONDARY)) {
815 alpha_overlay_active = paint_draw_tex_overlay(
816 ups, brush, vc, x, y, zoom, mode, false, false);
817 }
818 if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) {
819 alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
820 }
821 }
822 else {
823 if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != PaintMode::Weight)) {
824 alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, mode, false, true);
825 }
826 if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) {
827 alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
828 }
829 }
830
832 GPU_blend(blend_state);
833 GPU_depth_test(depth_test);
834
835 return alpha_overlay_active;
836}
837
839 const float sel_col[4],
840 const float pivot_col[4],
841 float *co,
842 float width,
843 bool selected)
844{
845 immUniformColor4fv(selected ? sel_col : pivot_col);
846
847 GPU_line_width(3.0f);
848
849 float w = width / 2.0f;
850 const float tri[3][2] = {
851 {co[0], co[1] + w},
852 {co[0] - w, co[1] - w},
853 {co[0] + w, co[1] - w},
854 };
855
857 immVertex2fv(pos, tri[0]);
858 immVertex2fv(pos, tri[1]);
859 immVertex2fv(pos, tri[2]);
860 immEnd();
861
862 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
863 GPU_line_width(1.0f);
864
866 immVertex2fv(pos, tri[0]);
867 immVertex2fv(pos, tri[1]);
868 immVertex2fv(pos, tri[2]);
869 immEnd();
870}
871
873 const float sel_col[4],
874 const float handle_col[4],
875 const float *co,
876 float width,
877 bool selected)
878{
879 immUniformColor4fv(selected ? sel_col : handle_col);
880
881 GPU_line_width(3.0f);
882
883 float w = width / 2.0f;
884 float minx = co[0] - w;
885 float miny = co[1] - w;
886 float maxx = co[0] + w;
887 float maxy = co[1] + w;
888
889 imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
890
891 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
892 GPU_line_width(1.0f);
893
894 imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
895}
896
897BLI_INLINE void draw_bezier_handle_lines(uint pos, const float sel_col[4], BezTriple *bez)
898{
899 immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
900 GPU_line_width(3.0f);
901
903 immVertex2fv(pos, bez->vec[0]);
904 immVertex2fv(pos, bez->vec[1]);
905 immVertex2fv(pos, bez->vec[2]);
906 immEnd();
907
908 GPU_line_width(1.0f);
909
910 if (bez->f1 || bez->f2) {
911 immUniformColor4fv(sel_col);
912 }
913 else {
914 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
915 }
917 immVertex2fv(pos, bez->vec[0]);
918 immVertex2fv(pos, bez->vec[1]);
919 immEnd();
920
921 if (bez->f3 || bez->f2) {
922 immUniformColor4fv(sel_col);
923 }
924 else {
925 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
926 }
928 immVertex2fv(pos, bez->vec[1]);
929 immVertex2fv(pos, bez->vec[2]);
930 immEnd();
931}
932
934{
937
938 if (brush->paint_curve && brush->paint_curve->points) {
939 PaintCurve *pc = brush->paint_curve;
940 PaintCurvePoint *cp = pc->points;
941
942 GPU_line_smooth(true);
944
945 /* Draw the bezier handles and the curve segment between the current and next point. */
947
949
950 float selec_col[4], handle_col[4], pivot_col[4];
954
955 for (int i = 0; i < pc->tot_points - 1; i++, cp++) {
956 int j;
957 PaintCurvePoint *cp_next = cp + 1;
958 float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
959 /* Use color coding to distinguish handles vs curve segments. */
960 draw_bezier_handle_lines(pos, selec_col, &cp->bez);
961 draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2);
963 pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
965 pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
966
967 for (j = 0; j < 2; j++) {
969 cp->bez.vec[2][j],
970 cp_next->bez.vec[0][j],
971 cp_next->bez.vec[1][j],
972 data + j,
974 sizeof(float[2]));
975 }
976
977 float(*v)[2] = (float(*)[2])data;
978
979 immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
980 GPU_line_width(3.0f);
982 for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
983 immVertex2fv(pos, v[j]);
984 }
985 immEnd();
986
987 immUniformColor4f(0.9f, 0.9f, 1.0f, 0.5f);
988 GPU_line_width(1.0f);
990 for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
991 immVertex2fv(pos, v[j]);
992 }
993 immEnd();
994 }
995
996 /* Draw last line segment. */
997 draw_bezier_handle_lines(pos, selec_col, &cp->bez);
998 draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2);
1000 pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
1002 pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
1003
1005 GPU_line_smooth(false);
1006
1008 }
1010}
1011
1012/* Special actions taken when paint cursor goes over mesh */
1013/* TODO: sculpt only for now. */
1015 Brush &brush,
1016 ViewContext &vc,
1017 const float location[3])
1018{
1019 float unprojected_radius, projected_radius;
1020
1021 /* Update the brush's cached 3D radius. */
1022 if (!BKE_brush_use_locked_size(vc.scene, &brush)) {
1023 /* Get 2D brush radius. */
1024 if (ups.draw_anchored) {
1025 projected_radius = ups.anchored_size;
1026 }
1027 else {
1028 if (brush.flag & BRUSH_ANCHORED) {
1029 projected_radius = 8;
1030 }
1031 else {
1032 projected_radius = BKE_brush_size_get(vc.scene, &brush);
1033 }
1034 }
1035
1036 /* Convert brush radius from 2D to 3D. */
1037 unprojected_radius = paint_calc_object_space_radius(vc, location, projected_radius);
1038
1039 /* Scale 3D brush radius by pressure. */
1040 if (ups.stroke_active && BKE_brush_use_size_pressure(&brush)) {
1041 unprojected_radius *= ups.size_pressure_value;
1042 }
1043
1044 /* Set cached value in either Brush or UnifiedPaintSettings. */
1045 BKE_brush_unprojected_radius_set(vc.scene, &brush, unprojected_radius);
1046 }
1047}
1048
1049static void cursor_draw_point_screen_space(const uint gpuattr,
1050 const ARegion *region,
1051 const float true_location[3],
1052 const float obmat[4][4],
1053 const int size)
1054{
1055 float translation_vertex_cursor[3], location[3];
1056 copy_v3_v3(location, true_location);
1057 mul_m4_v3(obmat, location);
1058 ED_view3d_project_v3(region, location, translation_vertex_cursor);
1059 /* Do not draw points behind the view. Z [near, far] is mapped to [-1, 1]. */
1060 if (translation_vertex_cursor[2] <= 1.0f) {
1062 gpuattr, translation_vertex_cursor[0], translation_vertex_cursor[1], size, 10);
1063 }
1064}
1065
1066static void cursor_draw_tiling_preview(const uint gpuattr,
1067 const ARegion *region,
1068 const float true_location[3],
1069 const Sculpt &sd,
1070 const Object &ob,
1071 const float radius)
1072{
1073 BLI_assert(ob.type == OB_MESH);
1075 if (!mesh) {
1076 mesh = static_cast<const Mesh *>(ob.data);
1077 }
1078 const Bounds<float3> bounds = *mesh->bounds_min_max();
1079 float orgLoc[3], location[3];
1080 int tile_pass = 0;
1081 int start[3];
1082 int end[3];
1083 int cur[3];
1084 const float *step = sd.paint.tile_offset;
1085
1086 copy_v3_v3(orgLoc, true_location);
1087 for (int dim = 0; dim < 3; dim++) {
1088 if ((sd.paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) {
1089 start[dim] = (bounds.min[dim] - orgLoc[dim] - radius) / step[dim];
1090 end[dim] = (bounds.max[dim] - orgLoc[dim] + radius) / step[dim];
1091 }
1092 else {
1093 start[dim] = end[dim] = 0;
1094 }
1095 }
1096 copy_v3_v3_int(cur, start);
1097 for (cur[0] = start[0]; cur[0] <= end[0]; cur[0]++) {
1098 for (cur[1] = start[1]; cur[1] <= end[1]; cur[1]++) {
1099 for (cur[2] = start[2]; cur[2] <= end[2]; cur[2]++) {
1100 if (!cur[0] && !cur[1] && !cur[2]) {
1101 /* Skip tile at orgLoc, this was already handled before all others. */
1102 continue;
1103 }
1104 tile_pass++;
1105 for (int dim = 0; dim < 3; dim++) {
1106 location[dim] = cur[dim] * step[dim] + orgLoc[dim];
1107 }
1108 cursor_draw_point_screen_space(gpuattr, region, location, ob.object_to_world().ptr(), 3);
1109 }
1110 }
1111 }
1112 (void)tile_pass; /* Quiet set-but-unused warning (may be removed). */
1113}
1114
1115static void cursor_draw_point_with_symmetry(const uint gpuattr,
1116 const ARegion *region,
1117 const float true_location[3],
1118 const Sculpt &sd,
1119 const Object &ob,
1120 const float radius)
1121{
1122 const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
1123 float3 location;
1124 float symm_rot_mat[4][4];
1125
1126 for (int i = 0; i <= symm; i++) {
1127 if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5)))) {
1128
1129 /* Axis Symmetry. */
1130 location = symmetry_flip(true_location, ePaintSymmetryFlags(i));
1131 cursor_draw_point_screen_space(gpuattr, region, location, ob.object_to_world().ptr(), 3);
1132
1133 /* Tiling. */
1134 cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius);
1135
1136 /* Radial Symmetry. */
1137 for (char raxis = 0; raxis < 3; raxis++) {
1138 for (int r = 1; r < sd.radial_symm[raxis]; r++) {
1139 float angle = 2 * M_PI * r / sd.radial_symm[int(raxis)];
1140 location = symmetry_flip(true_location, ePaintSymmetryFlags(i));
1141 unit_m4(symm_rot_mat);
1142 rotate_m4(symm_rot_mat, raxis + 'X', angle);
1143 mul_m4_v3(symm_rot_mat, location);
1144
1145 cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius);
1146 cursor_draw_point_screen_space(gpuattr, region, location, ob.object_to_world().ptr(), 3);
1147 }
1148 }
1149 }
1150 }
1151}
1152
1154 const uint gpuattr,
1155 const Brush &brush,
1156 const Object &object)
1157{
1158 if (!(brush.flag & BRUSH_GRAB_ACTIVE_VERTEX)) {
1159 return;
1160 }
1161
1162 const SculptSession &ss = *object.sculpt;
1163 if (bke::object::pbvh_get(object)->type() != bke::pbvh::Type::Mesh) {
1164 return;
1165 }
1166
1167 if (!ss.deform_modifiers_active) {
1168 return;
1169 }
1170
1171 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.6f);
1172
1173 /* Cursor normally draws on top, but for this part we need depth tests. */
1174 const eGPUDepthTest depth_test = GPU_depth_test_get();
1175 if (!depth_test) {
1177 }
1178
1179 GPU_line_width(1.0f);
1180 if (!ss.preview_verts.is_empty()) {
1183 for (const int vert : ss.preview_verts) {
1184 immVertex3fv(gpuattr, positions[vert]);
1185 }
1186 immEnd();
1187 }
1188
1189 /* Restore depth test value. */
1190 if (!depth_test) {
1192 }
1193}
1194
1196 const Brush &brush,
1197 const float rds,
1198 const float line_width,
1199 const float outline_col[3],
1200 const float alpha)
1201{
1202 float cursor_trans[4][4];
1203 unit_m4(cursor_trans);
1204 translate_m4(cursor_trans, 0.0f, 0.0f, brush.height);
1206 GPU_matrix_mul(cursor_trans);
1207
1208 GPU_line_width(line_width);
1209 immUniformColor3fvAlpha(outline_col, alpha * 0.5f);
1210 imm_draw_circle_wire_3d(gpuattr, 0, 0, rds, 80);
1212}
1213
1215{
1216 switch (mode) {
1217 case PaintMode::Sculpt:
1218 case PaintMode::Vertex:
1219 case PaintMode::Weight:
1220 return false;
1228 case PaintMode::GPencil:
1229 return true;
1230 case PaintMode::Invalid:
1232 }
1233 return true;
1234}
1235
1241
1247 Depsgraph *depsgraph;
1254
1255 /* Sculpt related data. */
1258
1263
1266 float radius;
1267
1268 /* 3D view cursor position and normal. */
1269 float location[3];
1271 float normal[3];
1272
1273 /* Cursor main colors. */
1274 float outline_col[3];
1276
1277 /* GPU attribute for drawing. */
1279
1281
1282 /* This variable is set after drawing the overlay, not on initialization. It can't be used for
1283 * checking if alpha overlay is enabled before drawing it. */
1285
1286 float zoomx;
1287 int x, y;
1288 float translation[2];
1289
1292};
1293
1295 const int x,
1296 const int y,
1297 PaintCursorContext *pcontext)
1298{
1299 ARegion *region = CTX_wm_region(C);
1300 if (region && region->regiontype != RGN_TYPE_WINDOW) {
1301 return false;
1302 }
1303
1304 pcontext->C = C;
1305 pcontext->region = region;
1306 pcontext->wm = CTX_wm_manager(C);
1307 pcontext->win = CTX_wm_window(C);
1309 pcontext->scene = CTX_data_scene(C);
1310 pcontext->ups = &pcontext->scene->toolsettings->unified_paint_settings;
1312 if (pcontext->paint == nullptr) {
1313 return false;
1314 }
1315 pcontext->brush = BKE_paint_brush(pcontext->paint);
1316 if (pcontext->brush == nullptr) {
1317 return false;
1318 }
1320
1321 pcontext->vc = ED_view3d_viewcontext_init(C, pcontext->depsgraph);
1322
1323 if (pcontext->brush->flag & BRUSH_CURVE) {
1324 pcontext->cursor_type = PAINT_CURSOR_CURVE;
1325 }
1326 else if (paint_use_2d_cursor(pcontext->mode)) {
1327 pcontext->cursor_type = PAINT_CURSOR_2D;
1328 }
1329 else {
1330 pcontext->cursor_type = PAINT_CURSOR_3D;
1331 }
1332
1333 pcontext->x = x;
1334 pcontext->y = y;
1335 pcontext->translation[0] = float(x);
1336 pcontext->translation[1] = float(y);
1337
1338 float zoomx, zoomy;
1339 get_imapaint_zoom(C, &zoomx, &zoomy);
1340 pcontext->zoomx = max_ff(zoomx, zoomy);
1341 pcontext->final_radius = (BKE_brush_size_get(pcontext->scene, pcontext->brush) * zoomx);
1342
1343 /* There is currently no way to check if the direction is inverted before starting the stroke,
1344 * so this does not reflect the state of the brush in the UI. */
1345 if (((pcontext->ups->draw_inverted == 0) ^ ((pcontext->brush->flag & BRUSH_DIR_IN) == 0)) &&
1347 {
1348 copy_v3_v3(pcontext->outline_col, pcontext->brush->sub_col);
1349 }
1350 else {
1351 copy_v3_v3(pcontext->outline_col, pcontext->brush->add_col);
1352 }
1353 pcontext->outline_alpha = pcontext->brush->add_col[3];
1354
1355 Object *active_object = pcontext->vc.obact;
1356 pcontext->ss = active_object ? active_object->sculpt : nullptr;
1357
1358 if (pcontext->ss && pcontext->ss->draw_faded_cursor) {
1359 pcontext->outline_alpha = 0.3f;
1360 copy_v3_fl(pcontext->outline_col, 0.8f);
1361 }
1362
1363 const bool is_brush_tool = paint_brush_tool_poll(C);
1364 if (!is_brush_tool) {
1365 /* Use a default color for tools that are not brushes. */
1366 pcontext->outline_alpha = 0.8f;
1367 copy_v3_fl(pcontext->outline_col, 0.8f);
1368 }
1369
1370 pcontext->is_stroke_active = pcontext->ups->stroke_active;
1371
1372 return true;
1373}
1374
1376{
1377 if (pcontext->is_cursor_over_mesh) {
1378 Brush *brush = BKE_paint_brush(pcontext->paint);
1380 &pcontext->vc,
1381 BKE_brush_unprojected_radius_get(pcontext->scene, brush),
1382 pcontext->location);
1383
1384 if (pcontext->pixel_radius == 0) {
1385 pcontext->pixel_radius = BKE_brush_size_get(pcontext->scene, brush);
1386 }
1387
1388 copy_v3_v3(pcontext->scene_space_location, pcontext->location);
1389 mul_m4_v3(pcontext->vc.obact->object_to_world().ptr(), pcontext->scene_space_location);
1390 }
1391 else {
1392 Sculpt *sd = CTX_data_tool_settings(pcontext->C)->sculpt;
1393 Brush *brush = BKE_paint_brush(&sd->paint);
1394
1395 pcontext->pixel_radius = BKE_brush_size_get(pcontext->scene, brush);
1396 }
1397}
1398
1400{
1401 BLI_assert(pcontext->ss != nullptr);
1402 BLI_assert(pcontext->mode == PaintMode::Sculpt);
1403
1404 bContext *C = pcontext->C;
1405 SculptSession &ss = *pcontext->ss;
1406 Brush &brush = *pcontext->brush;
1407 Scene &scene = *pcontext->scene;
1408 UnifiedPaintSettings &ups = *pcontext->ups;
1409 ViewContext &vc = pcontext->vc;
1411
1412 const float mval_fl[2] = {
1413 float(pcontext->x - pcontext->region->winrct.xmin),
1414 float(pcontext->y - pcontext->region->winrct.ymin),
1415 };
1416
1417 /* Ensure that the PBVH is generated before we call #SCULPT_cursor_geometry_info_update because
1418 * the PBVH is needed to do a ray-cast to find the active vertex. */
1419 bke::object::pbvh_ensure(*pcontext->depsgraph, *pcontext->vc.obact);
1420
1421 /* This updates the active vertex, which is needed for most of the Sculpt/Vertex Colors tools to
1422 * work correctly */
1424 if (!ups.stroke_active) {
1426 C, &gi, mval_fl, (pcontext->brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE));
1427 copy_v3_v3(pcontext->location, gi.location);
1428 copy_v3_v3(pcontext->normal, gi.normal);
1429 }
1430 else {
1431 pcontext->is_cursor_over_mesh = ups.last_hit;
1432 copy_v3_v3(pcontext->location, ups.last_location);
1433 }
1434
1436
1437 if (BKE_brush_use_locked_size(&scene, &brush)) {
1438 BKE_brush_size_set(&scene, &brush, pcontext->pixel_radius);
1439 }
1440
1441 if (pcontext->is_cursor_over_mesh) {
1443 }
1444
1445 pcontext->sd = CTX_data_tool_settings(pcontext->C)->sculpt;
1446}
1447
1449{
1450 if (pcontext->win->grabcursor != 0) {
1451 /* Don't set the cursor while it's grabbed, since this will show the cursor when interacting
1452 * with the UI (dragging a number button for e.g.), see: #102792. */
1453 return;
1454 }
1456 WM_cursor_set(pcontext->win, WM_CURSOR_DOT);
1457 }
1458 else {
1459 WM_cursor_set(pcontext->win, WM_CURSOR_PAINT);
1460 }
1461}
1462
1464{
1466
1467 /* Draw brush outline. */
1468 if (pcontext->ups->stroke_active && BKE_brush_use_size_pressure(pcontext->brush)) {
1469 imm_draw_circle_wire_2d(pcontext->pos,
1470 pcontext->translation[0],
1471 pcontext->translation[1],
1472 pcontext->final_radius * pcontext->ups->size_pressure_value,
1473 40);
1474 /* Outer at half alpha. */
1475 immUniformColor3fvAlpha(pcontext->outline_col, pcontext->outline_alpha * 0.5f);
1476 }
1477
1478 GPU_line_width(1.0f);
1479 imm_draw_circle_wire_2d(pcontext->pos,
1480 pcontext->translation[0],
1481 pcontext->translation[1],
1482 pcontext->final_radius,
1483 40);
1484}
1485
1487{
1488 float radius = float(pcontext->pixel_radius);
1489
1490 /* Red-ish color with alpha. */
1491 immUniformColor4ub(255, 100, 100, 20);
1492 imm_draw_circle_fill_2d(pcontext->pos, pcontext->x, pcontext->y, radius, 40);
1493
1495
1497
1498 float viewport_size[4];
1499 GPU_viewport_size_get_f(viewport_size);
1500 immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
1501
1502 immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
1503 immUniform1i("colors_len", 0); /* "simple" mode */
1504 immUniform1f("dash_width", 12.0f);
1505 immUniform1f("udash_factor", 0.5f);
1506
1507 /* XXX Dashed shader gives bad results with sets of small segments
1508 * currently, temp hack around the issue. :( */
1509 const int nsegments = max_ii(8, radius / 2);
1510 imm_draw_circle_wire_2d(pcontext->pos, pcontext->x, pcontext->y, radius, nsegments);
1511}
1512
1514{
1515 if (pcontext->region && !BLI_rcti_isect_pt(&pcontext->region->winrct, pcontext->x, pcontext->y))
1516 {
1517 return;
1518 }
1519
1520 Object *object = CTX_data_active_object(pcontext->C);
1521 if (object->type != OB_GREASE_PENCIL) {
1522 return;
1523 }
1524
1525 GreasePencil *grease_pencil = static_cast<GreasePencil *>(object->data);
1526 Paint *paint = pcontext->paint;
1527 Brush *brush = pcontext->brush;
1528 if ((brush == nullptr) || (brush->gpencil_settings == nullptr)) {
1529 return;
1530 }
1531
1532 float3 color(1.0f);
1533 const int x = pcontext->x;
1534 const int y = pcontext->y;
1535
1536 if (pcontext->mode == PaintMode::GPencil) {
1537 /* Hide the cursor while drawing. */
1538 if (grease_pencil->runtime->is_drawing_stroke) {
1539 return;
1540 }
1541
1542 /* Eraser has a special shape and uses a different shader program. */
1544 grease_pencil->runtime->temp_use_eraser)
1545 {
1546 /* If we use the eraser from the draw tool with a "scene" radius unit, we need to draw the
1547 * cursor with the appropriate size. */
1548 if (grease_pencil->runtime->temp_use_eraser && (brush->flag & BRUSH_LOCK_SIZE) != 0) {
1549 pcontext->pixel_radius = int(grease_pencil->runtime->temp_eraser_size);
1550 }
1551 else {
1552 pcontext->pixel_radius = brush->size;
1553 }
1554 grease_pencil_eraser_draw(pcontext);
1555 return;
1556 }
1557
1559 /* The fill tool doesn't use a brush size currently, but not showing any brush means that it
1560 * can be hard to see where the cursor is. Use a fixed size that's not too big (10px). By
1561 * disabling the "Display Cursor" option, this can still be turned off. */
1562 pcontext->pixel_radius = 10;
1563 }
1564
1566 pcontext->pixel_radius = brush->size;
1567 }
1568
1570 if ((brush->flag & BRUSH_LOCK_SIZE) != 0) {
1571 const bke::greasepencil::Layer *layer = grease_pencil->get_active_layer();
1572 const ed::greasepencil::DrawingPlacement placement(
1573 *pcontext->scene, *pcontext->region, *pcontext->vc.v3d, *object, layer);
1574 const float3 location = placement.project(float2(pcontext->x, pcontext->y));
1576 &pcontext->vc, brush->unprojected_radius, location);
1577 brush->size = std::max(pcontext->pixel_radius, 1);
1578 }
1579 else {
1580 pcontext->pixel_radius = brush->size;
1581 }
1582 }
1583
1584 /* Get current drawing material. */
1586 MaterialGPencilStyle *gp_style = ma->gp_style;
1587
1588 /* Follow user settings for the size of the draw cursor:
1589 * - Fixed size, or
1590 * - Brush size (i.e. stroke thickness)
1591 */
1592 if ((gp_style) && ((brush->flag & BRUSH_SMOOTH_STROKE) == 0) &&
1594 {
1595
1597 pcontext->scene->toolsettings->gp_paint, brush);
1598 const bool use_vertex_color_stroke = use_vertex_color &&
1602 color = use_vertex_color_stroke ? float3(brush->rgb) : float4(gp_style->stroke_rgba).xyz();
1603 }
1604 }
1605
1606 if ((brush->flag & BRUSH_SMOOTH_STROKE) != 0) {
1607 const float scale = 1.0f / 255.0f;
1608 color = scale * float3(paint->paint_cursor_col);
1609 }
1610 }
1611 else if (pcontext->mode == PaintMode::VertexGPencil) {
1612 pcontext->pixel_radius = BKE_brush_size_get(pcontext->vc.scene, brush);
1613 color = BKE_brush_color_get(pcontext->vc.scene, paint, brush);
1614 }
1615
1616 GPU_line_width(1.0f);
1617 /* Inner Ring: Color from UI panel */
1618 immUniformColor4f(color.x, color.y, color.z, 0.8f);
1619 imm_draw_circle_wire_2d(pcontext->pos, x, y, pcontext->pixel_radius, 32);
1620
1621 /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
1622 const float3 darkcolor = color * 0.40f;
1623 immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f);
1624 imm_draw_circle_wire_2d(pcontext->pos, x, y, pcontext->pixel_radius + 1, 32);
1625}
1626
1628{
1629 switch (pcontext->mode) {
1630 case PaintMode::GPencil:
1633 break;
1634 default:
1636 }
1637}
1638
1640{
1641 GPU_line_width(1.0f);
1643 imm_draw_circle_wire_3d(pcontext->pos,
1644 pcontext->translation[0],
1645 pcontext->translation[1],
1646 pcontext->final_radius,
1647 40);
1648}
1649
1651{
1652 GPU_line_width(1.0f);
1653 /* Reduce alpha to increase the contrast when the cursor is over the mesh. */
1654 immUniformColor3fvAlpha(pcontext->outline_col, pcontext->outline_alpha * 0.8);
1655 imm_draw_circle_wire_3d(pcontext->pos,
1656 pcontext->translation[0],
1657 pcontext->translation[1],
1658 pcontext->final_radius,
1659 80);
1660 immUniformColor3fvAlpha(pcontext->outline_col, pcontext->outline_alpha * 0.35f);
1661 imm_draw_circle_wire_3d(pcontext->pos,
1662 pcontext->translation[0],
1663 pcontext->translation[1],
1664 pcontext->final_radius * clamp_f(pcontext->brush->alpha, 0.0f, 1.0f),
1665 80);
1666}
1667
1669{
1670 if (!BKE_brush_use_locked_size(pcontext->scene, pcontext->brush)) {
1672 pcontext->vc, pcontext->location, BKE_brush_size_get(pcontext->scene, pcontext->brush));
1673 }
1674 else {
1675 pcontext->radius = BKE_brush_unprojected_radius_get(pcontext->scene, pcontext->brush);
1676 }
1677}
1678
1680{
1681 float cursor_trans[4][4], cursor_rot[4][4];
1682 const float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f};
1683 float quat[4];
1684 copy_m4_m4(cursor_trans, pcontext->vc.obact->object_to_world().ptr());
1685 translate_m4(cursor_trans, pcontext->location[0], pcontext->location[1], pcontext->location[2]);
1686 rotation_between_vecs_to_quat(quat, z_axis, pcontext->normal);
1687 quat_to_mat4(cursor_rot, quat);
1688 GPU_matrix_mul(cursor_trans);
1689 GPU_matrix_mul(cursor_rot);
1690}
1691
1693{
1695 GPU_line_width(2.0f);
1696 imm_draw_circle_wire_3d(pcontext->pos, 0, 0, pcontext->radius, 80);
1697
1698 GPU_line_width(1.0f);
1699 immUniformColor3fvAlpha(pcontext->outline_col, pcontext->outline_alpha * 0.5f);
1701 pcontext->pos, 0, 0, pcontext->radius * clamp_f(pcontext->brush->alpha, 0.0f, 1.0f), 80);
1702}
1703
1705{
1706 SculptSession &ss = *pcontext->ss;
1707 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
1708 GPU_line_width(2.0f);
1709
1710 BLI_assert(ss.pose_ik_chain_preview->initial_head_coords.size() ==
1711 ss.pose_ik_chain_preview->initial_orig_coords.size());
1712
1713 immBegin(GPU_PRIM_LINES, ss.pose_ik_chain_preview->initial_head_coords.size() * 2);
1714 for (const int i : ss.pose_ik_chain_preview->initial_head_coords.index_range()) {
1715 immVertex3fv(pcontext->pos, ss.pose_ik_chain_preview->initial_orig_coords[i]);
1716 immVertex3fv(pcontext->pos, ss.pose_ik_chain_preview->initial_head_coords[i]);
1717 }
1718
1719 immEnd();
1720}
1721
1723{
1724
1725 SculptSession &ss = *pcontext->ss;
1726 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
1727 for (const int i : ss.pose_ik_chain_preview->initial_orig_coords.index_range()) {
1729 pcontext->region,
1730 ss.pose_ik_chain_preview->initial_orig_coords[i],
1731 pcontext->vc.obact->object_to_world().ptr(),
1732 3);
1733 }
1734}
1735
1737{
1738 if (!pcontext->ss->boundary_preview) {
1739 /* There is no guarantee that a boundary preview exists as there may be no boundaries
1740 * inside the brush radius. */
1741 return;
1742 }
1743 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
1745 pcontext->region,
1746 pcontext->ss->boundary_preview->pivot_position,
1747 pcontext->vc.obact->object_to_world().ptr(),
1748 3);
1749}
1750
1752{
1753 SculptSession &ss = *pcontext->ss;
1754 /* Needed for updating the necessary SculptSession data in order to initialize the
1755 * boundary data for the preview. */
1756 BKE_sculpt_update_object_for_edit(pcontext->depsgraph, pcontext->vc.obact, false);
1757
1759 *pcontext->depsgraph, *pcontext->vc.obact, pcontext->brush, pcontext->radius);
1760}
1761
1763{
1764 const Brush &brush = *pcontext->brush;
1765
1766 /* 2D falloff is better represented with the default 2D cursor,
1767 * there is no need to draw anything else. */
1770 return;
1771 }
1772
1773 if (pcontext->alpha_overlay_drawn) {
1775 return;
1776 }
1777
1778 if (!pcontext->is_cursor_over_mesh) {
1780 return;
1781 }
1782
1783 BLI_assert(pcontext->vc.obact);
1784 Object &active_object = *pcontext->vc.obact;
1786
1788
1789 /* Setup drawing. */
1790 wmViewport(&pcontext->region->winrct);
1791
1792 /* Drawing of Cursor overlays in 2D screen space. */
1793
1794 /* Cursor location symmetry points. */
1795
1796 float3 active_vertex_co;
1798 SculptSession &ss = *pcontext->ss;
1799 if (bke::object::pbvh_get(active_object)->type() == bke::pbvh::Type::Mesh) {
1800 const Span<float3> positions = vert_positions_for_grab_active_get(*pcontext->depsgraph,
1801 active_object);
1802 active_vertex_co = positions[std::get<int>(ss.active_vert())];
1803 }
1804 else {
1805 active_vertex_co = pcontext->ss->active_vert_position(*pcontext->depsgraph, active_object);
1806 }
1807 }
1808 else {
1809 active_vertex_co = pcontext->ss->active_vert_position(*pcontext->depsgraph, active_object);
1810 }
1811 if (len_v3v3(active_vertex_co, pcontext->location) < pcontext->radius) {
1814 pcontext->region,
1815 active_vertex_co,
1816 *pcontext->sd,
1817 active_object,
1818 pcontext->radius);
1819 }
1820
1821 const bool is_brush_tool = paint_brush_tool_poll(pcontext->C);
1822
1823 /* Pose brush updates and rotation origins. */
1824
1825 if (is_brush_tool && brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_POSE) {
1826 /* Just after switching to the Pose Brush, the active vertex can be the same and the
1827 * cursor won't be tagged to update, so always initialize the preview chain if it is
1828 * nullptr before drawing it. */
1829 SculptSession &ss = *pcontext->ss;
1830 const bool update_previews = pcontext->prev_active_vert_index !=
1831 pcontext->ss->active_vert_index();
1832 if (update_previews || !ss.pose_ik_chain_preview) {
1833 BKE_sculpt_update_object_for_edit(pcontext->depsgraph, &active_object, false);
1834
1835 /* Free the previous pose brush preview. */
1836 if (ss.pose_ik_chain_preview) {
1837 ss.pose_ik_chain_preview.reset();
1838 }
1839
1840 /* Generate a new pose brush preview from the current cursor location. */
1842 *pcontext->depsgraph, active_object, ss, brush, pcontext->location, pcontext->radius);
1843 }
1844
1845 /* Draw the pose brush rotation origins. */
1847 }
1848
1849 /* Expand operation origin. */
1850 if (pcontext->ss->expand_cache) {
1851 const int vert = pcontext->ss->expand_cache->initial_active_vert;
1852
1853 float3 position;
1854 switch (bke::object::pbvh_get(active_object)->type()) {
1855 case bke::pbvh::Type::Mesh: {
1856 const Span positions = bke::pbvh::vert_positions_eval(*pcontext->depsgraph, active_object);
1857 position = positions[vert];
1858 break;
1859 }
1861 const SubdivCCG &subdiv_ccg = *pcontext->ss->subdiv_ccg;
1862 position = subdiv_ccg.positions[vert];
1863 break;
1864 }
1866 BMesh &bm = *pcontext->ss->bm;
1867 position = BM_vert_at_index(&bm, vert)->co;
1868 break;
1869 }
1870 }
1872 pcontext->pos, pcontext->region, position, active_object.object_to_world().ptr(), 2);
1873 }
1874
1875 if (is_brush_tool && brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_BOUNDARY) {
1878 }
1879
1880 /* Setup 3D perspective drawing. */
1882 ED_view3d_draw_setup_view(pcontext->wm,
1883 pcontext->win,
1884 pcontext->depsgraph,
1885 pcontext->scene,
1886 pcontext->region,
1887 CTX_wm_view3d(pcontext->C),
1888 nullptr,
1889 nullptr,
1890 nullptr);
1891
1893 GPU_matrix_mul(active_object.object_to_world().ptr());
1894
1895 /* Drawing Cursor overlays in 3D object space. */
1896 if (is_brush_tool && brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_GRAB &&
1898 {
1900 *pcontext->depsgraph, *pcontext->vc.obact, *pcontext->ss, pcontext->radius);
1902 *pcontext->depsgraph, pcontext->pos, *pcontext->brush, active_object);
1903 }
1904
1905 if (is_brush_tool && brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_POSE) {
1907 }
1908
1909 if (is_brush_tool && brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_BOUNDARY) {
1911 pcontext->pos, *pcontext->ss, pcontext->outline_col, pcontext->outline_alpha);
1912 boundary::pivot_line_preview_draw(pcontext->pos, *pcontext->ss);
1913 }
1914
1916
1917 /* Drawing Cursor overlays in Paint Cursor space (as additional info on top of the brush cursor)
1918 */
1921 /* Main inactive cursor. */
1923
1924 /* Cloth brush local simulation areas. */
1925 if (is_brush_tool && brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_CLOTH &&
1927 {
1928 const float white[3] = {1.0f, 1.0f, 1.0f};
1929 const float zero_v[3] = {0.0f};
1930 /* This functions sets its own drawing space in order to draw the simulation limits when the
1931 * cursor is active. When used here, this cursor overlay is already in cursor space, so its
1932 * position and normal should be set to 0. */
1934 pcontext->pos, brush, zero_v, zero_v, pcontext->radius, 1.0f, white, 0.25f);
1935 }
1936
1937 /* Layer brush height. */
1938 if (is_brush_tool && brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_LAYER) {
1940 brush,
1941 pcontext->radius,
1942 1.0f,
1943 pcontext->outline_col,
1944 pcontext->outline_alpha);
1945 }
1946
1948
1949 /* Reset drawing. */
1951 wmWindowViewport(pcontext->win);
1952}
1953
1955{
1956 BLI_assert(pcontext->ss != nullptr);
1957 BLI_assert(pcontext->mode == PaintMode::Sculpt);
1958
1959 SculptSession &ss = *pcontext->ss;
1960 Brush &brush = *pcontext->brush;
1961
1962 /* The cursor can be updated as active before creating the StrokeCache, so this needs to be
1963 * checked. */
1964 if (!ss.cache) {
1965 return;
1966 }
1967
1968 /* Most of the brushes initialize the necessary data for the custom cursor drawing after the
1969 * first brush step, so make sure that it is not drawn before being initialized. */
1971 return;
1972 }
1973
1974 /* Setup drawing. */
1975 wmViewport(&pcontext->region->winrct);
1977 ED_view3d_draw_setup_view(pcontext->wm,
1978 pcontext->win,
1979 pcontext->depsgraph,
1980 pcontext->scene,
1981 pcontext->region,
1982 CTX_wm_view3d(pcontext->C),
1983 nullptr,
1984 nullptr,
1985 nullptr);
1987 GPU_matrix_mul(pcontext->vc.obact->object_to_world().ptr());
1988
1989 /* Draw the special active cursors different brush types may have. */
1990
1993 *pcontext->depsgraph, pcontext->pos, brush, *pcontext->vc.obact);
1994 }
1995
1998 pcontext->pos, brush, ss, pcontext->outline_col, pcontext->outline_alpha);
1999 }
2000
2004 pcontext->pos, ss, pcontext->outline_col, pcontext->outline_alpha);
2005 }
2008 {
2009 /* Display the simulation limits if sculpting outside them. */
2010 /* This does not makes much sense of plane falloff as the falloff is infinite or global. */
2011
2013 ss.cache->radius * (1.0f + brush.cloth_sim_limit))
2014 {
2015 const float red[3] = {1.0f, 0.2f, 0.2f};
2017 brush,
2020 ss.cache->radius,
2021 2.0f,
2022 red,
2023 0.8f);
2024 }
2025 }
2026 }
2027
2029
2031 wmWindowViewport(pcontext->win);
2032}
2033
2035{
2036
2037 /* These paint tools are not using the SculptSession, so they need to use the default 2D brush
2038 * cursor in the 3D view. */
2039 if (pcontext->mode != PaintMode::Sculpt || !pcontext->ss) {
2041 return;
2042 }
2043
2045
2046 if (pcontext->is_stroke_active) {
2048 }
2049 else {
2051 }
2052}
2053
2055{
2056 ViewContext *vc = &pcontext->vc;
2057 return vc->rv3d && (vc->rv3d->rflag & RV3D_NAVIGATING);
2058}
2059
2061{
2062 if (pcontext->paint->flags & PAINT_SHOW_BRUSH) {
2065 {
2066 return false;
2067 }
2068 return true;
2069 }
2070 return false;
2071}
2072
2074{
2075 /* Don't calculate rake angles while a stroke is active because the rake variables are global
2076 * and we may get interference with the stroke itself.
2077 * For line strokes, such interference is visible. */
2078 if (!pcontext->ups->stroke_active) {
2080 *pcontext->ups, *pcontext->brush, pcontext->translation, pcontext->mode, true);
2081 }
2082}
2083
2085{
2086 pcontext->alpha_overlay_drawn = paint_draw_alpha_overlay(pcontext->ups,
2087 pcontext->brush,
2088 &pcontext->vc,
2089 pcontext->x,
2090 pcontext->y,
2091 pcontext->zoomx,
2092 pcontext->mode);
2093}
2094
2096{
2097 UnifiedPaintSettings *ups = pcontext->ups;
2098 if (ups->draw_anchored) {
2099 pcontext->final_radius = ups->anchored_size;
2100 copy_v2_fl2(pcontext->translation,
2101 ups->anchored_initial_mouse[0] + pcontext->region->winrct.xmin,
2102 ups->anchored_initial_mouse[1] + pcontext->region->winrct.ymin);
2103 }
2104}
2105
2115
2125
2132
2133static void paint_draw_cursor(bContext *C, int x, int y, void * /*unused*/)
2134{
2135 PaintCursorContext pcontext;
2136 if (!paint_cursor_context_init(C, x, y, &pcontext)) {
2137 return;
2138 }
2139
2140 if (!paint_cursor_is_brush_cursor_enabled(&pcontext)) {
2141 /* For Grease Pencil draw mode, we want to we only render a small mouse cursor (dot) if the
2142 * paint cursor is disabled so that the default mouse cursor doesn't get in the way of tablet
2143 * users. See #130089. */
2144 if (pcontext.mode == PaintMode::GPencil) {
2145 WM_cursor_set(pcontext.win, WM_CURSOR_DOT);
2146 }
2147 return;
2148 }
2149 if (paint_cursor_is_3d_view_navigating(&pcontext)) {
2150 return;
2151 }
2152
2153 switch (pcontext.cursor_type) {
2154 case PAINT_CURSOR_CURVE:
2155 paint_draw_curve_cursor(pcontext.brush, &pcontext.vc);
2156 break;
2157 case PAINT_CURSOR_2D:
2158 paint_update_mouse_cursor(&pcontext);
2159
2163
2167 break;
2168 case PAINT_CURSOR_3D:
2169 paint_update_mouse_cursor(&pcontext);
2170
2174
2178 break;
2179 }
2180}
2181
2182} // namespace blender::ed::sculpt_paint
2183
2184/* Public API */
2185
2186void ED_paint_cursor_start(Paint *paint, bool (*poll)(bContext *C))
2187{
2188 if (paint && !paint->paint_cursor) {
2191 }
2192
2193 /* Invalidate the paint cursors. */
2195}
float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1133
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1075
void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojected_radius)
Definition brush.cc:1120
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
Definition brush.cc:1059
bool BKE_brush_use_size_pressure(const Brush *brush)
Definition brush.cc:1091
bool BKE_brush_sculpt_has_secondary_color(const Brush *brush)
Definition brush.cc:1101
const float * BKE_brush_color_get(const Scene *scene, const Paint *paint, const Brush *brush)
Definition brush.cc:1029
bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
Definition brush.cc:1083
float BKE_brush_curve_strength_clamped(const Brush *br, float p, float len)
Definition brush.cc:1444
void BKE_curvemapping_init(CurveMapping *cumap)
wmWindow * CTX_wm_window(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition curve.cc:1663
Low-level operations for grease pencil.
Material * BKE_grease_pencil_object_material_from_brush_get(Object *ob, Brush *brush)
void BKE_image_pool_free(ImagePool *pool)
ImBuf * BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool)
void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool)
ImagePool * BKE_image_pool_new(void)
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh_no_subsurf(const Object *object_eval)
PaintMode
Definition BKE_paint.hh:99
@ SculptGreasePencil
Definition BKE_paint.hh:116
ePaintOverlayControlFlags BKE_paint_get_overlay_flags()
Definition paint.cc:292
ePaintOverlayControlFlags
Definition BKE_paint.hh:123
@ PAINT_OVERLAY_INVALID_CURVE
Definition BKE_paint.hh:126
@ PAINT_OVERLAY_INVALID_TEXTURE_SECONDARY
Definition BKE_paint.hh:125
@ PAINT_OVERLAY_OVERRIDE_CURSOR
Definition BKE_paint.hh:127
@ PAINT_OVERLAY_INVALID_TEXTURE_PRIMARY
Definition BKE_paint.hh:124
@ PAINT_OVERLAY_OVERRIDE_SECONDARY
Definition BKE_paint.hh:129
@ PAINT_OVERLAY_OVERRIDE_PRIMARY
Definition BKE_paint.hh:128
void BKE_paint_reset_overlay_invalid(ePaintOverlayControlFlags flag)
Definition paint.cc:315
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2601
Paint * BKE_paint_get_active_from_context(const bContext *C)
Definition paint.cc:477
Brush * BKE_paint_brush(Paint *paint)
Definition paint.cc:649
bool paint_calculate_rake_rotation(UnifiedPaintSettings &ups, const Brush &brush, const float mouse_pos[2], PaintMode paint_mode, bool stroke_has_started)
Definition paint.cc:2005
PaintMode BKE_paintmode_get_active_from_context(const bContext *C)
Definition paint.cc:506
void BKE_paint_invalidate_overlay_all()
Definition paint.cc:286
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_INLINE
MINLINE float max_ff(float a, float b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE int max_ii(int a, int b)
#define M_PI
void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
void unit_m4(float m[4][4])
Definition rct.c:1127
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void rotate_m4(float mat[4][4], char axis, float angle)
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
void quat_to_mat4(float m[4][4], const float q[4])
#define RAD2DEGF(_rad)
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_fl2(float v[2], float x, float y)
MINLINE void clamp_v4(float vec[4], float min, float max)
MINLINE float len_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_v3_int(int r[3], const int a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE float normalize_v3(float n[3])
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:193
bool BLI_rcti_isect_pt(const struct rcti *rect, int x, int y)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
unsigned char uchar
unsigned int uint
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
int BLI_task_parallel_thread_id(const TaskParallelTLS *tls)
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:230
#define CLAMP(a, b, c)
#define UNPACK3(a)
#define ELEM(...)
@ GPAINT_BRUSH_TYPE_TINT
@ GPAINT_BRUSH_TYPE_FILL
@ GPAINT_BRUSH_TYPE_DRAW
@ GPAINT_BRUSH_TYPE_ERASE
@ SCULPT_BRUSH_TYPE_GRAB
@ SCULPT_BRUSH_TYPE_BOUNDARY
@ SCULPT_BRUSH_TYPE_CLOTH
@ SCULPT_BRUSH_TYPE_POSE
@ SCULPT_BRUSH_TYPE_MULTIPLANE_SCRAPE
@ SCULPT_BRUSH_TYPE_LAYER
@ BRUSH_CURVE
@ BRUSH_GRAB_ACTIVE_VERTEX
@ BRUSH_SMOOTH_STROKE
@ BRUSH_DIR_IN
@ BRUSH_ANCHORED
@ BRUSH_LOCK_SIZE
@ IMAGE_PAINT_BRUSH_TYPE_FILL
@ IMAGE_PAINT_BRUSH_TYPE_DRAW
@ PAINT_FALLOFF_SHAPE_SPHERE
@ PAINT_FALLOFF_SHAPE_TUBE
@ BRUSH_OVERLAY_SECONDARY
@ BRUSH_OVERLAY_CURSOR
@ BRUSH_OVERLAY_PRIMARY
@ BRUSH_CLOTH_FORCE_FALLOFF_RADIAL
@ BRUSH_CLOTH_FORCE_FALLOFF_PLANE
@ GPPAINT_MODE_STROKE
@ GPPAINT_MODE_BOTH
@ BRUSH_CLOTH_SIMULATION_AREA_LOCAL
@ BRUSH_CLOTH_SIMULATION_AREA_GLOBAL
Object is a sort of wrapper for general info.
@ OB_GREASE_PENCIL
@ OB_MESH
ePaintSymmetryFlags
@ PAINT_TILE_X
@ PAINT_SHOW_BRUSH
@ RGN_TYPE_WINDOW
#define RGN_TYPE_ANY
@ SPACE_VIEW3D
#define SPACE_TYPE_ANY
@ MTEX_MAP_MODE_STENCIL
@ MTEX_MAP_MODE_TILED
@ MTEX_MAP_MODE_VIEW
@ TEX_IMAGE
@ RV3D_NAVIGATING
void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float r_out[3])
@ V3D_PROJ_TEST_NOP
Definition ED_view3d.hh:275
@ V3D_PROJ_RET_OK
Definition ED_view3d.hh:252
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
void ED_view3d_draw_setup_view(const wmWindowManager *wm, wmWindow *win, Depsgraph *depsgraph, Scene *scene, ARegion *region, View3D *v3d, const float viewmat[4][4], const float winmat[4][4], const rcti *rect)
void ED_view3d_project_v3(const ARegion *region, const float world[3], float r_region_co[3])
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
static AppView * view
void immEnd()
void immUnbindProgram()
void immUniform2f(const char *name, float x, float y)
void immUniformColor4f(float r, float g, float b, float a)
void immBindTextureSampler(const char *name, GPUTexture *tex, GPUSamplerState state)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex2fv(uint attr_id, const float data[2])
void immUniform1i(const char *name, int x)
void immUniform1f(const char *name, float x)
void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
GPUVertFormat * immVertexFormat()
void immUniformColor4fv(const float rgba[4])
void immAttr2f(uint attr_id, float x, float y)
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immUniformColor3fvAlpha(const float rgb[3], float a)
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2)
void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments)
void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegments)
void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
void GPU_matrix_translate_2fv(const float vec[2])
void GPU_matrix_scale_2f(float x, float y)
void GPU_matrix_push()
void GPU_matrix_push_projection()
#define GPU_matrix_mul(x)
void GPU_matrix_scale_1f(float factor)
void GPU_matrix_rotate_2d(float deg)
void GPU_matrix_pop_projection()
void GPU_matrix_pop()
void GPU_matrix_translate_2f(float x, float y)
@ GPU_PRIM_TRI_FAN
@ GPU_PRIM_LINE_LOOP
@ GPU_PRIM_LINES
@ GPU_PRIM_LINE_STRIP
@ GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_3D_IMAGE_COLOR
eGPUBlend
Definition GPU_state.hh:84
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
@ GPU_BLEND_ALPHA_PREMULT
Definition GPU_state.hh:88
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_line_width(float width)
Definition gpu_state.cc:161
eGPUBlend GPU_blend_get()
Definition gpu_state.cc:221
void GPU_line_smooth(bool enable)
Definition gpu_state.cc:78
eGPUDepthTest GPU_depth_test_get()
Definition gpu_state.cc:239
void GPU_color_mask(bool r, bool g, bool b, bool a)
Definition gpu_state.cc:98
eGPUDepthTest
Definition GPU_state.hh:107
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:111
@ GPU_DEPTH_NONE
Definition GPU_state.hh:108
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:262
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
void GPU_texture_unbind(GPUTexture *texture)
@ GPU_DATA_UBYTE
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
GPUSamplerExtendMode
@ GPU_SAMPLER_EXTEND_MODE_REPEAT
@ GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER
eGPUTextureFormat
@ GPU_R8
@ GPU_SAMPLER_FILTERING_LINEAR
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
void GPU_texture_swizzle_set(GPUTexture *texture, const char swizzle[4])
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace)
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its red
void ntreeTexEndExecTree(struct bNodeTreeExec *exec)
struct bNodeTreeExec * ntreeTexBeginExecTree(struct bNodeTree *ntree)
#define C
Definition RandGen.cpp:29
@ TH_PAINT_CURVE_HANDLE
@ TH_VERTEX_SELECT
@ TH_PAINT_CURVE_PIVOT
void UI_GetThemeColorType4fv(int colorid, int spacetype, float col[4])
#define U
ATTR_WARN_UNUSED_RESULT BMesh * bm
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
int64_t size() const
Definition BLI_array.hh:245
bool is_empty() const
Definition BLI_array.hh:253
local_group_size(16, 16) .push_constant(Type texture
#define sinf(x)
#define cosf(x)
#define atan2f(x, y)
#define fabsf(x)
#define sqrtf(x)
int len
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
RAYTRACE_GROUP_SIZE additional_info("eevee_shared", "eevee_gbuffer_data", "eevee_global_ubo", "eevee_sampling_data", "eevee_utility_texture", "eevee_hiz_data", "draw_view") .specialization_constant(Type RAYTRACE_GROUP_SIZE in_sh_0_tx in_sh_2_tx screen_normal_tx GPU_RGBA8
blender::gpu::Batch * quad
uint col
format
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
pbvh::Tree & pbvh_ensure(Depsgraph &depsgraph, Object &object)
Definition paint.cc:2811
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2482
void pivot_line_preview_draw(const uint gpuattr, SculptSession &ss)
std::unique_ptr< SculptBoundaryPreview > preview_data_init(const Depsgraph &depsgraph, Object &object, const Brush *brush, const float radius)
void edges_preview_draw(const uint gpuattr, SculptSession &ss, const float outline_col[3], const float outline_alpha)
void plane_falloff_preview_draw(const uint gpuattr, SculptSession &ss, const float outline_col[3], float outline_alpha)
void simulation_limits_draw(const uint gpuattr, const Brush &brush, const float location[3], const float normal[3], const float rds, const float line_width, const float outline_col[3], const float alpha)
bool brush_using_vertex_color(const GpPaint *gp_paint, const Brush *brush)
std::unique_ptr< SculptPoseIKChainPreview > preview_ik_chain_init(const Depsgraph &depsgraph, Object &ob, SculptSession &ss, const Brush &brush, const float3 &initial_location, const float radius)
static void paint_cursor_preview_boundary_data_update(PaintCursorContext *pcontext)
static void paint_cursor_update_unprojected_radius(UnifiedPaintSettings &ups, Brush &brush, ViewContext &vc, const float location[3])
static void load_tex_cursor_task_cb(void *__restrict userdata, const int j, const TaskParallelTLS *__restrict)
static bool paint_use_2d_cursor(PaintMode mode)
static void paint_cursor_pose_brush_segments_draw(PaintCursorContext *pcontext)
static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom, const PaintMode mode, bool col, bool primary)
static void SCULPT_layer_brush_height_preview_draw(const uint gpuattr, const Brush &brush, const float rds, const float line_width, const float outline_col[3], const float alpha)
static void load_tex_task_cb_ex(void *__restrict userdata, const int j, const TaskParallelTLS *__restrict tls)
static void grease_pencil_eraser_draw(PaintCursorContext *pcontext)
static void paint_draw_cursor(bContext *C, int x, int y, void *)
static void paint_cursor_pose_brush_origins_draw(PaintCursorContext *pcontext)
static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool col, float zoom)
static void sculpt_geometry_preview_lines_draw(const Depsgraph &depsgraph, const uint gpuattr, const Brush &brush, const Object &object)
static void paint_draw_legacy_3D_view_brush_cursor(PaintCursorContext *pcontext)
static void make_tex_snap(TexSnapshot *snap, ViewContext *vc, float zoom)
static void paint_draw_2D_view_brush_cursor_default(PaintCursorContext *pcontext)
static void paint_cursor_update_rake_rotation(PaintCursorContext *pcontext)
static void cursor_draw_point_screen_space(const uint gpuattr, const ARegion *region, const float true_location[3], const float obmat[4][4], const int size)
float3 symmetry_flip(const float3 &src, const ePaintSymmetryFlags symm)
static void grease_pencil_brush_cursor_draw(PaintCursorContext *pcontext)
static void paint_cursor_restore_drawing_state()
static void paint_draw_3D_view_inactive_brush_cursor(PaintCursorContext *pcontext)
static void cursor_draw_tiling_preview(const uint gpuattr, const ARegion *region, const float true_location[3], const Sculpt &sd, const Object &ob, const float radius)
BLI_INLINE void draw_bezier_handle_lines(uint pos, const float sel_col[4], BezTriple *bez)
static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *pcontext)
BLI_INLINE void draw_tri_point(uint pos, const float sel_col[4], const float pivot_col[4], float *co, float width, bool selected)
BLI_INLINE void draw_rect_point(uint pos, const float sel_col[4], const float handle_col[4], const float *co, float width, bool selected)
static void paint_cursor_setup_3D_drawing(PaintCursorContext *pcontext)
static void paint_draw_2D_view_brush_cursor(PaintCursorContext *pcontext)
static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom, PaintMode mode)
static void paint_cursor_preview_boundary_data_pivot_draw(PaintCursorContext *pcontext)
static void paint_cursor_cursor_draw_3d_view_brush_cursor_active(PaintCursorContext *pcontext)
static void paint_cursor_update_object_space_radius(PaintCursorContext *pcontext)
static void paint_cursor_sculpt_session_update_and_init(PaintCursorContext *pcontext)
static void paint_update_mouse_cursor(PaintCursorContext *pcontext)
static bool paint_cursor_is_3d_view_navigating(PaintCursorContext *pcontext)
static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool primary)
static void cursor_draw_point_with_symmetry(const uint gpuattr, const ARegion *region, const float true_location[3], const Sculpt &sd, const Object &ob, const float radius)
static void paint_cursor_check_and_draw_alpha_overlays(PaintCursorContext *pcontext)
static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc)
static bool paint_cursor_context_init(bContext *C, const int x, const int y, PaintCursorContext *pcontext)
static void paint_cursor_update_pixel_radius(PaintCursorContext *pcontext)
static int project_brush_radius(ViewContext *vc, float radius, const float location[3])
static void paint_cursor_draw_main_inactive_cursor(PaintCursorContext *pcontext)
void multiplane_scrape_preview_draw(const uint gpuattr, const Brush &brush, const SculptSession &ss, const float outline_col[3], const float outline_alpha)
static void paint_cursor_drawing_setup_cursor_space(PaintCursorContext *pcontext)
static void paint_cursor_setup_2D_drawing(PaintCursorContext *pcontext)
bool paint_brush_tool_poll(bContext *C)
static void paint_cursor_draw_3D_view_brush_cursor(PaintCursorContext *pcontext)
static void paint_cursor_update_anchored_location(PaintCursorContext *pcontext)
static bool paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom)
void geometry_preview_lines_update(Depsgraph &depsgraph, Object &object, SculptSession &ss, float radius)
Definition grab.cc:227
static bool paint_cursor_is_brush_cursor_enabled(PaintCursorContext *pcontext)
Span< float3 > vert_positions_for_grab_active_get(const Depsgraph &depsgraph, const Object &object)
Definition sculpt.cc:171
VecBase< float, 4 > float4
VecBase< float, 2 > float2
VecBase< float, 3 > float3
vector snap(vector a, vector b)
Definition node_math.h:65
static void init(bNodeTree *, bNode *node)
static ePaintOverlayControlFlags overlay_flags
Definition paint.cc:251
void paint_cursor_delete_textures()
static CursorSnapshot cursor_snap
static TexSnapshot primary_snap
static TexSnapshot secondary_snap
void ED_paint_cursor_start(Paint *paint, bool(*poll)(bContext *C))
bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
float paint_calc_object_space_radius(const ViewContext &vc, const blender::float3 &center, float pixel_radius)
#define PAINT_CURVE_NUM_SEGMENTS
bool paint_get_tex_pixel(const MTex *mtex, float u, float v, ImagePool *pool, int thread, float *r_intensity, float r_rgba[4])
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(const blender::ed::sculpt_paint::StrokeCache &cache)
Definition sculpt.cc:513
ePaintSymmetryFlags SCULPT_mesh_symmetry_xyz_get(const Object &object)
Definition sculpt.cc:186
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mval[2], bool use_sampled_normal)
Definition sculpt.cc:4580
void SCULPT_vertex_random_access_ensure(Object &object)
Definition sculpt.cc:144
float co[3]
float vec[3][3]
float alpha
char sculpt_brush_type
int mask_overlay_alpha
float add_col[4]
struct MTex mtex
float stencil_pos[2]
int texture_overlay_alpha
float unprojected_radius
float stencil_dimension[2]
int cursor_overlay_alpha
char image_brush_type
int curve_preset
struct CurveMapping * curve
float texture_sample_bias
char falloff_shape
float mask_stencil_pos[2]
float rgb[3]
struct BrushGpencilSettings * gpencil_settings
float cloth_sim_limit
float height
float sub_col[4]
struct MTex mask_mtex
float mask_stencil_dimension[2]
int cloth_simulation_area_type
char gpencil_brush_type
struct PaintCurve * paint_curve
int cloth_force_falloff_type
int overlay_flags
GPUTexture * overlay_texture
GreasePencilRuntimeHandle * runtime
ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
char brush_map_mode
struct Tex * tex
struct SculptSession * sculpt
PaintCurvePoint * points
float tile_offset[3]
int symmetry_flags
void * paint_cursor
struct ToolSettings * toolsettings
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:427
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
std::unique_ptr< SculptBoundaryPreview > boundary_preview
Definition BKE_paint.hh:456
bool draw_faded_cursor
Definition BKE_paint.hh:438
blender::Array< int > preview_verts
Definition BKE_paint.hh:450
ActiveVert active_vert() const
Definition paint.cc:2180
blender::float3 active_vert_position(const Depsgraph &depsgraph, const Object &object) const
Definition paint.cc:2224
std::unique_ptr< SculptPoseIKChainPreview > pose_ik_chain_preview
Definition BKE_paint.hh:453
blender::ed::sculpt_paint::expand::Cache * expand_cache
Definition BKE_paint.hh:429
int active_vert_index() const
Definition paint.cc:2190
bool deform_modifiers_active
Definition BKE_paint.hh:411
int radial_symm[3]
blender::Array< blender::float3 > positions
GPUTexture * overlay_texture
struct ImageUser iuser
struct bNodeTree * nodetree
struct Image * ima
struct UnifiedPaintSettings unified_paint_settings
RegionView3D * rv3d
Definition ED_view3d.hh:76
ARegion * region
Definition ED_view3d.hh:73
Scene * scene
Definition ED_view3d.hh:69
View3D * v3d
Definition ED_view3d.hh:74
Object * obact
Definition ED_view3d.hh:71
bNodeTreeRuntimeHandle * runtime
VecBase< T, 3 > xyz() const
int ymin
int xmin
void WM_cursor_set(wmWindow *win, int curs)
@ WM_CURSOR_PAINT
Definition wm_cursors.hh:27
@ WM_CURSOR_DOT
Definition wm_cursors.hh:28
wmPaintCursor * WM_paint_cursor_activate(short space_type, short region_type, bool(*poll)(bContext *C), wmPaintCursorDraw draw, void *customdata)
void wmViewport(const rcti *winrct)
void wmWindowViewport(const wmWindow *win)