Two new Features:

* Support for Rake in projective paint (2D painting will be a separate
commit)
* Support for smooth stroke across all paint systems
This commit is contained in:
Antony Riakiotakis
2013-03-14 02:27:36 +00:00
parent d9408f8800
commit 0d70e8a4fd
9 changed files with 153 additions and 143 deletions

View File

@@ -69,10 +69,8 @@ float BKE_brush_curve_strength_clamp(struct Brush *br, float p, const float len)
float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */
/* sampling */
void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float sampleco[3],
float rgba[4], const int thread, struct ImagePool *pool);
float BKE_brush_sample_tex_3D(const Scene *scene, struct Brush *br, const float point[3],
float rgba[3], struct ImagePool *pool);
float rgba[3], const int thread, struct ImagePool *pool);
float BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2],
float rgba[4], struct ImagePool *pool);
void BKE_brush_imbuf_new(const struct Scene *scene, struct Brush *brush, short flt, short texfalloff, int size,

View File

@@ -472,52 +472,10 @@ int BKE_brush_clone_image_delete(Brush *brush)
return 0;
}
/* Brush Sampling for 3d brushes. Currently used for texture painting only, but should be generalized */
void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco[3], float rgba[4], const int thread, struct ImagePool *pool)
{
MTex *mtex = &brush->mtex;
if (mtex && mtex->tex) {
float tin, tr, tg, tb, ta;
int hasrgb;
const int radius = BKE_brush_size_get(scene, brush);
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
hasrgb = externtex(mtex, sampleco, &tin, &tr, &tg, &tb, &ta, thread, pool);
}
else {
float co[3];
co[0] = sampleco[0] / radius;
co[1] = sampleco[1] / radius;
co[2] = 0.0f;
hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread, pool);
}
if (hasrgb) {
rgba[0] = tr;
rgba[1] = tg;
rgba[2] = tb;
rgba[3] = ta;
}
else {
rgba[0] = tin;
rgba[1] = tin;
rgba[2] = tin;
rgba[3] = 1.0f;
}
}
else {
rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f;
}
}
/* Return a multiplier for brush strength on a particular vertex. */
float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
const float point[3],
float rgba[3],
float rgba[3], const int thread,
struct ImagePool *pool)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
@@ -532,7 +490,7 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
/* Get strength by feeding the vertex
* location directly into a texture */
hasrgb = externtex(mtex, point, &intensity,
rgba, rgba + 1, rgba + 2, rgba + 3, 0, pool);
rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
}
else {
float rotation = -mtex->rot;
@@ -587,7 +545,7 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
co[2] = 0.0f;
hasrgb = externtex(mtex, co, &intensity,
rgba, rgba + 1, rgba + 2, rgba + 3, 0, pool);
rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
}
intensity += br->texture_sample_bias;

View File

