Blender V4.3
brush.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#include <array>
9#include <optional>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_ID.h"
14#include "DNA_brush_types.h"
15#include "DNA_defaults.h"
16#include "DNA_material_types.h"
17#include "DNA_scene_types.h"
18
19#include "BLI_listbase.h"
20#include "BLI_math_base.hh"
21#include "BLI_math_rotation.h"
22#include "BLI_rand.h"
23
24#include "BLT_translation.hh"
25
26#include "BKE_asset.hh"
27#include "BKE_bpath.hh"
28#include "BKE_brush.hh"
29#include "BKE_colortools.hh"
30#include "BKE_gpencil_legacy.h"
31#include "BKE_grease_pencil.hh"
32#include "BKE_idprop.hh"
33#include "BKE_idtype.hh"
34#include "BKE_lib_id.hh"
35#include "BKE_lib_query.hh"
36#include "BKE_lib_remap.hh"
37#include "BKE_main.hh"
38#include "BKE_material.h"
39#include "BKE_paint.hh"
40#include "BKE_preview_image.hh"
41#include "BKE_texture.h"
42
44#include "IMB_imbuf.hh"
45#include "IMB_imbuf_types.hh"
46
47#include "RE_texture.h" /* RE_texture_evaluate */
48
49#include "BLO_read_write.hh"
50
51static void brush_init_data(ID *id)
52{
53 Brush *brush = (Brush *)id;
55
57
58 /* enable fake user by default */
59 id_fake_user_set(&brush->id);
60
61 /* the default alpha falloff curve */
63}
64
65static void brush_copy_data(Main * /*bmain*/,
66 std::optional<Library *> /*owner_library*/,
67 ID *id_dst,
68 const ID *id_src,
69 const int flag)
70{
71 Brush *brush_dst = (Brush *)id_dst;
72 const Brush *brush_src = (const Brush *)id_src;
73 if (brush_src->icon_imbuf) {
74 brush_dst->icon_imbuf = IMB_dupImBuf(brush_src->icon_imbuf);
75 }
76
77 if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
78 BKE_previewimg_id_copy(&brush_dst->id, &brush_src->id);
79 }
80 else {
81 brush_dst->preview = nullptr;
82 }
83
84 brush_dst->curve = BKE_curvemapping_copy(brush_src->curve);
86
87 if (brush_src->gpencil_settings != nullptr) {
88 brush_dst->gpencil_settings = MEM_cnew<BrushGpencilSettings>(__func__,
89 *(brush_src->gpencil_settings));
95 brush_src->gpencil_settings->curve_jitter);
96
102 brush_src->gpencil_settings->curve_rand_uv);
104 brush_src->gpencil_settings->curve_rand_hue);
109 }
110 if (brush_src->curves_sculpt_settings != nullptr) {
111 brush_dst->curves_sculpt_settings = MEM_cnew<BrushCurvesSculptSettings>(
112 __func__, *(brush_src->curves_sculpt_settings));
115 }
116
117 /* enable fake user by default */
118 id_fake_user_set(&brush_dst->id);
119}
120
153
154static void brush_make_local(Main *bmain, ID *id, const int flags)
155{
156 if (!ID_IS_LINKED(id)) {
157 return;
158 }
159
160 Brush *brush = (Brush *)id;
161 const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0;
162
163 bool force_local, force_copy;
164 BKE_lib_id_make_local_generic_action_define(bmain, id, flags, &force_local, &force_copy);
165
166 if (brush->clone.image) {
167 /* Special case: `ima` always local immediately.
168 * Clone image should only have one user anyway. */
169 /* FIXME: Recursive calls affecting other non-embedded IDs are really bad and should be avoided
170 * in IDType callbacks. Higher-level ID management code usually does not expect such things and
171 * does not deal properly with it. */
172 /* NOTE: assert below ensures that the comment above is valid, and that exception is
173 * acceptable for the time being. */
175 BLI_assert(!ID_IS_LINKED(brush->clone.image) && brush->clone.image->id.newid == nullptr);
176 }
177
178 if (force_local) {
179 BKE_lib_id_clear_library_data(bmain, &brush->id, flags);
180 BKE_lib_id_expand_local(bmain, &brush->id, flags);
181
182 /* enable fake user by default */
183 id_fake_user_set(&brush->id);
184 }
185 else if (force_copy) {
186 Brush *brush_new = (Brush *)BKE_id_copy(bmain, &brush->id); /* Ensures FAKE_USER is set */
187
188 brush_new->id.us = 0;
189
190 /* setting newid is mandatory for complex make_lib_local logic... */
191 ID_NEW_SET(brush, brush_new);
192
193 if (!lib_local) {
194 BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE);
195 }
196 }
197}
198
214
215static void brush_foreach_path(ID *id, BPathForeachPathData *bpath_data)
216{
217 Brush *brush = (Brush *)id;
218 if (brush->icon_filepath[0] != '\0') {
220 bpath_data, brush->icon_filepath, sizeof(brush->icon_filepath));
221 }
222}
223
224static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
225{
226 Brush *brush = (Brush *)id;
227
228 BLO_write_id_struct(writer, Brush, id_address, &brush->id);
229 BKE_id_blend_write(writer, &brush->id);
230
231 if (brush->curve) {
232 BKE_curvemapping_blend_write(writer, brush->curve);
233 }
234
235 if (brush->automasking_cavity_curve) {
237 }
238
239 if (brush->gpencil_settings) {
241
244 }
245 if (brush->gpencil_settings->curve_strength) {
247 }
248 if (brush->gpencil_settings->curve_jitter) {
250 }
253 }
256 }
257 if (brush->gpencil_settings->curve_rand_uv) {
259 }
260 if (brush->gpencil_settings->curve_rand_hue) {
262 }
265 }
268 }
269 }
270 if (brush->curves_sculpt_settings) {
273 }
274 if (brush->gradient) {
275 BLO_write_struct(writer, ColorBand, brush->gradient);
276 }
277
278 BKE_previewimg_blend_write(writer, brush->preview);
279}
280
281static void brush_blend_read_data(BlendDataReader *reader, ID *id)
282{
283 Brush *brush = (Brush *)id;
284
285 /* Falloff curve. */
286 BLO_read_struct(reader, CurveMapping, &brush->curve);
287
288 BLO_read_struct(reader, ColorBand, &brush->gradient);
289
290 if (brush->curve) {
291 BKE_curvemapping_blend_read(reader, brush->curve);
292 }
293 else {
295 }
296
298 if (brush->automasking_cavity_curve) {
300 }
301 else {
303 }
304
305 /* grease pencil */
307 if (brush->gpencil_settings != nullptr) {
311
318
321 }
322
323 if (brush->gpencil_settings->curve_strength) {
325 }
326
327 if (brush->gpencil_settings->curve_jitter) {
329 }
330
333 }
334
337 }
338
339 if (brush->gpencil_settings->curve_rand_uv) {
341 }
342
343 if (brush->gpencil_settings->curve_rand_hue) {
345 }
346
349 }
350
353 }
354 }
355
357 if (brush->curves_sculpt_settings) {
361 }
362 }
363
364 BLO_read_struct(reader, PreviewImage, &brush->preview);
365 BKE_previewimg_blend_read(reader, brush->preview);
366
367 brush->icon_imbuf = nullptr;
368 brush->has_unsaved_changes = false;
369}
370
372{
373 Brush *brush = reinterpret_cast<Brush *>(id);
374
375 /* Update brush settings depending on availability of other IDs. */
376 if (brush->gpencil_settings != nullptr) {
378 if (!brush->gpencil_settings->material) {
380 }
381 }
382 else {
383 brush->gpencil_settings->material = nullptr;
384 }
385 }
386}
387
388static void brush_asset_metadata_ensure(void *asset_ptr, AssetMetaData *asset_data)
389{
390 using namespace blender;
391 using namespace blender::bke;
392
393 Brush *brush = reinterpret_cast<Brush *>(asset_ptr);
394 BLI_assert(GS(brush->id.name) == ID_BR);
395
396 /* Most names copied from brush RNA (not all are available there though). */
397 constexpr std::array mode_map{
398 std::tuple{"use_paint_sculpt", OB_MODE_SCULPT, "sculpt_brush_type"},
399 std::tuple{"use_paint_vertex", OB_MODE_VERTEX_PAINT, "vertex_brush_type"},
400 std::tuple{"use_paint_weight", OB_MODE_WEIGHT_PAINT, "weight_brush_type"},
401 std::tuple{"use_paint_image", OB_MODE_TEXTURE_PAINT, "image_brush_type"},
402 /* Sculpt UVs in the image editor while in edit mode. */
403 std::tuple{"use_paint_uv_sculpt", OB_MODE_EDIT, "image_brush_type"},
404 std::tuple{"use_paint_grease_pencil", OB_MODE_PAINT_GREASE_PENCIL, "gpencil_brush_type"},
405 /* Note: Not defined in brush RNA, own name. */
406 std::tuple{
407 "use_sculpt_grease_pencil", OB_MODE_SCULPT_GREASE_PENCIL, "gpencil_sculpt_brush_type"},
408 std::tuple{
409 "use_vertex_grease_pencil", OB_MODE_VERTEX_GREASE_PENCIL, "gpencil_vertex_brush_type"},
410 std::tuple{"use_weight_gpencil", OB_MODE_WEIGHT_GREASE_PENCIL, "gpencil_weight_brush_type"},
411 std::tuple{"use_paint_sculpt_curves", OB_MODE_SCULPT_CURVES, "curves_sculpt_brush_type"},
412 };
413
414 for (const auto &[prop_name, mode, tool_prop_name] : mode_map) {
415 /* Only add booleans for supported modes. */
416 if (!(brush->ob_mode & mode)) {
417 continue;
418 }
419 auto mode_property = idprop::create_bool(prop_name, true);
420 BKE_asset_metadata_idprop_ensure(asset_data, mode_property.release());
421
422 if (std::optional<int> brush_tool = BKE_paint_get_brush_type_from_obmode(brush, mode)) {
423 auto type_property = idprop::create(tool_prop_name, *brush_tool);
424 BKE_asset_metadata_idprop_ensure(asset_data, type_property.release());
425 }
426 else {
428 }
429 }
430}
431
433 /*pre_save_fn*/ brush_asset_metadata_ensure,
434 /*on_mark_asset_fn*/ brush_asset_metadata_ensure,
435};
436
438 /*id_code*/ ID_BR,
439 /*id_filter*/ FILTER_ID_BR,
440 /*dependencies_id_types*/
442 /*main_listbase_index*/ INDEX_ID_BR,
443 /*struct_size*/ sizeof(Brush),
444 /*name*/ "Brush",
445 /*name_plural*/ N_("brushes"),
446 /*translation_context*/ BLT_I18NCONTEXT_ID_BRUSH,
448 /*asset_type_info*/ &AssetType_BR,
449
450 /*init_data*/ brush_init_data,
451 /*copy_data*/ brush_copy_data,
452 /*free_data*/ brush_free_data,
453 /*make_local*/ brush_make_local,
454 /*foreach_id*/ brush_foreach_id,
455 /*foreach_cache*/ nullptr,
456 /*foreach_path*/ brush_foreach_path,
457 /*owner_pointer_get*/ nullptr,
458
459 /*blend_write*/ brush_blend_write,
460 /*blend_read_data*/ brush_blend_read_data,
461 /*blend_read_after_liblink*/ brush_blend_read_after_liblink,
462
463 /*blend_read_undo_preserve*/ nullptr,
464
465 /*lib_override_apply_post*/ nullptr,
466};
467
469
471{
473 BLI_rng_srandom(brush_rng, 31415682);
474}
475
477{
478 if (brush_rng == nullptr) {
479 return;
480 }
482 brush_rng = nullptr;
483}
484
485static void brush_defaults(Brush *brush)
486{
487
488 const Brush *brush_def = DNA_struct_default_get(Brush);
489
490#define FROM_DEFAULT(member) \
491 memcpy((void *)&brush->member, (void *)&brush_def->member, sizeof(brush->member))
492#define FROM_DEFAULT_PTR(member) memcpy(brush->member, brush_def->member, sizeof(brush->member))
493
496 FROM_DEFAULT(weight);
498 FROM_DEFAULT(alpha);
499 FROM_DEFAULT(hardness);
500 FROM_DEFAULT(autosmooth_factor);
501 FROM_DEFAULT(topology_rake_factor);
502 FROM_DEFAULT(crease_pinch_factor);
503 FROM_DEFAULT(normal_radius_factor);
504 FROM_DEFAULT(wet_paint_radius_factor);
505 FROM_DEFAULT(area_radius_factor);
506 FROM_DEFAULT(disconnected_distance_max);
507 FROM_DEFAULT(sculpt_plane);
508 FROM_DEFAULT(plane_offset);
509 FROM_DEFAULT(clone.alpha);
510 FROM_DEFAULT(normal_weight);
511 FROM_DEFAULT(fill_threshold);
513 FROM_DEFAULT(sampling_flag);
514 FROM_DEFAULT_PTR(rgb);
515 FROM_DEFAULT_PTR(secondary_rgb);
516 FROM_DEFAULT(spacing);
517 FROM_DEFAULT(smooth_stroke_radius);
518 FROM_DEFAULT(smooth_stroke_factor);
519 FROM_DEFAULT(rate);
520 FROM_DEFAULT(jitter);
521 FROM_DEFAULT(texture_sample_bias);
522 FROM_DEFAULT(texture_overlay_alpha);
523 FROM_DEFAULT(mask_overlay_alpha);
524 FROM_DEFAULT(cursor_overlay_alpha);
526 FROM_DEFAULT_PTR(add_col);
527 FROM_DEFAULT_PTR(sub_col);
528 FROM_DEFAULT(stencil_pos);
529 FROM_DEFAULT(stencil_dimension);
530 FROM_DEFAULT(mtex);
531 FROM_DEFAULT(mask_mtex);
532 FROM_DEFAULT(falloff_shape);
533 FROM_DEFAULT(tip_scale_x);
534 FROM_DEFAULT(tip_roundness);
535
536#undef FROM_DEFAULT
537#undef FROM_DEFAULT_PTR
538}
539
540/* Datablock add/copy/free/make_local */
541
542Brush *BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
543{
544 Brush *brush = (Brush *)BKE_id_new(bmain, ID_BR, name);
545
546 brush->ob_mode = ob_mode;
547
548 if (ob_mode == OB_MODE_SCULPT_CURVES) {
550 }
551 else if (ELEM(ob_mode,
556 {
558 }
559
560 return brush;
561}
562
564{
565 if (brush->gpencil_settings == nullptr) {
566 brush->gpencil_settings = MEM_cnew<BrushGpencilSettings>("BrushGpencilSettings");
567 }
568
570 brush->gpencil_settings->flag = 0;
572 brush->gpencil_settings->draw_strength = 1.0f;
573 brush->gpencil_settings->draw_jitter = 0.0f;
575
576 /* curves */
577 brush->gpencil_settings->curve_sensitivity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
578 brush->gpencil_settings->curve_strength = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
579 brush->gpencil_settings->curve_jitter = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
580
581 brush->gpencil_settings->curve_rand_pressure = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
582 brush->gpencil_settings->curve_rand_strength = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
583 brush->gpencil_settings->curve_rand_uv = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
584 brush->gpencil_settings->curve_rand_hue = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
585 brush->gpencil_settings->curve_rand_saturation = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
586 brush->gpencil_settings->curve_rand_value = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
587}
588
589bool BKE_brush_delete(Main *bmain, Brush *brush)
590{
591 if (brush->id.tag & ID_TAG_INDIRECT) {
592 return false;
593 }
594 if (ID_REAL_USERS(brush) <= 1 && ID_EXTRA_USERS(brush) == 0 &&
596 {
597 return false;
598 }
599
600 BKE_id_delete(bmain, brush);
601
602 return true;
603}
604
606{
607 if (brush->curves_sculpt_settings == nullptr) {
608 brush->curves_sculpt_settings = MEM_cnew<BrushCurvesSculptSettings>(__func__);
609 }
612 settings->add_amount = 1;
613 settings->points_per_curve = 8;
614 settings->minimum_length = 0.01f;
615 settings->curve_length = 0.3f;
616 settings->curve_radius = 0.01f;
617 settings->density_add_attempts = 100;
618 settings->curve_parameter_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
619}
620
622{
623 if (brush && ID_IS_LINKED(brush)) {
624 brush->has_unsaved_changes = true;
625 }
626}
627
629{
630 LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
631 if (brush->ob_mode & ob_mode) {
632 return brush;
633 }
634 }
635 return nullptr;
636}
637
639{
640 /* create a fake brush and set it to the defaults */
641 Brush def = blender::dna::shallow_zero_initialize();
642 brush_defaults(&def);
643
644#define BR_TEST(field, t) \
645 if (br->field != def.field) { \
646 printf("br->" #field " = %" #t ";\n", br->field); \
647 } \
648 ((void)0)
649
650#define BR_TEST_FLAG(_f) \
651 if ((br->flag & _f) && !(def.flag & _f)) { \
652 printf("br->flag |= " #_f ";\n"); \
653 } \
654 else if (!(br->flag & _f) && (def.flag & _f)) { \
655 printf("br->flag &= ~" #_f ";\n"); \
656 } \
657 ((void)0)
658
659#define BR_TEST_FLAG_OVERLAY(_f) \
660 if ((br->overlay_flags & _f) && !(def.overlay_flags & _f)) { \
661 printf("br->overlay_flags |= " #_f ";\n"); \
662 } \
663 else if (!(br->overlay_flags & _f) && (def.overlay_flags & _f)) { \
664 printf("br->overlay_flags &= ~" #_f ";\n"); \
665 } \
666 ((void)0)
667
668 /* print out any non-default brush state */
669 BR_TEST(normal_weight, f);
670
671 BR_TEST(blend, d);
672 BR_TEST(size, d);
673
674 /* br->flag */
698
705
706 BR_TEST(jitter, f);
707 BR_TEST(spacing, d);
708 BR_TEST(smooth_stroke_radius, d);
709 BR_TEST(smooth_stroke_factor, f);
710 BR_TEST(rate, f);
711
712 BR_TEST(alpha, f);
713
714 BR_TEST(sculpt_plane, d);
715
716 BR_TEST(plane_offset, f);
717
718 BR_TEST(autosmooth_factor, f);
719
720 BR_TEST(topology_rake_factor, f);
721
722 BR_TEST(crease_pinch_factor, f);
723
724 BR_TEST(plane_trim, f);
725
726 BR_TEST(texture_sample_bias, f);
727 BR_TEST(texture_overlay_alpha, d);
728
729 BR_TEST(add_col[0], f);
730 BR_TEST(add_col[1], f);
731 BR_TEST(add_col[2], f);
732 BR_TEST(add_col[3], f);
733 BR_TEST(sub_col[0], f);
734 BR_TEST(sub_col[1], f);
735 BR_TEST(sub_col[2], f);
736 BR_TEST(sub_col[3], f);
737
738 printf("\n");
739
740#undef BR_TEST
741#undef BR_TEST_FLAG
742}
743
745{
746 CurveMapping *cumap = nullptr;
747 CurveMap *cuma = nullptr;
748
749 if (!b->curve) {
750 b->curve = BKE_curvemapping_add(1, 0, 0, 1, 1);
751 }
752 cumap = b->curve;
754 cumap->preset = preset;
755
756 cuma = b->curve->cm;
758 BKE_curvemapping_changed(cumap, false);
760}
761
762const MTex *BKE_brush_mask_texture_get(const Brush *brush, const eObjectMode object_mode)
763{
764 if (object_mode == OB_MODE_SCULPT) {
765 return &brush->mtex;
766 }
767 return &brush->mask_mtex;
768}
769
770const MTex *BKE_brush_color_texture_get(const Brush *brush, const eObjectMode object_mode)
771{
772 if (object_mode == OB_MODE_SCULPT) {
773 return &brush->mask_mtex;
774 }
775 return &brush->mtex;
776}
777
779 const Brush *br,
780 const MTex *mtex,
781 const float point[3],
782 float rgba[4],
783 const int thread,
784 ImagePool *pool)
785{
787 float intensity = 1.0;
788 bool hasrgb = false;
789
790 if (mtex == nullptr || mtex->tex == nullptr) {
791 intensity = 1;
792 }
793 else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
794 /* Get strength by feeding the vertex
795 * location directly into a texture */
796 hasrgb = RE_texture_evaluate(mtex, point, thread, pool, false, false, &intensity, rgba);
797 }
798 else if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) {
799 float rotation = -mtex->rot;
800 const float point_2d[2] = {point[0], point[1]};
801 float x, y;
802 float co[3];
803
804 x = point_2d[0] - br->stencil_pos[0];
805 y = point_2d[1] - br->stencil_pos[1];
806
807 if (rotation > 0.001f || rotation < -0.001f) {
808 const float angle = atan2f(y, x) + rotation;
809 const float flen = sqrtf(x * x + y * y);
810
811 x = flen * cosf(angle);
812 y = flen * sinf(angle);
813 }
814
815 if (fabsf(x) > br->stencil_dimension[0] || fabsf(y) > br->stencil_dimension[1]) {
816 zero_v4(rgba);
817 return 0.0f;
818 }
819 x /= (br->stencil_dimension[0]);
820 y /= (br->stencil_dimension[1]);
821
822 co[0] = x;
823 co[1] = y;
824 co[2] = 0.0f;
825
826 hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba);
827 }
828 else {
829 float rotation = -mtex->rot;
830 const float point_2d[2] = {point[0], point[1]};
831 float x = 0.0f, y = 0.0f; /* Quite warnings */
832 float invradius = 1.0f; /* Quite warnings */
833 float co[3];
834
835 if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
836 /* keep coordinates relative to mouse */
837
838 rotation -= ups->brush_rotation;
839
840 x = point_2d[0] - ups->tex_mouse[0];
841 y = point_2d[1] - ups->tex_mouse[1];
842
843 /* use pressure adjusted size for fixed mode */
844 invradius = 1.0f / ups->pixel_radius;
845 }
846 else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
847 /* leave the coordinates relative to the screen */
848
849 /* use unadjusted size for tiled mode */
850 invradius = 1.0f / ups->start_pixel_radius;
851
852 x = point_2d[0];
853 y = point_2d[1];
854 }
855 else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) {
856 rotation -= ups->brush_rotation;
857 /* these contain a random coordinate */
858 x = point_2d[0] - ups->tex_mouse[0];
859 y = point_2d[1] - ups->tex_mouse[1];
860
861 invradius = 1.0f / ups->pixel_radius;
862 }
863
864 x *= invradius;
865 y *= invradius;
866
867 /* it is probably worth optimizing for those cases where
868 * the texture is not rotated by skipping the calls to
869 * atan2, sqrtf, sin, and cos. */
870 if (rotation > 0.001f || rotation < -0.001f) {
871 const float angle = atan2f(y, x) + rotation;
872 const float flen = sqrtf(x * x + y * y);
873
874 x = flen * cosf(angle);
875 y = flen * sinf(angle);
876 }
877
878 co[0] = x;
879 co[1] = y;
880 co[2] = 0.0f;
881
882 hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba);
883 }
884
885 intensity += br->texture_sample_bias;
886
887 if (!hasrgb) {
888 rgba[0] = intensity;
889 rgba[1] = intensity;
890 rgba[2] = intensity;
891 rgba[3] = 1.0f;
892 }
893 /* For consistency, sampling always returns color in linear space */
894 else if (ups->do_linear_conversion) {
896 }
897
898 return intensity;
899}
900
902 const Scene *scene, Brush *br, const float point[2], const int thread, ImagePool *pool)
903{
905 MTex *mtex = &br->mask_mtex;
906 float rgba[4], intensity;
907
908 if (!mtex->tex) {
909 return 1.0f;
910 }
912 float rotation = -mtex->rot;
913 const float point_2d[2] = {point[0], point[1]};
914 float x, y;
915 float co[3];
916
917 x = point_2d[0] - br->mask_stencil_pos[0];
918 y = point_2d[1] - br->mask_stencil_pos[1];
919
920 if (rotation > 0.001f || rotation < -0.001f) {
921 const float angle = atan2f(y, x) + rotation;
922 const float flen = sqrtf(x * x + y * y);
923
924 x = flen * cosf(angle);
925 y = flen * sinf(angle);
926 }
927
928 if (fabsf(x) > br->mask_stencil_dimension[0] || fabsf(y) > br->mask_stencil_dimension[1]) {
929 zero_v4(rgba);
930 return 0.0f;
931 }
932 x /= (br->mask_stencil_dimension[0]);
933 y /= (br->mask_stencil_dimension[1]);
934
935 co[0] = x;
936 co[1] = y;
937 co[2] = 0.0f;
938
939 RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba);
940 }
941 else {
942 float rotation = -mtex->rot;
943 const float point_2d[2] = {point[0], point[1]};
944 float x = 0.0f, y = 0.0f; /* Quite warnings */
945 float invradius = 1.0f; /* Quite warnings */
946 float co[3];
947
948 if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
949 /* keep coordinates relative to mouse */
950
951 rotation -= ups->brush_rotation_sec;
952
953 x = point_2d[0] - ups->mask_tex_mouse[0];
954 y = point_2d[1] - ups->mask_tex_mouse[1];
955
956 /* use pressure adjusted size for fixed mode */
957 invradius = 1.0f / ups->pixel_radius;
958 }
959 else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
960 /* leave the coordinates relative to the screen */
961
962 /* use unadjusted size for tiled mode */
963 invradius = 1.0f / ups->start_pixel_radius;
964
965 x = point_2d[0];
966 y = point_2d[1];
967 }
968 else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) {
969 rotation -= ups->brush_rotation_sec;
970 /* these contain a random coordinate */
971 x = point_2d[0] - ups->mask_tex_mouse[0];
972 y = point_2d[1] - ups->mask_tex_mouse[1];
973
974 invradius = 1.0f / ups->pixel_radius;
975 }
976
977 x *= invradius;
978 y *= invradius;
979
980 /* it is probably worth optimizing for those cases where
981 * the texture is not rotated by skipping the calls to
982 * atan2, sqrtf, sin, and cos. */
983 if (rotation > 0.001f || rotation < -0.001f) {
984 const float angle = atan2f(y, x) + rotation;
985 const float flen = sqrtf(x * x + y * y);
986
987 x = flen * cosf(angle);
988 y = flen * sinf(angle);
989 }
990
991 co[0] = x;
992 co[1] = y;
993 co[2] = 0.0f;
994
995 RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba);
996 }
997
998 CLAMP(intensity, 0.0f, 1.0f);
999
1000 switch (br->mask_pressure) {
1002 intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f;
1003 break;
1005 intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value);
1006 break;
1007 default:
1008 break;
1009 }
1010
1011 return intensity;
1012}
1013
1014/* Unified Size / Strength / Color */
1015
1016/* XXX: be careful about setting size and unprojected radius
1017 * because they depend on one another
1018 * these functions do not set the other corresponding value
1019 * this can lead to odd behavior if size and unprojected
1020 * radius become inconsistent.
1021 * the biggest problem is that it isn't possible to change
1022 * unprojected radius because a view context is not
1023 * available. my usual solution to this is to use the
1024 * ratio of change of the size to change the unprojected
1025 * radius. Not completely convinced that is correct.
1026 * In any case, a better solution is needed to prevent
1027 * inconsistency. */
1028
1029const float *BKE_brush_color_get(const Scene *scene, const Paint *paint, const Brush *brush)
1030{
1033 }
1034 return brush->rgb;
1035}
1036
1037const float *BKE_brush_secondary_color_get(const Scene *scene,
1038 const Paint *paint,
1039 const Brush *brush)
1040{
1043 }
1044 return brush->secondary_rgb;
1045}
1046
1047void BKE_brush_color_set(Scene *scene, const Paint *paint, Brush *brush, const float color[3])
1048{
1051 copy_v3_v3(ups->rgb, color);
1052 }
1053 else {
1054 copy_v3_v3(brush->rgb, color);
1056 }
1057}
1058
1059void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
1060{
1062
1063 /* make sure range is sane */
1065
1066 if (ups->flag & UNIFIED_PAINT_SIZE) {
1067 ups->size = size;
1068 }
1069 else {
1070 brush->size = size;
1072 }
1073}
1074
1075int BKE_brush_size_get(const Scene *scene, const Brush *brush)
1076{
1078 int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
1079
1080 return size;
1081}
1082
1083bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
1084{
1085 const short us_flag = scene->toolsettings->unified_paint_settings.flag;
1086
1087 return (us_flag & UNIFIED_PAINT_SIZE) ? (us_flag & UNIFIED_PAINT_BRUSH_LOCK_SIZE) :
1088 (brush->flag & BRUSH_LOCK_SIZE);
1089}
1090
1092{
1093 return brush->flag & BRUSH_SIZE_PRESSURE;
1094}
1095
1097{
1098 return brush->flag & BRUSH_ALPHA_PRESSURE;
1099}
1100
1119
1120void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojected_radius)
1121{
1123
1124 if (ups->flag & UNIFIED_PAINT_SIZE) {
1125 ups->unprojected_radius = unprojected_radius;
1126 }
1127 else {
1128 brush->unprojected_radius = unprojected_radius;
1130 }
1131}
1132
1133float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush)
1134{
1136
1137 return (ups->flag & UNIFIED_PAINT_SIZE) ? ups->unprojected_radius : brush->unprojected_radius;
1138}
1139
1140void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha)
1141{
1143
1144 if (ups->flag & UNIFIED_PAINT_ALPHA) {
1145 ups->alpha = alpha;
1146 }
1147 else {
1148 brush->alpha = alpha;
1150 }
1151}
1152
1153float BKE_brush_alpha_get(const Scene *scene, const Brush *brush)
1154{
1156
1157 return (ups->flag & UNIFIED_PAINT_ALPHA) ? ups->alpha : brush->alpha;
1158}
1159
1160float BKE_brush_weight_get(const Scene *scene, const Brush *brush)
1161{
1163
1164 return (ups->flag & UNIFIED_PAINT_WEIGHT) ? ups->weight : brush->weight;
1165}
1166
1167void BKE_brush_weight_set(const Scene *scene, Brush *brush, float value)
1168{
1170
1171 if (ups->flag & UNIFIED_PAINT_WEIGHT) {
1172 ups->weight = value;
1173 }
1174 else {
1175 brush->weight = value;
1177 }
1178}
1179
1180int BKE_brush_input_samples_get(const Scene *scene, const Brush *brush)
1181{
1183
1184 return (ups->flag & UNIFIED_PAINT_INPUT_SAMPLES) ? ups->input_samples : brush->input_samples;
1185}
1186
1187void BKE_brush_input_samples_set(const Scene *scene, Brush *brush, int value)
1188{
1190
1191 if (ups->flag & UNIFIED_PAINT_INPUT_SAMPLES) {
1192 ups->input_samples = value;
1193 }
1194 else {
1195 brush->input_samples = value;
1197 }
1198}
1199
1200void BKE_brush_scale_unprojected_radius(float *unprojected_radius,
1201 int new_brush_size,
1202 int old_brush_size)
1203{
1204 float scale = new_brush_size;
1205 /* avoid division by zero */
1206 if (old_brush_size != 0) {
1207 scale /= float(old_brush_size);
1208 }
1209 (*unprojected_radius) *= scale;
1210}
1211
1212void BKE_brush_scale_size(int *r_brush_size,
1213 float new_unprojected_radius,
1214 float old_unprojected_radius)
1215{
1216 float scale = new_unprojected_radius;
1217 /* avoid division by zero */
1218 if (old_unprojected_radius != 0) {
1219 scale /= new_unprojected_radius;
1220 }
1221 (*r_brush_size) = int(float(*r_brush_size) * scale);
1222}
1223
1224void BKE_brush_jitter_pos(const Scene &scene,
1225 const Brush &brush,
1226 const float pos[2],
1227 float jitterpos[2])
1228{
1229 float rand_pos[2];
1230 float spread;
1231 int diameter;
1232
1233 do {
1234 rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f;
1235 rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f;
1236 } while (len_squared_v2(rand_pos) > square_f(0.5f));
1237
1238 if (brush.flag & BRUSH_ABSOLUTE_JITTER) {
1239 diameter = 2 * brush.jitter_absolute;
1240 spread = 1.0;
1241 }
1242 else {
1243 diameter = 2 * BKE_brush_size_get(&scene, &brush);
1244 spread = brush.jitter;
1245 }
1246 /* find random position within a circle of diameter 1 */
1247 jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread;
1248 jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread;
1249}
1250
1252{
1253 /* we multiply with brush radius as an optimization for the brush
1254 * texture sampling functions */
1255 if (mask) {
1258 }
1259 else {
1262 }
1263}
1264
1266 const CurveMapping *cumap,
1267 const blender::Span<float> distances,
1268 const float brush_radius,
1269 const blender::MutableSpan<float> factors)
1270{
1271 BLI_assert(factors.size() == distances.size());
1272
1273 const float radius_rcp = blender::math::rcp(brush_radius);
1274 switch (preset) {
1275 case BRUSH_CURVE_CUSTOM: {
1276 for (const int i : distances.index_range()) {
1277 const float distance = distances[i];
1278 if (distance >= brush_radius) {
1279 factors[i] = 0.0f;
1280 continue;
1281 }
1282 factors[i] *= BKE_curvemapping_evaluateF(cumap, 0, distance * radius_rcp);
1283 }
1284 break;
1285 }
1286 case BRUSH_CURVE_SHARP: {
1287 for (const int i : distances.index_range()) {
1288 const float distance = distances[i];
1289 if (distance >= brush_radius) {
1290 factors[i] = 0.0f;
1291 continue;
1292 }
1293 const float factor = 1.0f - distance * radius_rcp;
1294 factors[i] *= factor * factor;
1295 }
1296 break;
1297 }
1298 case BRUSH_CURVE_SMOOTH: {
1299 for (const int i : distances.index_range()) {
1300 const float distance = distances[i];
1301 if (distance >= brush_radius) {
1302 factors[i] = 0.0f;
1303 continue;
1304 }
1305 const float factor = 1.0f - distance * radius_rcp;
1306 factors[i] *= 3.0f * factor * factor - 2.0f * factor * factor * factor;
1307 }
1308 break;
1309 }
1310 case BRUSH_CURVE_SMOOTHER: {
1311 for (const int i : distances.index_range()) {
1312 const float distance = distances[i];
1313 if (distance >= brush_radius) {
1314 factors[i] = 0.0f;
1315 continue;
1316 }
1317 const float factor = 1.0f - distance * radius_rcp;
1318 factors[i] *= pow3f(factor) * (factor * (factor * 6.0f - 15.0f) + 10.0f);
1319 }
1320 break;
1321 }
1322 case BRUSH_CURVE_ROOT: {
1323 for (const int i : distances.index_range()) {
1324 const float distance = distances[i];
1325 if (distance >= brush_radius) {
1326 factors[i] = 0.0f;
1327 continue;
1328 }
1329 const float factor = 1.0f - distance * radius_rcp;
1330 factors[i] *= sqrtf(factor);
1331 }
1332 break;
1333 }
1334 case BRUSH_CURVE_LIN: {
1335 for (const int i : distances.index_range()) {
1336 const float distance = distances[i];
1337 if (distance >= brush_radius) {
1338 factors[i] = 0.0f;
1339 continue;
1340 }
1341 const float factor = 1.0f - distance * radius_rcp;
1342 factors[i] *= factor;
1343 }
1344 break;
1345 }
1346 case BRUSH_CURVE_CONSTANT: {
1347 break;
1348 }
1349 case BRUSH_CURVE_SPHERE: {
1350 for (const int i : distances.index_range()) {
1351 const float distance = distances[i];
1352 if (distance >= brush_radius) {
1353 factors[i] = 0.0f;
1354 continue;
1355 }
1356 const float factor = 1.0f - distance * radius_rcp;
1357 factors[i] *= sqrtf(2 * factor - factor * factor);
1358 }
1359 break;
1360 }
1361 case BRUSH_CURVE_POW4: {
1362 for (const int i : distances.index_range()) {
1363 const float distance = distances[i];
1364 if (distance >= brush_radius) {
1365 factors[i] = 0.0f;
1366 continue;
1367 }
1368 const float factor = 1.0f - distance * radius_rcp;
1369 factors[i] *= factor * factor * factor * factor;
1370 }
1371 break;
1372 }
1373 case BRUSH_CURVE_INVSQUARE: {
1374 for (const int i : distances.index_range()) {
1375 const float distance = distances[i];
1376 if (distance >= brush_radius) {
1377 factors[i] = 0.0f;
1378 continue;
1379 }
1380 const float factor = 1.0f - distance * radius_rcp;
1381 factors[i] *= factor * (2.0f - factor);
1382 }
1383 break;
1384 }
1385 }
1386}
1387
1389 const CurveMapping *cumap,
1390 const float distance,
1391 const float brush_radius)
1392{
1393 float p = distance;
1394 float strength = 1.0f;
1395
1396 if (p >= brush_radius) {
1397 return 0;
1398 }
1399
1400 p = p / brush_radius;
1401 p = 1.0f - p;
1402
1403 switch (preset) {
1404 case BRUSH_CURVE_CUSTOM:
1405 strength = BKE_curvemapping_evaluateF(cumap, 0, 1.0f - p);
1406 break;
1407 case BRUSH_CURVE_SHARP:
1408 strength = p * p;
1409 break;
1410 case BRUSH_CURVE_SMOOTH:
1411 strength = 3.0f * p * p - 2.0f * p * p * p;
1412 break;
1414 strength = pow3f(p) * (p * (p * 6.0f - 15.0f) + 10.0f);
1415 break;
1416 case BRUSH_CURVE_ROOT:
1417 strength = sqrtf(p);
1418 break;
1419 case BRUSH_CURVE_LIN:
1420 strength = p;
1421 break;
1423 strength = 1.0f;
1424 break;
1425 case BRUSH_CURVE_SPHERE:
1426 strength = sqrtf(2 * p - p * p);
1427 break;
1428 case BRUSH_CURVE_POW4:
1429 strength = p * p * p * p;
1430 break;
1432 strength = p * (2.0f - p);
1433 break;
1434 }
1435
1436 return strength;
1437}
1438
1439float BKE_brush_curve_strength(const Brush *br, float p, const float len)
1440{
1442}
1443
1444float BKE_brush_curve_strength_clamped(const Brush *br, float p, const float len)
1445{
1446 float strength = BKE_brush_curve_strength(br, p, len);
1447
1448 CLAMP(strength, 0.0f, 1.0f);
1449
1450 return strength;
1451}
1452
1453/* TODO: should probably be unified with BrushPainter stuff? */
1454static bool brush_gen_texture(const Brush *br,
1455 const int side,
1456 const bool use_secondary,
1457 float *rect)
1458{
1459 const MTex *mtex = (use_secondary) ? &br->mask_mtex : &br->mtex;
1460 if (mtex->tex == nullptr) {
1461 return false;
1462 }
1463
1464 const float step = 2.0 / side;
1465 int ix, iy;
1466 float x, y;
1467
1468 /* Do normalized canonical view coords for texture. */
1469 for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
1470 for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
1471 const float co[3] = {x, y, 0.0f};
1472
1473 float intensity;
1474 float rgba_dummy[4];
1475 RE_texture_evaluate(mtex, co, 0, nullptr, false, false, &intensity, rgba_dummy);
1476
1477 rect[iy * side + ix] = intensity;
1478 }
1479 }
1480
1481 return true;
1482}
1483
1484ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool display_gradient)
1485{
1486 ImBuf *im = MEM_cnew<ImBuf>("radial control texture");
1487 int side = 512;
1488 int half = side / 2;
1489
1491
1492 float *rect_float = (float *)MEM_callocN(sizeof(float) * side * side, "radial control rect");
1494
1495 im->x = im->y = side;
1496
1497 const bool have_texture = brush_gen_texture(br, side, secondary, im->float_buffer.data);
1498
1499 if (display_gradient || have_texture) {
1500 for (int i = 0; i < side; i++) {
1501 for (int j = 0; j < side; j++) {
1502 const float magn = sqrtf(pow2f(i - half) + pow2f(j - half));
1503 const float strength = BKE_brush_curve_strength_clamped(br, magn, half);
1504 im->float_buffer.data[i * side + j] = (have_texture) ?
1505 im->float_buffer.data[i * side + j] * strength :
1506 strength;
1507 }
1508 }
1509 }
1510
1511 return im;
1512}
1513
1514bool BKE_brush_has_cube_tip(const Brush *brush, PaintMode paint_mode)
1515{
1516 switch (paint_mode) {
1517 case PaintMode::Sculpt: {
1519 return true;
1520 }
1521
1523 (brush->tip_roundness < 1.0f || brush->tip_scale_x != 1.0f))
1524 {
1525 return true;
1526 }
1527
1528 break;
1529 }
1530 default: {
1531 break;
1532 }
1533 }
1534
1535 return false;
1536}
void BKE_asset_metadata_idprop_ensure(AssetMetaData *asset_data, IDProperty *prop)
Definition asset.cc:175
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
Definition bpath.cc:123
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
CurveMapping * BKE_curvemapping_copy(const CurveMapping *cumap)
void BKE_curvemapping_init(CurveMapping *cumap)
CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition colortools.cc:90
void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
void BKE_curvemapping_free(CurveMapping *cumap)
void BKE_curvemapping_changed(CurveMapping *cumap, bool rem_doubles)
void BKE_curvemapping_blend_write(BlendWriter *writer, const CurveMapping *cumap)
@ CURVEMAP_SLOPE_NEGATIVE
Low-level operations for grease pencil.
IDTypeInfo IDType_ID_BR
Definition brush.cc:437
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition BKE_idtype.hh:41
@ IDTYPE_FLAGS_NO_MEMFILE_UNDO
Definition BKE_idtype.hh:50
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
void BKE_lib_id_expand_local(Main *bmain, ID *id, int flags)
Definition lib_id.cc:474
void id_fake_user_set(ID *id)
Definition lib_id.cc:389
bool BKE_lib_id_make_local(Main *bmain, ID *id, int flags)
Definition lib_id.cc:584
void BKE_lib_id_make_local_generic_action_define(Main *bmain, ID *id, int flags, bool *r_force_local, bool *r_force_copy)
Definition lib_id.cc:488
ID * BKE_id_copy(Main *bmain, const ID *id)
Definition lib_id.cc:765
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1482
void BKE_lib_id_clear_library_data(Main *bmain, ID *id, int flags)
Definition lib_id.cc:206
@ LIB_ID_COPY_NO_PREVIEW
@ LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR
@ LIB_ID_MAKELOCAL_FULL_LIBRARY
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2560
#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data_, func_call_)
@ IDWALK_CB_USER
@ IDWALK_CB_NOP
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
Definition lib_query.cc:613
@ ID_REMAP_SKIP_INDIRECT_USAGE
void void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, int remap_flags) ATTR_NONNULL(1
General operations, lookup, etc. for materials.
PaintMode
Definition BKE_paint.hh:99
std::optional< int > BKE_paint_get_brush_type_from_obmode(const Brush *brush, const eObjectMode ob_mode)
Definition paint.cc:1280
bool BKE_paint_use_unified_color(const ToolSettings *tool_settings, const Paint *paint)
Definition paint.cc:605
CurveMapping * BKE_sculpt_default_cavity_curve()
Definition scene.cc:120
void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv)
void BKE_previewimg_free(PreviewImage **prv)
void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv)
void BKE_previewimg_id_copy(ID *new_id, const ID *old_id)
void BKE_texture_mtex_foreach_id(struct LibraryForeachIDData *data, struct MTex *mtex)
Definition texture.cc:230
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
MINLINE float pow2f(float x)
MINLINE float square_f(float a)
MINLINE float pow3f(float x)
MINLINE float len_squared_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v4(float r[4])
Random number functions.
struct RNG * BLI_rng_new(unsigned int seed)
Definition rand.cc:39
void BLI_rng_srandom(struct RNG *rng, unsigned int seed) ATTR_NONNULL(1)
Definition rand.cc:68
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:58
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:93
#define CLAMP(a, b, c)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define BLT_I18NCONTEXT_ID_BRUSH
ID and Library types, which are fundamental for SDNA.
#define ID_EXTRA_USERS(id)
Definition DNA_ID.h:623
#define FILTER_ID_MA
Definition DNA_ID.h:1175
#define FILTER_ID_BR
Definition DNA_ID.h:1166
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
#define FILTER_ID_TE
Definition DNA_ID.h:1187
@ INDEX_ID_BR
Definition DNA_ID.h:1314
#define ID_REAL_USERS(id)
Definition DNA_ID.h:637
#define FILTER_ID_PC
Definition DNA_ID.h:1183
@ ID_TAG_INDIRECT
Definition DNA_ID.h:794
#define ID_NEW_SET(_id, _idn)
Definition DNA_ID.h:707
#define FILTER_ID_IM
Definition DNA_ID.h:1171
@ ID_BR
eBrushCurvePreset
@ BRUSH_CURVE_CUSTOM
@ BRUSH_CURVE_SHARP
@ BRUSH_CURVE_INVSQUARE
@ BRUSH_CURVE_SPHERE
@ BRUSH_CURVE_CONSTANT
@ BRUSH_CURVE_POW4
@ BRUSH_CURVE_ROOT
@ BRUSH_CURVE_SMOOTH
@ BRUSH_CURVE_SMOOTHER
@ BRUSH_CURVE_LIN
@ SCULPT_BRUSH_TYPE_DRAW_SHARP
@ SCULPT_BRUSH_TYPE_MASK
@ SCULPT_BRUSH_TYPE_FILL
@ SCULPT_BRUSH_TYPE_DRAW
@ SCULPT_BRUSH_TYPE_CLAY
@ SCULPT_BRUSH_TYPE_PINCH
@ SCULPT_BRUSH_TYPE_CLAY_THUMB
@ SCULPT_BRUSH_TYPE_MULTIPLANE_SCRAPE
@ SCULPT_BRUSH_TYPE_CREASE
@ SCULPT_BRUSH_TYPE_LAYER
@ SCULPT_BRUSH_TYPE_FLATTEN
@ SCULPT_BRUSH_TYPE_PAINT
@ SCULPT_BRUSH_TYPE_SCRAPE
@ SCULPT_BRUSH_TYPE_INFLATE
@ SCULPT_BRUSH_TYPE_BLOB
@ SCULPT_BRUSH_TYPE_CLAY_STRIPS
@ GP_BRUSH_MATERIAL_PINNED
@ GP_BRUSH_USE_JITTER_PRESSURE
@ GP_BRUSH_USE_PRESSURE
@ BRUSH_OFFSET_PRESSURE
@ BRUSH_ORIGINAL_NORMAL
@ BRUSH_ALPHA_PRESSURE
@ BRUSH_SPACE_ATTEN
@ BRUSH_LOCK_ALPHA
@ BRUSH_FRONTFACE
@ BRUSH_ADAPTIVE_SPACE
@ BRUSH_DRAG_DOT
@ BRUSH_SPACING_PRESSURE
@ BRUSH_EDGE_TO_EDGE
@ BRUSH_SMOOTH_STROKE
@ BRUSH_ACCUMULATE
@ BRUSH_DIR_IN
@ BRUSH_ANCHORED
@ BRUSH_CUSTOM_ICON
@ BRUSH_JITTER_PRESSURE
@ BRUSH_PLANE_TRIM
@ BRUSH_LOCK_SIZE
@ BRUSH_INVERSE_SMOOTH_PRESSURE
@ BRUSH_ABSOLUTE_JITTER
@ BRUSH_PERSISTENT
@ BRUSH_SIZE_PRESSURE
@ BRUSH_AIRBRUSH
@ BRUSH_SPACE
@ BRUSH_MASK_PRESSURE_RAMP
@ BRUSH_MASK_PRESSURE_CUTOFF
@ BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_RADIUS
@ BRUSH_OVERLAY_SECONDARY_OVERRIDE_ON_STROKE
@ BRUSH_OVERLAY_PRIMARY_OVERRIDE_ON_STROKE
@ BRUSH_OVERLAY_SECONDARY
@ BRUSH_OVERLAY_CURSOR
@ BRUSH_OVERLAY_CURSOR_OVERRIDE_ON_STROKE
@ BRUSH_OVERLAY_PRIMARY
#define MAX_BRUSH_PIXEL_RADIUS
@ CUMA_EXTEND_EXTRAPOLATE
eCurveMappingPreset
@ CURVE_PRESET_SMOOTH
@ CURVE_PRESET_SHARP
#define DNA_struct_default_get(struct_name)
eObjectMode
@ OB_MODE_VERTEX_GREASE_PENCIL
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_SCULPT
@ OB_MODE_SCULPT_CURVES
@ OB_MODE_PAINT_GREASE_PENCIL
@ OB_MODE_SCULPT_GREASE_PENCIL
@ OB_MODE_TEXTURE_PAINT
@ OB_MODE_WEIGHT_GREASE_PENCIL
@ OB_MODE_VERTEX_PAINT
@ UNIFIED_PAINT_WEIGHT
@ UNIFIED_PAINT_SIZE
@ UNIFIED_PAINT_BRUSH_LOCK_SIZE
@ UNIFIED_PAINT_ALPHA
@ UNIFIED_PAINT_INPUT_SAMPLES
@ MTEX_MAP_MODE_3D
@ MTEX_MAP_MODE_STENCIL
@ MTEX_MAP_MODE_TILED
@ MTEX_MAP_MODE_RANDOM
@ MTEX_MAP_MODE_VIEW
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)
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership)
Contains defines and structs used throughout the imbuf module.
@ IB_DO_NOT_TAKE_OWNERSHIP
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
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 color
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
void BKE_brush_jitter_pos(const Scene &scene, const Brush &brush, const float pos[2], float jitterpos[2])
Definition brush.cc:1224
void BKE_brush_weight_set(const Scene *scene, Brush *brush, float value)
Definition brush.cc:1167
const MTex * BKE_brush_mask_texture_get(const Brush *brush, const eObjectMode object_mode)
Definition brush.cc:762
float BKE_brush_curve_strength_clamped(const Brush *br, float p, const float len)
Definition brush.cc:1444
static void brush_defaults(Brush *brush)
Definition brush.cc:485
bool BKE_brush_use_alpha_pressure(const Brush *brush)
Definition brush.cc:1096
void BKE_brush_randomize_texture_coords(UnifiedPaintSettings *ups, bool mask)
Definition brush.cc:1251
float BKE_brush_weight_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1160
float BKE_brush_curve_strength(const eBrushCurvePreset preset, const CurveMapping *cumap, const float distance, const float brush_radius)
Definition brush.cc:1388
float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1133
static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition brush.cc:224
#define BR_TEST(field, t)
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1075
static void brush_free_data(ID *id)
Definition brush.cc:121
static AssetTypeInfo AssetType_BR
Definition brush.cc:432
static void brush_blend_read_after_liblink(BlendLibReader *, ID *id)
Definition brush.cc:371
const MTex * BKE_brush_color_texture_get(const Brush *brush, const eObjectMode object_mode)
Definition brush.cc:770
void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojected_radius)
Definition brush.cc:1120
Brush * BKE_brush_first_search(Main *bmain, const eObjectMode ob_mode)
Definition brush.cc:628
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
Definition brush.cc:1059
static void brush_foreach_id(ID *id, LibraryForeachIDData *data)
Definition brush.cc:199
#define FROM_DEFAULT(member)
#define BR_TEST_FLAG_OVERLAY(_f)
const float * BKE_brush_secondary_color_get(const Scene *scene, const Paint *paint, const Brush *brush)
Definition brush.cc:1037
void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha)
Definition brush.cc:1140
bool BKE_brush_use_size_pressure(const Brush *brush)
Definition brush.cc:1091
void BKE_brush_input_samples_set(const Scene *scene, Brush *brush, int value)
Definition brush.cc:1187
static void brush_init_data(ID *id)
Definition brush.cc:51
bool BKE_brush_has_cube_tip(const Brush *brush, PaintMode paint_mode)
Definition brush.cc:1514
static void brush_make_local(Main *bmain, ID *id, const int flags)
Definition brush.cc:154
static void brush_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int flag)
Definition brush.cc:65
void BKE_brush_init_curves_sculpt_settings(Brush *brush)
Definition brush.cc:605
Brush * BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
Definition brush.cc:542
void BKE_brush_system_init()
Definition brush.cc:470
#define FROM_DEFAULT_PTR(member)
ImBuf * BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool display_gradient)
Definition brush.cc:1484
static bool brush_gen_texture(const Brush *br, const int side, const bool use_secondary, float *rect)
Definition brush.cc:1454
void BKE_brush_color_set(Scene *scene, const Paint *paint, Brush *brush, const float color[3])
Definition brush.cc:1047
static RNG * brush_rng
Definition brush.cc:468
void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset)
Definition brush.cc:744
static void brush_blend_read_data(BlendDataReader *reader, ID *id)
Definition brush.cc:281
void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, const CurveMapping *cumap, const blender::Span< float > distances, const float brush_radius, const blender::MutableSpan< float > factors)
Definition brush.cc:1265
bool BKE_brush_sculpt_has_secondary_color(const Brush *brush)
Definition brush.cc:1101
void BKE_brush_init_gpencil_settings(Brush *brush)
Definition brush.cc:563
float BKE_brush_sample_masktex(const Scene *scene, Brush *br, const float point[2], const int thread, ImagePool *pool)
Definition brush.cc:901
static void brush_foreach_path(ID *id, BPathForeachPathData *bpath_data)
Definition brush.cc:215
void BKE_brush_scale_size(int *r_brush_size, float new_unprojected_radius, float old_unprojected_radius)
Definition brush.cc:1212
float BKE_brush_alpha_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1153
const float * BKE_brush_color_get(const Scene *scene, const Paint *paint, const Brush *brush)
Definition brush.cc:1029
void BKE_brush_debug_print_state(Brush *br)
Definition brush.cc:638
bool BKE_brush_delete(Main *bmain, Brush *brush)
Definition brush.cc:589
bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
Definition brush.cc:1083
void BKE_brush_scale_unprojected_radius(float *unprojected_radius, int new_brush_size, int old_brush_size)
Definition brush.cc:1200
static void brush_asset_metadata_ensure(void *asset_ptr, AssetMetaData *asset_data)
Definition brush.cc:388
void BKE_brush_tag_unsaved_changes(Brush *brush)
Definition brush.cc:621
#define BR_TEST_FLAG(_f)
void BKE_brush_system_exit()
Definition brush.cc:476
int BKE_brush_input_samples_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1180
float BKE_brush_sample_tex_3d(const Scene *scene, const Brush *br, const MTex *mtex, const float point[3], float rgba[4], const int thread, ImagePool *pool)
Definition brush.cc:778
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
Definition half.h:42
local_group_size(16, 16) .push_constant(Type b
#define printf
#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
void IMB_freeImBuf(ImBuf *)
#define GS(x)
Definition iris.cc:202
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ccl_device_inline float4 mask(const int4 mask, const float4 a)
std::unique_ptr< IDProperty, IDPropertyDeleter > create_bool(StringRefNull prop_name, bool value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_BOOLEAN, set its name and value.
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
T rcp(const T &a)
float distance(float a, float b)
static ePaintOverlayControlFlags overlay_flags
Definition paint.cc:251
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
struct Image * image
struct CurveMapping * curve_parameter_falloff
struct CurveMapping * curve_sensitivity
struct CurveMapping * curve_strength
struct CurveMapping * curve_jitter
struct CurveMapping * curve_rand_pressure
struct CurveMapping * curve_rand_strength
struct CurveMapping * curve_rand_saturation
struct CurveMapping * curve_rand_hue
struct CurveMapping * curve_rand_uv
struct Material * material
struct Material * material_alt
struct CurveMapping * curve_rand_value
float alpha
char sculpt_brush_type
float jitter
struct ImBuf * icon_imbuf
struct ColorBand * gradient
struct BrushClone clone
struct MTex mtex
float stencil_pos[2]
float unprojected_radius
short ob_mode
float stencil_dimension[2]
int curve_preset
struct CurveMapping * curve
float tip_scale_x
float texture_sample_bias
int jitter_absolute
float mask_stencil_pos[2]
float rgb[3]
struct BrushGpencilSettings * gpencil_settings
char has_unsaved_changes
struct Brush * toggle_brush
int input_samples
char icon_filepath[1024]
PreviewImage * preview
struct CurveMapping * automasking_cavity_curve
struct BrushCurvesSculptSettings * curves_sculpt_settings
struct MTex mask_mtex
int mask_pressure
float mask_stencil_dimension[2]
float weight
float secondary_rgb[3]
struct PaintCurve * paint_curve
float tip_roundness
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
int us
Definition DNA_ID.h:435
struct ID * newid
Definition DNA_ID.h:417
char name[66]
Definition DNA_ID.h:425
ImBufFloatBuffer float_buffer
char brush_map_mode
struct Tex * tex
ListBase brushes
Definition BKE_main.hh:235
Definition rand.cc:33
struct ToolSettings * toolsettings
struct UnifiedPaintSettings unified_paint_settings
struct ColorSpace * colorspace
bool RE_texture_evaluate(const MTex *mtex, const float vec[3], const int thread, ImagePool *pool, const bool skip_load_image, const bool texnode_preview, float *r_intensity, float r_rgba[4])
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:138