Sculpt: Add a curve brush channel type
* Added a new curve brush channel type * Added a BKE_brush_curve_strength_ex method that just takes preset and curve as arguments, instead of pulling them from Brush. * Autosmooth and topology rake now have their own falloff curves.
This commit is contained in:
parent
99c0ee0558
commit
ccb3ca41cd
|
@ -31,6 +31,22 @@ channel_name_map = {
|
|||
};
|
||||
expand_channels = {"direction"}
|
||||
|
||||
def template_curve(layout, base, propname, full_path):
|
||||
layout.template_curve_mapping(base, propname, brush=True)
|
||||
|
||||
path = full_path
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
|
||||
shapes = ['SMOOTH', 'ROUND', 'ROOT', 'SHARP', 'LINE', 'MAX']
|
||||
icons = ['SMOOTHCURVE', 'SPHERECURVE', 'ROOTCURVE', 'SHARPCURVE', 'LINCURVE', 'NOCURVE']
|
||||
|
||||
for i, shape in enumerate(shapes):
|
||||
props = row.operator("brush.curve_preset_load", icon=icons[i], text="")
|
||||
props.shape = shape
|
||||
props.path = path
|
||||
|
||||
class UnifiedPaintPanel:
|
||||
# subclass must set
|
||||
# bl_space_type = 'IMAGE_EDITOR'
|
||||
|
@ -144,7 +160,7 @@ class UnifiedPaintPanel:
|
|||
typeprop = "color3_value"
|
||||
elif ch.type == "VEC4":
|
||||
typeprop = "color4_value"
|
||||
|
||||
|
||||
if text is None:
|
||||
s = prop_name.lower().replace("_", " ").split(" ");
|
||||
text = ''
|
||||
|
@ -181,7 +197,13 @@ class UnifiedPaintPanel:
|
|||
row.prop(ch, "show_in_workspace", text="", icon="HIDE_OFF")
|
||||
#row.prop(ch, "ui_order", text="")
|
||||
|
||||
if ch.type == "BITMASK":
|
||||
if ch.type == "CURVE":
|
||||
row.prop(finalch.curve, "curve_preset")
|
||||
if finalch.curve.curve_preset == "CUSTOM":
|
||||
path2 = path + ".curve.curve"
|
||||
template_curve(layout, finalch.curve, "curve", path2)
|
||||
|
||||
elif ch.type == "BITMASK":
|
||||
row.label(text=text)
|
||||
|
||||
if header:
|
||||
|
@ -201,7 +223,7 @@ class UnifiedPaintPanel:
|
|||
else:
|
||||
row.prop(finalch, typeprop, icon=icon, text=text, slider=slider)
|
||||
|
||||
pressure = pressure and ch.type not in ["BOOL", "ENUM", "BITMASK"]
|
||||
pressure = pressure and ch.type not in ["BOOL", "ENUM", "BITMASK", "CURVE"]
|
||||
|
||||
if pressure:
|
||||
row.prop(finalch.mappings["PRESSURE"], "enabled", text="", icon="STYLUS_PRESSURE")
|
||||
|
@ -213,14 +235,14 @@ class UnifiedPaintPanel:
|
|||
#if unified_name and not header:
|
||||
# # NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281
|
||||
# row.prop(ups, unified_name, text="", icon='BRUSHES_ALL')
|
||||
if not header: # and ch.type != "BOOL":
|
||||
if not header:
|
||||
if ch.type == "BITMASK" and not toolsettings_only and ch == finalch:
|
||||
row.prop(ch, "inherit_if_unset", text="Combine With Defaults")
|
||||
|
||||
if not toolsettings_only:
|
||||
row.prop(ch, "inherit", text="", icon='BRUSHES_ALL')
|
||||
|
||||
if ch.type == "BITMASK" or ch.type == "BOOL":
|
||||
if ch.type in ["BITMASK", "BOOL", "CURVE"]:
|
||||
return
|
||||
|
||||
if not ui_editing and not show_reorder:
|
||||
|
@ -792,12 +814,18 @@ def brush_settings(layout, context, brush, popover=False):
|
|||
"auto_smooth_radius_factor",
|
||||
slider=True
|
||||
)
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
box,
|
||||
context,
|
||||
brush,
|
||||
"autosmooth_falloff_curve"
|
||||
)
|
||||
elif brush.sculpt_tool == "SMOOTH":
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"auto_smooth_projection",
|
||||
"projection",
|
||||
slider=True
|
||||
)
|
||||
|
||||
|
@ -847,7 +875,21 @@ def brush_settings(layout, context, brush, popover=False):
|
|||
slider=True
|
||||
)
|
||||
|
||||
box.prop(brush, "use_curvature_rake")
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
box,
|
||||
context,
|
||||
brush,
|
||||
"topology_rake_mode",
|
||||
expand=True
|
||||
)
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
box,
|
||||
context,
|
||||
brush,
|
||||
"topology_rake_falloff_curve"
|
||||
)
|
||||
|
||||
#box.prop(brush, "use_curvature_rake")
|
||||
box.prop(brush, "ignore_falloff_for_topology_rake")
|
||||
|
||||
if context.sculpt_object.use_dynamic_topology_sculpting:
|
||||
|
|
|
@ -38,6 +38,7 @@ struct ToolSettings;
|
|||
struct UnifiedPaintSettings;
|
||||
struct DynTopoSettings;
|
||||
struct Sculpt;
|
||||
struct CurveMapping;
|
||||
|
||||
// enum eCurveMappingPreset;
|
||||
|
||||
|
@ -166,6 +167,10 @@ bool BKE_brush_hard_edge_mode_get(const struct Scene *scene, const struct Brush
|
|||
void BKE_brush_hard_edge_mode_set(struct Scene *scene, struct Brush *brush, bool val);
|
||||
|
||||
float BKE_brush_fset_slide_get(const struct Scene *scene, const struct Brush *brush);
|
||||
float BKE_brush_curve_strength_ex(int curve_preset,
|
||||
const struct CurveMapping *curve,
|
||||
float p,
|
||||
const float len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ struct Sculpt;
|
|||
BKE_brush_channelset_get_float(chset, MAKE_BUILTIN_CH_NAME(channel), mapdata)
|
||||
#define BRUSHSET_GET_INT(chset, channel, mapdata) \
|
||||
BKE_brush_channelset_get_int(chset, MAKE_BUILTIN_CH_NAME(channel), mapdata)
|
||||
#define BRUSHSET_ENSURE_BUILTIN(chset, channel) \
|
||||
BKE_brush_channelset_ensure_builtin(chset, MAKE_BUILTIN_CH_NAME(channel))
|
||||
|
||||
//#define DEBUG_CURVE_MAPPING_ALLOC
|
||||
#ifdef DEBUG_CURVE_MAPPING_ALLOC
|
||||
|
@ -109,6 +111,7 @@ typedef struct BrushChannelType {
|
|||
int ivalue;
|
||||
float fvalue;
|
||||
float vector[4];
|
||||
int curve_preset;
|
||||
|
||||
BrushEnumDef enumdef[MAX_BRUSH_ENUM_DEF]; // for enum/bitmask types
|
||||
EnumPropertyItem *rna_enumdef;
|
||||
|
@ -165,8 +168,8 @@ BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *id
|
|||
|
||||
bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname);
|
||||
|
||||
void BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname);
|
||||
bool BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname);
|
||||
BrushChannel *BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname);
|
||||
BrushChannel *BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname);
|
||||
|
||||
void BKE_brush_channelset_merge(BrushChannelSet *dst,
|
||||
BrushChannelSet *child,
|
||||
|
@ -217,6 +220,11 @@ void BKE_brush_channelset_set_final_float(BrushChannelSet *child,
|
|||
void BKE_brush_channel_set_vector(BrushChannel *ch, float vec[4]);
|
||||
int BKE_brush_channel_get_vector_size(BrushChannel *ch);
|
||||
|
||||
float BKE_brush_channel_curve_evaluate(BrushChannel *ch, float val, const float maxval);
|
||||
CurveMapping *BKE_brush_channel_curvemapping_get(BrushCurve *curve, bool force_create);
|
||||
bool BKE_brush_channel_curve_ensure_write(BrushCurve *curve);
|
||||
void BKE_brush_channel_curve_assign(BrushChannel *ch, BrushCurve *curve);
|
||||
|
||||
/* returns size of vector */
|
||||
int BKE_brush_channel_get_vector(BrushChannel *ch, float out[4], BrushMappingData *mapdata);
|
||||
|
||||
|
|
|
@ -2675,8 +2675,10 @@ void BKE_brush_randomize_texture_coords(UnifiedPaintSettings *ups, bool mask)
|
|||
}
|
||||
}
|
||||
|
||||
/* Uses the brush curve control to find a strength value */
|
||||
ATTR_NO_OPT float BKE_brush_curve_strength(const Brush *br, float p, const float len)
|
||||
ATTR_NO_OPT float BKE_brush_curve_strength_ex(int curve_preset,
|
||||
const CurveMapping *curve,
|
||||
float p,
|
||||
const float len)
|
||||
{
|
||||
float strength = 1.0f;
|
||||
|
||||
|
@ -2687,9 +2689,9 @@ ATTR_NO_OPT float BKE_brush_curve_strength(const Brush *br, float p, const float
|
|||
p = p / len;
|
||||
p = 1.0f - p;
|
||||
|
||||
switch (br->curve_preset) {
|
||||
switch (curve_preset) {
|
||||
case BRUSH_CURVE_CUSTOM:
|
||||
strength = BKE_curvemapping_evaluateF(br->curve, 0, 1.0f - p);
|
||||
strength = BKE_curvemapping_evaluateF(curve, 0, 1.0f - p);
|
||||
break;
|
||||
case BRUSH_CURVE_SHARP:
|
||||
strength = p * p;
|
||||
|
@ -2723,6 +2725,12 @@ ATTR_NO_OPT float BKE_brush_curve_strength(const Brush *br, float p, const float
|
|||
return strength;
|
||||
}
|
||||
|
||||
/* Uses the brush curve control to find a strength value */
|
||||
ATTR_NO_OPT float BKE_brush_curve_strength(const Brush *br, float p, const float len)
|
||||
{
|
||||
return BKE_brush_curve_strength_ex(br->curve_preset, br->curve, p, len);
|
||||
}
|
||||
|
||||
/* Uses the brush curve control to find a strength value between 0 and 1 */
|
||||
float BKE_brush_curve_strength_clamped(Brush *br, float p, const float len)
|
||||
{
|
||||
|
|
|
@ -58,6 +58,9 @@ places in rna_engine_codebase are relevent:
|
|||
# ifdef MAKE_FLAGS_EX
|
||||
# undef MAKE_FLAGS_EX
|
||||
# endif
|
||||
# ifdef MAKE_CURVE
|
||||
# undef MAKE_CURVE
|
||||
# endif
|
||||
|
||||
# ifdef MAKE_BUILTIN_CH_DEF
|
||||
# undef MAKE_BUILTIN_CH_DEF
|
||||
|
@ -90,7 +93,7 @@ places in rna_engine_codebase are relevent:
|
|||
# define MAKE_FLAGS(idname1, name1, tooltip1, value1, enumdef1) MAKE_BUILTIN_CH_DEF(idname1);
|
||||
# define MAKE_FLAGS_EX(idname1, name1, tooltip1, value1, enumdef1, flag1) \
|
||||
MAKE_BUILTIN_CH_DEF(idname1);
|
||||
|
||||
# define MAKE_CURVE(idname1, name1, tooltip1, preset1) MAKE_BUILTIN_CH_DEF(idname1);
|
||||
#else
|
||||
#endif
|
||||
|
||||
|
@ -317,6 +320,10 @@ MAKE_ENUM(deform_target, "Deformation Target", "How the deformation of the brush
|
|||
{-1}
|
||||
}))
|
||||
|
||||
MAKE_CURVE(autosmooth_falloff_curve, "Falloff", "Custom curve for autosmooth", BRUSH_CURVE_SMOOTH)
|
||||
MAKE_CURVE(topology_rake_falloff_curve, "Falloff", "Custom curve for topolgoy rake", BRUSH_CURVE_SMOOTH)
|
||||
MAKE_CURVE(falloff_curve, "Falloff", "Falloff curve", BRUSH_CURVE_SMOOTH)
|
||||
|
||||
/* clang-format on */
|
||||
#if defined(BRUSH_CHANNEL_DEFINE_TYPES) || defined(BRUSH_CHANNEL_DEFINE_EXTERNAL)
|
||||
# ifdef MAKE_FLOAT
|
||||
|
@ -366,4 +373,8 @@ MAKE_ENUM(deform_target, "Deformation Target", "How the deformation of the brush
|
|||
# ifdef MAKE_BUILTIN_CH_DEF
|
||||
# undef MAKE_BUILTIN_CH_DEF
|
||||
# endif
|
||||
|
||||
# ifdef MAKE_CURVE
|
||||
# undef MAKE_CURVE
|
||||
# endif
|
||||
#endif
|
||||
|
|
|
@ -95,6 +95,39 @@ bool BKE_brush_mapping_ensure_write(BrushMapping *mp)
|
|||
return false;
|
||||
}
|
||||
|
||||
void BKE_brush_channel_curve_assign(BrushChannel *ch, BrushCurve *curve)
|
||||
{
|
||||
RELEASE_OR_FREE_CURVE(ch->curve.curve);
|
||||
|
||||
if (curve->curve) {
|
||||
if (IS_CACHE_CURVE(curve->curve)) {
|
||||
ch->curve.curve = curve->curve;
|
||||
CURVE_ADDREF(curve->curve);
|
||||
}
|
||||
else {
|
||||
ch->curve.curve = BKE_curvemapping_copy(curve->curve);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ch->curve.curve = NULL;
|
||||
}
|
||||
|
||||
ch->curve.preset = curve->preset;
|
||||
}
|
||||
|
||||
// returns true if curve was duplicated
|
||||
bool BKE_brush_channel_curve_ensure_write(BrushCurve *curve)
|
||||
{
|
||||
BKE_brush_channel_curvemapping_get(curve, true);
|
||||
|
||||
if (IS_CACHE_CURVE(curve->curve)) {
|
||||
curve->curve = BKE_curvemapping_copy(curve->curve);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT static bool check_corrupted_curve(BrushMapping *dst)
|
||||
{
|
||||
CurveMapping *curve = dst->curve;
|
||||
|
@ -178,6 +211,10 @@ ATTR_NO_OPT void BKE_brush_channeltype_rna_check(BrushChannelType *def,
|
|||
|
||||
ATTR_NO_OPT void BKE_brush_channel_free_data(BrushChannel *ch)
|
||||
{
|
||||
if (ch->curve.curve) {
|
||||
RELEASE_OR_FREE_CURVE(ch->curve.curve);
|
||||
}
|
||||
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
BrushMapping *mp = ch->mappings + i;
|
||||
|
||||
|
@ -193,6 +230,15 @@ ATTR_NO_OPT void BKE_brush_channel_free(BrushChannel *ch)
|
|||
|
||||
ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src)
|
||||
{
|
||||
if (src->type == BRUSH_CHANNEL_CURVE) {
|
||||
if (dst->curve.curve && IS_CACHE_CURVE(dst->curve.curve)) {
|
||||
RELEASE_CACHE_CURVE(dst->curve.curve);
|
||||
}
|
||||
else if (dst->curve.curve) {
|
||||
BKE_curvemapping_free(dst->curve.curve);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
BrushMapping *mp = dst->mappings + i;
|
||||
|
||||
|
@ -215,6 +261,19 @@ ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *sr
|
|||
|
||||
*dst = *src;
|
||||
|
||||
if (src->curve.curve) {
|
||||
if (!IS_CACHE_CURVE(src->curve.curve)) {
|
||||
// dst->curve = GET_CACHE_CURVE(src->curve);
|
||||
|
||||
// hrm, let's not modify src->curve, GET_CACHE_CURVE might free it
|
||||
dst->curve.curve = BKE_curvemapping_cache_get(
|
||||
BKE_curvemapping_cache_global(), src->curve.curve, false);
|
||||
}
|
||||
else {
|
||||
CURVE_ADDREF(dst->curve.curve);
|
||||
}
|
||||
}
|
||||
|
||||
dst->next = next;
|
||||
dst->prev = prev;
|
||||
|
||||
|
@ -244,6 +303,7 @@ ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
|
|||
|
||||
ch->flag = def->flag;
|
||||
|
||||
ch->curve.preset = def->curve_preset;
|
||||
ch->fvalue = def->fvalue;
|
||||
ch->ivalue = def->ivalue;
|
||||
|
||||
|
@ -302,6 +362,31 @@ ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
|
|||
}
|
||||
}
|
||||
|
||||
CurveMapping *BKE_brush_channel_curvemapping_get(BrushCurve *curve, bool force_create)
|
||||
{
|
||||
if ((force_create || curve->preset == BRUSH_CURVE_CUSTOM) && !curve->curve) {
|
||||
CurveMapping *cumap = curve->curve = MEM_callocN(sizeof(CurveMapping), "channel CurveMapping");
|
||||
|
||||
BKE_curvemapping_set_defaults(cumap, 1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
|
||||
BKE_curvemap_reset(cumap->cm,
|
||||
&(struct rctf){.xmin = 0, .ymin = 0.0, .xmax = 1.0, .ymax = 1.0},
|
||||
CURVE_PRESET_LINE,
|
||||
1);
|
||||
|
||||
BKE_curvemapping_init(cumap);
|
||||
}
|
||||
|
||||
return curve->curve;
|
||||
}
|
||||
|
||||
float BKE_brush_channel_curve_evaluate(BrushChannel *ch, float val, const float maxval)
|
||||
{
|
||||
BKE_brush_channel_curvemapping_get(&ch->curve, false);
|
||||
|
||||
return BKE_brush_curve_strength_ex(ch->curve.preset, ch->curve.curve, val, maxval);
|
||||
}
|
||||
|
||||
BrushChannelSet *BKE_brush_channelset_create()
|
||||
{
|
||||
BrushChannelSet *chset = (BrushChannelSet *)MEM_callocN(sizeof(BrushChannelSet),
|
||||
|
@ -482,13 +567,14 @@ ATTR_NO_OPT BrushChannelType *BKE_brush_builtin_channel_def_find(const char *nam
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname)
|
||||
ATTR_NO_OPT BrushChannel *BKE_brush_channelset_add_builtin(BrushChannelSet *chset,
|
||||
const char *idname)
|
||||
{
|
||||
BrushChannelType *def = BKE_brush_builtin_channel_def_find(idname);
|
||||
|
||||
if (!def) {
|
||||
printf("%s: Could not find brush %s\n", __func__, idname);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
namestack_push(__func__);
|
||||
|
@ -499,20 +585,25 @@ ATTR_NO_OPT void BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const
|
|||
BKE_brush_channelset_add(chset, ch);
|
||||
|
||||
namestack_pop(NULL);
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
bool BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname)
|
||||
BrushChannel *BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname)
|
||||
{
|
||||
namestack_push(__func__);
|
||||
|
||||
if (!BKE_brush_channelset_has(chset, idname)) {
|
||||
BKE_brush_channelset_add_builtin(chset, idname);
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
|
||||
|
||||
if (ch) {
|
||||
namestack_pop(NULL);
|
||||
return true;
|
||||
return ch;
|
||||
}
|
||||
|
||||
ch = BKE_brush_channelset_add_builtin(chset, idname);
|
||||
|
||||
namestack_pop(NULL);
|
||||
return false;
|
||||
return ch;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset,
|
||||
|
@ -1216,14 +1307,14 @@ BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool)
|
|||
ADDCH("strength");
|
||||
ADDCH("fset_slide");
|
||||
ADDCH("boundary_smooth");
|
||||
ADDCH("autosmooth_projection");
|
||||
ADDCH("projection");
|
||||
break;
|
||||
case SCULPT_TOOL_TOPOLOGY_RAKE:
|
||||
ADDCH("radius");
|
||||
ADDCH("strength");
|
||||
// ADDCH("fset_slide");
|
||||
// ADDCH("boundary_smooth");
|
||||
ADDCH("autosmooth_projection");
|
||||
ADDCH("projection");
|
||||
ADDCH("topology_rake_mode");
|
||||
break;
|
||||
case SCULPT_TOOL_DYNTOPO:
|
||||
|
@ -1235,7 +1326,10 @@ BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool)
|
|||
return command;
|
||||
}
|
||||
|
||||
static void float_set_uninherit(BrushChannelSet *chset, const char *channel, float val)
|
||||
#define float_set_uninherit(chset, channel, val) \
|
||||
_float_set_uninherit(chset, MAKE_BUILTIN_CH_NAME(channel), val)
|
||||
|
||||
static void _float_set_uninherit(BrushChannelSet *chset, const char *channel, float val)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, channel);
|
||||
|
||||
|
@ -1289,10 +1383,22 @@ ATTR_NO_OPT static void bke_builtin_commandlist_create_paint(Brush *brush,
|
|||
float autosmooth = BRUSHSET_GET_FLOAT(chset, autosmooth, mapdata);
|
||||
if (autosmooth > 0.0f) {
|
||||
cmd = BKE_brush_command_init(BKE_brush_commandlist_add(cl, chset, true), SCULPT_TOOL_SMOOTH);
|
||||
float_set_uninherit(cmd->params, "strength", autosmooth);
|
||||
float_set_uninherit(cmd->params, "radius", radius * autosmooth_scale);
|
||||
float_set_uninherit(cmd->params, "projection", autosmooth_projection);
|
||||
float_set_uninherit(cmd->params, "spacing", autosmooth_spacing);
|
||||
|
||||
BrushChannel *ch = BRUSHSET_ENSURE_BUILTIN(cmd->params, falloff_curve);
|
||||
BrushChannel *ch2 = BRUSHSET_LOOKUP(chset, autosmooth_falloff_curve);
|
||||
|
||||
if (ch2) {
|
||||
BKE_brush_channel_curve_assign(ch, &ch2->curve);
|
||||
ch->flag &= ~BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
else {
|
||||
ch->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
|
||||
float_set_uninherit(cmd->params, strength, autosmooth);
|
||||
float_set_uninherit(cmd->params, radius, radius * autosmooth_scale);
|
||||
float_set_uninherit(cmd->params, projection, autosmooth_projection);
|
||||
float_set_uninherit(cmd->params, spacing, autosmooth_spacing);
|
||||
}
|
||||
|
||||
float vcol_boundary = BKE_brush_channelset_get_float(chset, "vcol_boundary_factor", mapdata);
|
||||
|
@ -1301,9 +1407,10 @@ ATTR_NO_OPT static void bke_builtin_commandlist_create_paint(Brush *brush,
|
|||
if (vcol_boundary > 0.0f) {
|
||||
cmd = BKE_brush_command_init(BKE_brush_commandlist_add(cl, chset, true),
|
||||
SCULPT_TOOL_VCOL_BOUNDARY);
|
||||
float_set_uninherit(cmd->params, "radius", radius * GETF("vcol_boundary_radius_scale"));
|
||||
float_set_uninherit(cmd->params, "spacing", GETF("vcol_boundary_spacing"));
|
||||
float_set_uninherit(cmd->params, "strength", vcol_boundary);
|
||||
|
||||
float_set_uninherit(cmd->params, radius, radius * GETF("vcol_boundary_radius_scale"));
|
||||
float_set_uninherit(cmd->params, spacing, GETF("vcol_boundary_spacing"));
|
||||
float_set_uninherit(cmd->params, strength, vcol_boundary);
|
||||
}
|
||||
|
||||
#undef GETF
|
||||
|
@ -1319,6 +1426,7 @@ ATTR_NO_OPT void BKE_builtin_commandlist_create(Brush *brush,
|
|||
BrushMappingData *mapdata)
|
||||
{
|
||||
BrushCommand *cmd;
|
||||
BrushChannel *ch;
|
||||
|
||||
/* add main tool */
|
||||
if (ELEM(tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) {
|
||||
|
@ -1340,6 +1448,17 @@ ATTR_NO_OPT void BKE_builtin_commandlist_create(Brush *brush,
|
|||
float autosmooth_projection = BKE_brush_channelset_get_float(
|
||||
chset, "autosmooth_projection", NULL);
|
||||
|
||||
bool is_cloth = tool = SCULPT_TOOL_CLOTH;
|
||||
is_cloth = is_cloth ||
|
||||
(ELEM(tool, SCULPT_TOOL_BOUNDARY, SCULPT_TOOL_POSE) &&
|
||||
BRUSHSET_GET_INT(chset, deform_target, mapdata) == BRUSH_DEFORM_TARGET_CLOTH_SIM);
|
||||
float cloth_radius_mul = 1.0f;
|
||||
|
||||
if (is_cloth && (ch = BRUSHSET_LOOKUP(chset, cloth_sim_limit))) {
|
||||
autosmooth_scale *= ch->fvalue;
|
||||
cloth_radius_mul = ch->fvalue;
|
||||
}
|
||||
|
||||
float autosmooth_spacing;
|
||||
|
||||
if (BKE_brush_channelset_get_int(chset, "autosmooth_use_spacing", mapdata)) {
|
||||
|
@ -1352,14 +1471,27 @@ ATTR_NO_OPT void BKE_builtin_commandlist_create(Brush *brush,
|
|||
float autosmooth = BKE_brush_channelset_get_float(chset, "autosmooth", mapdata);
|
||||
if (!no_autosmooth && autosmooth > 0.0f) {
|
||||
cmd = BKE_brush_command_init(BKE_brush_commandlist_add(cl, chset, true), SCULPT_TOOL_SMOOTH);
|
||||
float_set_uninherit(cmd->params, "strength", autosmooth);
|
||||
float_set_uninherit(cmd->params, "radius", radius * autosmooth_scale);
|
||||
float_set_uninherit(cmd->params, "projection", autosmooth_projection);
|
||||
float_set_uninherit(cmd->params, "spacing", autosmooth_spacing);
|
||||
|
||||
BrushChannel *ch = BRUSHSET_ENSURE_BUILTIN(cmd->params, falloff_curve);
|
||||
BrushChannel *ch2 = BRUSHSET_LOOKUP(chset, autosmooth_falloff_curve);
|
||||
|
||||
if (ch2) {
|
||||
BKE_brush_channel_curve_assign(ch, &ch2->curve);
|
||||
ch->flag &= ~BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
else {
|
||||
ch->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
|
||||
float_set_uninherit(cmd->params, strength, autosmooth);
|
||||
float_set_uninherit(cmd->params, radius, radius * autosmooth_scale);
|
||||
float_set_uninherit(cmd->params, projection, autosmooth_projection);
|
||||
float_set_uninherit(cmd->params, spacing, autosmooth_spacing);
|
||||
}
|
||||
|
||||
float topology_rake_scale = BKE_brush_channelset_get_float(
|
||||
chset, "topology_rake_radius_scale", mapdata);
|
||||
chset, "topology_rake_radius_scale", mapdata) *
|
||||
cloth_radius_mul;
|
||||
float topology_rake_projection = BKE_brush_channelset_get_float(
|
||||
chset, "topology_rake_projection", mapdata);
|
||||
|
||||
|
@ -1379,10 +1511,21 @@ ATTR_NO_OPT void BKE_builtin_commandlist_create(Brush *brush,
|
|||
cmd = BKE_brush_command_init(BKE_brush_commandlist_add(cl, chset, true),
|
||||
SCULPT_TOOL_TOPOLOGY_RAKE);
|
||||
|
||||
float_set_uninherit(cmd->params, "strength", topology_rake);
|
||||
float_set_uninherit(cmd->params, "radius", radius * topology_rake_scale);
|
||||
float_set_uninherit(cmd->params, "projection", topology_rake_projection);
|
||||
float_set_uninherit(cmd->params, "spacing", topology_rake_spacing);
|
||||
BrushChannel *ch = BRUSHSET_ENSURE_BUILTIN(cmd->params, falloff_curve);
|
||||
BrushChannel *ch2 = BRUSHSET_LOOKUP(chset, topology_rake_falloff_curve);
|
||||
|
||||
if (ch2) {
|
||||
BKE_brush_channel_curve_assign(ch, &ch2->curve);
|
||||
ch->flag &= ~BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
else {
|
||||
ch->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
|
||||
float_set_uninherit(cmd->params, strength, topology_rake);
|
||||
float_set_uninherit(cmd->params, radius, radius * topology_rake_scale);
|
||||
float_set_uninherit(cmd->params, projection, topology_rake_projection);
|
||||
float_set_uninherit(cmd->params, spacing, topology_rake_spacing);
|
||||
}
|
||||
|
||||
/* build dyntopo command */
|
||||
|
@ -1395,8 +1538,8 @@ ATTR_NO_OPT void BKE_builtin_commandlist_create(Brush *brush,
|
|||
|
||||
radius2 *= radius;
|
||||
|
||||
float_set_uninherit(cmd->params, "spacing", spacing);
|
||||
float_set_uninherit(cmd->params, "radius", radius2);
|
||||
float_set_uninherit(cmd->params, spacing, spacing);
|
||||
float_set_uninherit(cmd->params, radius, radius2);
|
||||
}
|
||||
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
|
@ -1417,6 +1560,12 @@ ATTR_NO_OPT void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannel
|
|||
|
||||
BLI_ghash_insert(chset->namemap, ch->idname, ch);
|
||||
|
||||
BLO_read_data_address(reader, &ch->curve.curve);
|
||||
if (ch->curve.curve) {
|
||||
BKE_curvemapping_blend_read(reader, ch->curve.curve);
|
||||
BKE_curvemapping_init(ch->curve.curve);
|
||||
}
|
||||
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
BrushMapping *mp = ch->mappings + i;
|
||||
|
||||
|
@ -1467,6 +1616,10 @@ ATTR_NO_OPT void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet
|
|||
|
||||
BrushChannel *ch;
|
||||
for (ch = chset->channels.first; ch; ch = ch->next) {
|
||||
if (ch->curve.curve) {
|
||||
BKE_curvemapping_blend_write(writer, ch->curve.curve);
|
||||
}
|
||||
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
BKE_brush_mapping_ensure_write(ch->mappings + i);
|
||||
BKE_curvemapping_blend_write(writer, ch->mappings[i].curve);
|
||||
|
|
|
@ -151,6 +151,15 @@ MAKE_FLOAT_EX_EX(idname1, name1, tooltip1, value1, min1, max1, smin1, smax1, pre
|
|||
#define MAKE_FLAGS(idname1, name1, tooltip1, value1, enumdef1) MAKE_FLAGS_EX(idname1, name1, tooltip1, value1, enumdef1, 0)
|
||||
#define MAKE_ENUM(idname1, name1, tooltip1, value1, enumdef1) MAKE_ENUM_EX(idname1, name1, tooltip1, value1, enumdef1, 0)
|
||||
|
||||
#define MAKE_CURVE(idname1, name1, tooltip1, preset1)\
|
||||
{\
|
||||
.idname = #idname1,\
|
||||
.name = name1,\
|
||||
.tooltip = tooltip1,\
|
||||
.type = BRUSH_CHANNEL_CURVE,\
|
||||
.curve_preset = preset1,\
|
||||
},
|
||||
|
||||
/*
|
||||
This is where all the builtin brush channels are defined.
|
||||
That includes per-brush enums and bitflags!
|
||||
|
@ -632,6 +641,7 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
|
|||
ADDCH(autosmooth_spacing);
|
||||
ADDCH(autosmooth_use_spacing);
|
||||
ADDCH(autosmooth_projection);
|
||||
ADDCH(autosmooth_falloff_curve);
|
||||
|
||||
ADDCH(vcol_boundary_exponent);
|
||||
ADDCH(vcol_boundary_factor);
|
||||
|
@ -644,6 +654,7 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
|
|||
ADDCH(topology_rake_use_spacing);
|
||||
ADDCH(topology_rake_spacing);
|
||||
ADDCH(topology_rake_projection);
|
||||
ADDCH(topology_rake_falloff_curve);
|
||||
|
||||
ADDCH(hardness);
|
||||
ADDCH(tip_roundness);
|
||||
|
@ -975,6 +986,19 @@ void BKE_brush_check_toolsettings(Sculpt *sd)
|
|||
ADDCH(automasking);
|
||||
ADDCH(topology_rake_mode);
|
||||
|
||||
ADDCH(autosmooth);
|
||||
ADDCH(autosmooth_projection);
|
||||
ADDCH(autosmooth_radius_scale);
|
||||
ADDCH(autosmooth_spacing);
|
||||
ADDCH(autosmooth_falloff_curve);
|
||||
|
||||
ADDCH(topology_rake_radius_scale);
|
||||
ADDCH(topology_rake_projection);
|
||||
ADDCH(topology_rake_use_spacing);
|
||||
ADDCH(topology_rake_spacing);
|
||||
ADDCH(topology_rake);
|
||||
ADDCH(topology_rake_falloff_curve);
|
||||
|
||||
ADDCH(vcol_boundary_exponent);
|
||||
ADDCH(vcol_boundary_factor);
|
||||
ADDCH(vcol_boundary_radius_scale);
|
||||
|
|
|
@ -9096,6 +9096,13 @@ ATTR_NO_OPT static void SCULPT_run_command_list(
|
|||
for (int step = 0; step < list->totcommand; step++) {
|
||||
BrushCommand *cmd = list->commands + step;
|
||||
|
||||
float radius = BRUSHSET_GET_FLOAT(cmd->params_final, radius, NULL);
|
||||
radius = paint_calc_object_space_radius(ss->cache->vc, ss->cache->true_location, radius);
|
||||
|
||||
ss->cache->radius = radius;
|
||||
ss->cache->radius_squared = radius * radius;
|
||||
radius_scale = 1.0f;
|
||||
|
||||
BKE_brush_channelset_free(cmd->params_mapped);
|
||||
cmd->params_mapped = BKE_brush_channelset_copy(cmd->params_final);
|
||||
BKE_brush_channelset_apply_mapping(cmd->params_mapped, &ss->cache->input_mapping);
|
||||
|
@ -9120,6 +9127,12 @@ ATTR_NO_OPT static void SCULPT_run_command_list(
|
|||
|
||||
*brush2 = *brush;
|
||||
|
||||
BrushChannel *ch = BRUSHSET_LOOKUP(cmd->params_final, falloff_curve);
|
||||
if (ch) {
|
||||
brush2->curve_preset = ch->curve.preset;
|
||||
brush2->curve = ch->curve.curve;
|
||||
}
|
||||
|
||||
// Load parameters into brush2 for compatibility with old code
|
||||
// Make sure to remove all pen pressure/tilt old code
|
||||
BKE_brush_channelset_compat_load(cmd->params_mapped, brush2, false);
|
||||
|
|
|
@ -1150,8 +1150,12 @@ ATTR_NO_OPT static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
|
|||
}
|
||||
BKE_pbvh_vertex_iter_end;
|
||||
|
||||
if (modified && weighted) {
|
||||
BKE_pbvh_node_mark_update_tri_area(data->nodes[n]);
|
||||
if (modified) {
|
||||
if (weighted) {
|
||||
BKE_pbvh_node_mark_update_tri_area(data->nodes[n]);
|
||||
}
|
||||
|
||||
BKE_pbvh_node_mark_update(data->nodes[n]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -40,6 +40,11 @@ typedef struct BrushMapping {
|
|||
int flag, type;
|
||||
} BrushMapping;
|
||||
|
||||
typedef struct BrushCurve {
|
||||
CurveMapping *curve;
|
||||
int preset, _pad[1]; // see eBrushCurvePreset, this differs from the one in BrushMappingDef
|
||||
} BrushCurve;
|
||||
|
||||
typedef struct BrushChannel {
|
||||
struct BrushChannel *next, *prev;
|
||||
|
||||
|
@ -51,6 +56,8 @@ typedef struct BrushChannel {
|
|||
float fvalue;
|
||||
int ivalue;
|
||||
float vector[4];
|
||||
BrushCurve curve;
|
||||
|
||||
BrushMapping mappings[5]; // should always be BRUSH_MAPPING_MAX
|
||||
|
||||
short type, ui_order;
|
||||
|
@ -109,5 +116,6 @@ enum {
|
|||
BRUSH_CHANNEL_BITMASK = 1 << 3,
|
||||
BRUSH_CHANNEL_BOOL = 1 << 4,
|
||||
BRUSH_CHANNEL_VEC3 = 1 << 5,
|
||||
BRUSH_CHANNEL_VEC4 = 1 << 6
|
||||
BRUSH_CHANNEL_VEC4 = 1 << 6,
|
||||
BRUSH_CHANNEL_CURVE = 1 << 7
|
||||
};
|
||||
|
|
|
@ -2088,6 +2088,20 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
|
|||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
}
|
||||
|
||||
const EnumPropertyItem brush_curve_preset_items[] = {
|
||||
{BRUSH_CURVE_CUSTOM, "CUSTOM", ICON_RNDCURVE, "Custom", ""},
|
||||
{BRUSH_CURVE_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
|
||||
{BRUSH_CURVE_SMOOTHER, "SMOOTHER", ICON_SMOOTHCURVE, "Smoother", ""},
|
||||
{BRUSH_CURVE_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", ""},
|
||||
{BRUSH_CURVE_ROOT, "ROOT", ICON_ROOTCURVE, "Root", ""},
|
||||
{BRUSH_CURVE_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", ""},
|
||||
{BRUSH_CURVE_LIN, "LIN", ICON_LINCURVE, "Linear", ""},
|
||||
{BRUSH_CURVE_POW4, "POW4", ICON_SHARPCURVE, "Sharper", ""},
|
||||
{BRUSH_CURVE_INVSQUARE, "INVSQUARE", ICON_INVERSESQUARECURVE, "Inverse Square", ""},
|
||||
{BRUSH_CURVE_CONSTANT, "CONSTANT", ICON_NOCURVE, "Constant", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static void rna_def_brush(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
@ -2250,20 +2264,6 @@ static void rna_def_brush(BlenderRNA *brna)
|
|||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem brush_curve_preset_items[] = {
|
||||
{BRUSH_CURVE_CUSTOM, "CUSTOM", ICON_RNDCURVE, "Custom", ""},
|
||||
{BRUSH_CURVE_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
|
||||
{BRUSH_CURVE_SMOOTHER, "SMOOTHER", ICON_SMOOTHCURVE, "Smoother", ""},
|
||||
{BRUSH_CURVE_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", ""},
|
||||
{BRUSH_CURVE_ROOT, "ROOT", ICON_ROOTCURVE, "Root", ""},
|
||||
{BRUSH_CURVE_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", ""},
|
||||
{BRUSH_CURVE_LIN, "LIN", ICON_LINCURVE, "Linear", ""},
|
||||
{BRUSH_CURVE_POW4, "POW4", ICON_SHARPCURVE, "Sharper", ""},
|
||||
{BRUSH_CURVE_INVSQUARE, "INVSQUARE", ICON_INVERSESQUARECURVE, "Inverse Square", ""},
|
||||
{BRUSH_CURVE_CONSTANT, "CONSTANT", ICON_NOCURVE, "Constant", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem brush_deformation_target_items[] = {
|
||||
{BRUSH_DEFORM_TARGET_GEOMETRY,
|
||||
"GEOMETRY",
|
||||
|
|
|
@ -147,6 +147,16 @@ PointerRNA rna_BrushMapping_curve_get(PointerRNA *ptr)
|
|||
return rna_pointer_inherit_refine(ptr, &RNA_CurveMapping, mapping->curve);
|
||||
}
|
||||
|
||||
PointerRNA rna_BrushCurve_curve_get(PointerRNA *ptr)
|
||||
{
|
||||
BrushCurve *curve = (BrushCurve *)ptr->data;
|
||||
|
||||
// make sure we can write to curve
|
||||
BKE_brush_channel_curve_ensure_write(curve);
|
||||
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_CurveMapping, curve->curve);
|
||||
}
|
||||
|
||||
int rna_BrushChannel_mappings_begin(CollectionPropertyIterator *iter, struct PointerRNA *ptr)
|
||||
{
|
||||
BrushChannel *ch = ptr->data;
|
||||
|
@ -345,8 +355,47 @@ EnumPropertyItem channel_types[] = {{BRUSH_CHANNEL_FLOAT, "FLOAT", ICON_NONE, "F
|
|||
{BRUSH_CHANNEL_BOOL, "BOOL", ICON_NONE, "Boolean"},
|
||||
{BRUSH_CHANNEL_VEC3, "VEC3", ICON_NONE, "Color3"},
|
||||
{BRUSH_CHANNEL_VEC4, "VEC4", ICON_NONE, "Color4"},
|
||||
{BRUSH_CHANNEL_CURVE, "CURVE", ICON_NONE, "Curve"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
// getting weird link errors here
|
||||
// extern const EnumPropertyItem brush_curve_preset_items[];
|
||||
|
||||
static const EnumPropertyItem brush_curve_preset_items[] = {
|
||||
{BRUSH_CURVE_CUSTOM, "CUSTOM", ICON_RNDCURVE, "Custom", ""},
|
||||
{BRUSH_CURVE_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
|
||||
{BRUSH_CURVE_SMOOTHER, "SMOOTHER", ICON_SMOOTHCURVE, "Smoother", ""},
|
||||
{BRUSH_CURVE_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", ""},
|
||||
{BRUSH_CURVE_ROOT, "ROOT", ICON_ROOTCURVE, "Root", ""},
|
||||
{BRUSH_CURVE_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", ""},
|
||||
{BRUSH_CURVE_LIN, "LIN", ICON_LINCURVE, "Linear", ""},
|
||||
{BRUSH_CURVE_POW4, "POW4", ICON_SHARPCURVE, "Sharper", ""},
|
||||
{BRUSH_CURVE_INVSQUARE, "INVSQUARE", ICON_INVERSESQUARECURVE, "Inverse Square", ""},
|
||||
{BRUSH_CURVE_CONSTANT, "CONSTANT", ICON_NOCURVE, "Constant", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
void RNA_def_brush_curve(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "BrushCurve", NULL);
|
||||
RNA_def_struct_sdna(srna, "BrushCurve");
|
||||
RNA_def_struct_ui_text(srna, "Brush Curve", "Brush Curve");
|
||||
|
||||
prop = RNA_def_property(srna, "curve_preset", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, "BrushCurve", "preset");
|
||||
RNA_def_property_enum_items(prop, brush_curve_preset_items);
|
||||
RNA_def_property_ui_text(prop, "Curve Preset", "");
|
||||
|
||||
prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "CurveMapping");
|
||||
RNA_def_property_ui_text(prop, "Curve Sensitivity", "Curve used for the sensitivity");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_pointer_funcs(prop, "rna_BrushCurve_curve_get", NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void RNA_def_brush_channel(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
@ -521,6 +570,10 @@ void RNA_def_brush_channel(BlenderRNA *brna)
|
|||
"rna_BrushChannel_enum_value_get_items");
|
||||
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
|
||||
|
||||
prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "BrushCurve");
|
||||
RNA_def_property_ui_text(prop, "Curve", "Curve");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
// PROP_ENUM_FLAG
|
||||
}
|
||||
|
||||
|
@ -560,6 +613,7 @@ void RNA_def_brush_channelset(BlenderRNA *brna)
|
|||
|
||||
void RNA_def_brush_engine(BlenderRNA *brna)
|
||||
{
|
||||
RNA_def_brush_curve(brna);
|
||||
RNA_def_brush_mapping(brna);
|
||||
RNA_def_brush_channel(brna);
|
||||
RNA_def_brush_channelset(brna);
|
||||
|
|
Loading…
Reference in New Issue