@@ -3898,11 +3898,8 @@ static void *do_projectpaint_thread(void *ph_v)
if (ps->is_texbrush) {
MTex *mtex = &brush->mtex;
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
sub_v2_v2v2(samplecos, projPixel->projCoSS, pos);
}
/* taking 3d copy to account for 3D mapping too. It gets concatenated during sampling */
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
copy_v3_v3(samplecos, projPixel->worldCoSS);
}
else {
@@ -3914,7 +3911,7 @@ static void *do_projectpaint_thread(void *ph_v)
if (falloff > 0.0f) {
if (ps->is_texbrush) {
/* note, for clone and smear, we only use the alpha, could be a special function */
BKE_brush_sample_tex(ps->scene, brush, samplecos, rgba, thread_index, pool);
BKE_brush_sample_tex_3D(ps->scene, brush, samplecos, rgba, thread_index, pool);
alpha = rgba[3];
}
else {

View File

@@ -66,7 +66,8 @@ void paint_stroke_data_free(struct wmOperator *op);
bool paint_space_stroke_enabled(struct Brush *br, enum PaintMode mode);
bool paint_supports_dynamic_size(struct Brush *br, enum PaintMode mode);
bool paint_supports_moving_texture(struct Brush *br, enum PaintMode mode);
bool paint_supports_dynamic_tex_coords(struct Brush *br, enum PaintMode mode);
bool paint_supports_smooth_stroke(struct Brush *br, enum PaintMode mode);
bool paint_supports_jitter(enum PaintMode mode);
struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf);

View File

@@ -312,19 +312,12 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const wmEve
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
static int paint_smooth_stroke(PaintStroke *stroke, float output[2],
const PaintSample *sample)
const PaintSample *sample, PaintMode mode)
{
output[0] = sample->mouse[0];
output[1] = sample->mouse[1];
if ((stroke->brush->flag & BRUSH_SMOOTH_STROKE) &&
!ELEM4(stroke->brush->sculpt_tool,
SCULPT_TOOL_GRAB,
SCULPT_TOOL_THUMB,
SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK) &&
!(stroke->brush->flag & BRUSH_ANCHORED) &&
!(stroke->brush->flag & BRUSH_RESTORE_MESH))
if (paint_supports_smooth_stroke(stroke->brush, mode))
{
float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u;
float dx = stroke->last_mouse_position[0] - sample->mouse[0];
@@ -478,8 +471,29 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
return true;
}
bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
{
if(!(br->flag & BRUSH_SMOOTH_STROKE) ||
(br->flag & BRUSH_ANCHORED) ||
(br->flag & BRUSH_RESTORE_MESH))
return false;
switch (mode) {
case PAINT_SCULPT:
if (ELEM4(br->sculpt_tool,
SCULPT_TOOL_GRAB,
SCULPT_TOOL_THUMB,
SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK))
return false;
default:
;
}
return true;
}
/* return true if the brush size can change during paint (normally used for pressure) */
bool paint_supports_moving_texture(Brush *br, PaintMode mode)
bool paint_supports_dynamic_tex_coords(Brush *br, PaintMode mode)
{
if (br->flag & BRUSH_ANCHORED)
return false;
@@ -616,7 +630,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
(event->type == TIMER && (event->customdata == stroke->timer)) )
{
if (stroke->stroke_started) {
if (paint_smooth_stroke(stroke, mouse, &sample_average)) {
if (paint_smooth_stroke(stroke, mouse, &sample_average, mode)) {
if (paint_space_stroke_enabled(stroke->brush, mode)) {
if (!paint_space_stroke(C, op, event, mouse)) {
//ED_region_tag_redraw(ar);

View File

@@ -933,7 +933,7 @@ static float tex_strength(SculptSession *ss, Brush *br,
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
/* Get strength by feeding the vertex
* location directly into a texture */
avg = BKE_brush_sample_tex_3D(scene, br, point, rgba, ss->tex_pool);
avg = BKE_brush_sample_tex_3D(scene, br, point, rgba, 0, ss->tex_pool);
}
else if (ss->texcache) {
float symm_point[3], point_2d[2];
@@ -974,7 +974,7 @@ static float tex_strength(SculptSession *ss, Brush *br,
}
else {
const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
avg = BKE_brush_sample_tex_3D(scene, br, point_3d, rgba, ss->tex_pool);
avg = BKE_brush_sample_tex_3D(scene, br, point_3d, rgba, 0, ss->tex_pool);
}
}

View File

@@ -106,7 +106,7 @@ EnumPropertyItem brush_image_tool_items[] = {
#include "WM_api.h"
static int rna_SculptCapabilities_has_accumulate_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_accumulate_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM6(br->sculpt_tool,
@@ -114,19 +114,19 @@ static int rna_SculptCapabilities_has_accumulate_get(PointerRNA *ptr)
SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_LAYER);
}
static int rna_SculptCapabilities_has_auto_smooth_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_auto_smooth_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return !ELEM(br->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH);
}
static int rna_SculptCapabilities_has_height_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_height_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return br->sculpt_tool == SCULPT_TOOL_LAYER;
}
static int rna_SculptCapabilities_has_jitter_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_jitter_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
@@ -136,13 +136,13 @@ static int rna_SculptCapabilities_has_jitter_get(PointerRNA *ptr)
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
static int rna_SculptCapabilities_has_normal_weight_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_normal_weight_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK);
}
static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_overlay_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM(br->mtex.brush_map_mode,
@@ -150,38 +150,43 @@ static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr)
MTEX_MAP_MODE_TILED);
}
static int rna_SculptCapabilities_has_persistence_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_persistence_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return br->sculpt_tool == SCULPT_TOOL_LAYER;
}
static int rna_SculptCapabilities_has_pinch_factor_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_pinch_factor_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM(br->sculpt_tool, SCULPT_TOOL_BLOB, SCULPT_TOOL_CREASE);
}
static int rna_SculptCapabilities_has_plane_offset_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_plane_offset_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM5(br->sculpt_tool, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
SCULPT_TOOL_FILL, SCULPT_TOOL_FLATTEN, SCULPT_TOOL_SCRAPE);
}
static int rna_SculptCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (!ELEM4(br->sculpt_tool,
SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (ELEM(br->mtex.brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_AREA) &&
!(br->flag & BRUSH_ANCHORED) &&
!ELEM4(br->sculpt_tool,
SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
!(br->flag & BRUSH_ANCHORED));
}
static int rna_SculptCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return !ELEM4(br->sculpt_tool, SCULPT_TOOL_INFLATE,
@@ -189,7 +194,7 @@ static int rna_SculptCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
SCULPT_TOOL_SMOOTH);
}
static int rna_SculptCapabilities_has_secondary_color_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_secondary_color_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM10(br->sculpt_tool,
@@ -199,7 +204,7 @@ static int rna_SculptCapabilities_has_secondary_color_get(PointerRNA *ptr)
SCULPT_TOOL_SCRAPE);
}
static int rna_SculptCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
@@ -209,7 +214,7 @@ static int rna_SculptCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
static int rna_SculptCapabilities_has_space_attenuation_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_space_attenuation_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ((br->flag & BRUSH_SPACE) &&
@@ -217,22 +222,19 @@ static int rna_SculptCapabilities_has_space_attenuation_get(PointerRNA *ptr)
SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SNAKE_HOOK));
}
static int rna_SculptCapabilities_has_spacing_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_spacing_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
!ELEM4(br->sculpt_tool,
SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
return (!(br->flag & BRUSH_ANCHORED));
}
static int rna_SculptCapabilities_has_strength_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_strength_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return !ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK);
}
static int rna_SculptCapabilities_has_texture_angle_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM3(br->mtex.brush_map_mode,
@@ -241,7 +243,7 @@ static int rna_SculptCapabilities_has_texture_angle_get(PointerRNA *ptr)
MTEX_MAP_MODE_TILED);
}
static int rna_SculptCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM(br->mtex.brush_map_mode,
@@ -249,9 +251,14 @@ static int rna_SculptCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
MTEX_MAP_MODE_AREA);
}
static PointerRNA rna_Brush_sculpt_capabilities_get(PointerRNA *ptr)
static PointerRNA rna_Sculpt_sculpt_tool_capabilities_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_SculptCapabilities, ptr->id.data);
return rna_pointer_inherit_refine(ptr, &RNA_SculptToolCapabilities, ptr->id.data);
}
static PointerRNA rna_Brush_capabilities_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->id.data);
}
static void rna_Brush_reset_icon(Brush *br, const char *UNUSED(type))
@@ -463,41 +470,66 @@ static void rna_def_sculpt_capabilities(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "SculptCapabilities", NULL);
srna = RNA_def_struct(brna, "SculptToolCapabilities", NULL);
RNA_def_struct_sdna(srna, "Brush");
RNA_def_struct_nested(brna, srna, "Brush");
RNA_def_struct_ui_text(srna, "Sculpt Capabilities",
"Read-only indications of which brush operations "
"are supported by the current sculpt tool");
#define SCULPT_TOOL_CAPABILITY(prop_name_, ui_name_) \
prop = RNA_def_property(srna, "sculpt_" #prop_name_, \
PROP_BOOLEAN, PROP_NONE); \
RNA_def_property_clear_flag(prop, PROP_EDITABLE); \
RNA_def_property_boolean_funcs(prop, "rna_SculptToolCapabilities_" \
#prop_name_ "_get", NULL); \
RNA_def_property_ui_text(prop, ui_name_, NULL)
SCULPT_TOOL_CAPABILITY(has_accumulate, "Has Accumulate");
SCULPT_TOOL_CAPABILITY(has_auto_smooth, "Has Auto Smooth");
SCULPT_TOOL_CAPABILITY(has_height, "Has Height");
SCULPT_TOOL_CAPABILITY(has_jitter, "Has Jitter");
SCULPT_TOOL_CAPABILITY(has_normal_weight, "Has Crease/Pinch Factor");
SCULPT_TOOL_CAPABILITY(has_persistence, "Has Persistence");
SCULPT_TOOL_CAPABILITY(has_pinch_factor, "Has Pinch Factor");
SCULPT_TOOL_CAPABILITY(has_plane_offset, "Has Plane Offset");
SCULPT_TOOL_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle");
SCULPT_TOOL_CAPABILITY(has_sculpt_plane, "Has Sculpt Plane");
SCULPT_TOOL_CAPABILITY(has_secondary_color, "Has Secondary Color");
SCULPT_TOOL_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke");
SCULPT_TOOL_CAPABILITY(has_space_attenuation, "Has Space Attenuation");
SCULPT_TOOL_CAPABILITY(has_strength, "Has Strength");
#undef SCULPT_CAPABILITY
}
static void rna_def_brush_capabilities(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "BrushCapabilities", NULL);
RNA_def_struct_sdna(srna, "Brush");
RNA_def_struct_nested(brna, srna, "Brush");
RNA_def_struct_ui_text(srna, "Brush Capabilities",
"Read-only indications of which brush operations "
"are supported by the current brush");
#define BRUSH_CAPABILITY(prop_name_, ui_name_) \
prop = RNA_def_property(srna, #prop_name_, \
PROP_BOOLEAN, PROP_NONE); \
RNA_def_property_clear_flag(prop, PROP_EDITABLE); \
RNA_def_property_boolean_funcs(prop, "rna_SculptCapabilities_" \
RNA_def_property_boolean_funcs(prop, "rna_BrushCapabilities_" \
#prop_name_ "_get", NULL); \
RNA_def_property_ui_text(prop, ui_name_, NULL)
BRUSH_CAPABILITY(has_accumulate, "Has Accumulate");
BRUSH_CAPABILITY(has_auto_smooth, "Has Auto Smooth");
BRUSH_CAPABILITY(has_height, "Has Height");
BRUSH_CAPABILITY(has_jitter, "Has Jitter");
BRUSH_CAPABILITY(has_normal_weight, "Has Crease/Pinch Factor");
BRUSH_CAPABILITY(has_overlay, "Has Overlay");
BRUSH_CAPABILITY(has_persistence, "Has Persistence");
BRUSH_CAPABILITY(has_pinch_factor, "Has Pinch Factor");
BRUSH_CAPABILITY(has_plane_offset, "Has Plane Offset");
BRUSH_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle");
BRUSH_CAPABILITY(has_sculpt_plane, "Has Sculpt Plane");
BRUSH_CAPABILITY(has_secondary_color, "Has Secondary Color");
BRUSH_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke");
BRUSH_CAPABILITY(has_space_attenuation, "Has Space Attenuation");
BRUSH_CAPABILITY(has_spacing, "Has Spacing");
BRUSH_CAPABILITY(has_strength, "Has Strength");
BRUSH_CAPABILITY(has_texture_angle, "Has Texture Angle");
BRUSH_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
BRUSH_CAPABILITY(has_spacing, "Has Spacing");
#undef SCULPT_CAPABILITY
#undef BRUSH_CAPABILITY
}
static void rna_def_brush(BlenderRNA *brna)
@@ -968,11 +1000,17 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -1.0f, 1.0f, 10.0f, 3);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_Brush_update");
prop = RNA_def_property(srna, "brush_capabilities", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "BrushCapabilities");
RNA_def_property_pointer_funcs(prop, "rna_Brush_capabilities_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Brush Capabilities", "Brush's capabilities");
/* brush capabilities (mode-dependent) */
prop = RNA_def_property(srna, "sculpt_capabilities", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "SculptCapabilities");
RNA_def_property_pointer_funcs(prop, "rna_Brush_sculpt_capabilities_get", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "SculptToolCapabilities");
RNA_def_property_pointer_funcs(prop, "rna_Sculpt_sculpt_tool_capabilities_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Sculpt Capabilities", "Brush's capabilities in sculpt mode");
}
@@ -1034,6 +1072,7 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna)
void RNA_def_brush(BlenderRNA *brna)
{
rna_def_brush(brna);
rna_def_brush_capabilities(brna);
rna_def_sculpt_capabilities(brna);
rna_def_brush_texture_slot(brna);
rna_def_operator_stroke_element(brna);