Sculpt: flushed out brush channel RNA and made basic UI

This commit is contained in:
Joseph Eagar 2021-09-18 12:10:14 -07:00
parent 7749b89d74
commit 1ca57bc5f4
8 changed files with 371 additions and 22 deletions

View File

@ -19,7 +19,6 @@
# <pep8 compliant>
from bpy.types import Menu
class UnifiedPaintPanel:
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
@ -97,6 +96,68 @@ class UnifiedPaintPanel:
return tool_settings.gpencil_vertex_paint
return None
@staticmethod
def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None, slider=False, header=False):
""" Generalized way of adding brush options to the UI,
along with their pen pressure setting and global toggle, if they exist. """
ch = brush.channels.channels[prop_name]
finalch = ch
l1 = layout
if ch.ui_expanded:
layout = layout.box().column() #.column() is a bit more compact
row = layout.row(align=True)
if text is None:
s = prop_name.lower().replace("_", " ").split(" ");
text = ''
for k in s:
text += k[0].upper() + k[1:] + " "
text = text.strip()
if ch.inherit:
sd = context.tool_settings.sculpt
#ensure channel exists in tool settings channel set
sd.channels.ensure(ch)
finalch = sd.channels.channels[prop_name]
row.prop(finalch, "value", icon=icon, text=text, slider=slider)
if pressure:
row.prop(finalch.mappings["PRESSURE"], "enabled", text="", icon="STYLUS_PRESSURE")
#if pressure_name:
# row.prop(brush, pressure_name, text="")
#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:
row.prop(ch, "inherit", text="", icon='BRUSHES_ALL')
row.prop(ch, "ui_expanded", text="", icon="TRIA_DOWN" if ch.ui_expanded else "TRIA_RIGHT")
if ch.ui_expanded:
for mp in finalch.mappings:
row2 = layout.row()
name = mp.type.lower()
if len(name) > 0:
name = name[0].upper() + name[1:]
else:
name = "name error"
row2.label(text=name)
row2.prop(mp, "enabled", text="", icon="STYLUS_PRESSURE")
row2.prop(mp, "ui_expanded", text="", icon="TRIA_DOWN" if mp.ui_expanded else "TRIA_RIGHT")
if mp.ui_expanded:
layout.template_curve_mapping(mp, "curve", brush=True)
#row2.prop(mp, "curve")
return row
@staticmethod
def prop_unified(
layout,
@ -972,11 +1033,16 @@ def brush_shared_settings(layout, context, brush, popover=False):
layout.row().prop(size_owner, "use_locked_size", expand=True)
layout.separator()
#if strength and mode == "SCULPT":
# layout.prop(brush.channels.channels["STRENGTH"], "value", text="Strength")
# pass
#elif strength:
if strength:
if 0 and strength:
UnifiedPaintPanel.channel_unified(
layout,
context,
brush,
"STRENGTH",
slider=True
)
layout.separator()
elif strength:
pressure_name = "use_pressure_strength" if strength_pressure else None
UnifiedPaintPanel.prop_unified(
layout,
@ -988,7 +1054,6 @@ def brush_shared_settings(layout, context, brush, popover=False):
slider=True,
)
layout.separator()
if direction:
layout.row().prop(brush, "direction", expand=True)

View File

@ -92,13 +92,19 @@ typedef struct BrushCommandList {
} BrushCommandList;
void BKE_brush_channel_free(BrushChannel *ch);
void BKE_brush_channel_copy(BrushChannel *dst, BrushChannel *src);
void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src);
void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def);
BrushChannelSet *BKE_brush_channelset_create();
BrushChannelSet *BKE_brush_channelset_create();
BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *src);
void BKE_brush_channelset_free(BrushChannelSet *chset);
// makes a copy of ch
void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch);
// checks is a channel with existing->idname exists; if not a copy of existing is made and inserted
void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset, BrushChannel *existing);
BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname);
bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname);
@ -123,6 +129,9 @@ BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool);
void BKE_builtin_commandlist_create(BrushChannelSet *chset, BrushCommandList *cl, int tool);
void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *cset);
void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet *cset);
void BKE_brush_mapping_copy_data(BrushMapping *dst, BrushMapping *src);
const char *BKE_brush_mapping_type_to_str(BrushMappingType mapping);
const char *BKE_brush_mapping_type_to_typename(BrushMappingType mapping);
#ifdef __cplusplus
}

View File

@ -8,6 +8,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_rect.h"
#include "DNA_brush_enums.h"
#include "DNA_brush_types.h"
@ -31,6 +32,31 @@
#define ICON_NONE -1
static bool check_corrupted_curve(BrushMapping *dst)
{
const float clip_size_x = BLI_rctf_size_x(&dst->curve.curr);
const float clip_size_y = BLI_rctf_size_y(&dst->curve.curr);
// fix corrupted curve
if (clip_size_x == 0.0f || clip_size_y == 0.0f) {
for (int i = 0; i < 4; i++) {
BKE_curvemapping_free_data(&dst->curve);
BKE_curvemapping_set_defaults(&dst->curve, 1, 0.0, 0.0, 1.0, 1.0);
BKE_curvemap_reset(&dst->curve.cm[i],
&(struct rctf){.xmin = 0, .ymin = 0.0, .xmax = 1.0, .ymax = 1.0},
CURVE_PRESET_LINE,
dst->flag & BRUSH_MAPPING_INVERT);
BKE_curvemapping_init(&dst->curve);
}
return false;
}
return true;
}
/*
Brush command lists.
@ -50,6 +76,7 @@ BrushChannelType brush_builtin_channels[] = {
.min = 0.001f,
.type = BRUSH_CHANNEL_FLOAT,
.max = 2048.0f,
.fvalue = 50.0f,
.soft_min = 0.1f,
.soft_max = 1024.0f,
.mappings = {
@ -62,6 +89,7 @@ BrushChannelType brush_builtin_channels[] = {
.min = -1.0f,
.type = BRUSH_CHANNEL_FLOAT,
.max = 4.0f,
.fvalue = 0.5f,
.soft_min = 0.0f,
.soft_max = 1.0f,
.mappings = {
@ -74,6 +102,7 @@ BrushChannelType brush_builtin_channels[] = {
.min = 0.001f,
.type = BRUSH_CHANNEL_FLOAT,
.max = 4.0f,
.fvalue = 0.1f,
.soft_min = 0.005f,
.soft_max = 2.0f,
.mappings = {
@ -110,6 +139,7 @@ BrushChannelType brush_builtin_channels[] = {
.type = BRUSH_CHANNEL_FLOAT,
.min = 0.0001f,
.max = 25.0f,
.fvalue = 1.0f,
.soft_min = 0.1f,
.soft_max = 4.0f,
.mappings = {
@ -122,6 +152,7 @@ BrushChannelType brush_builtin_channels[] = {
.type = BRUSH_CHANNEL_FLOAT,
.min = 0.0001f,
.max = 25.0f,
.fvalue = 1.0f,
.soft_min = 0.1f,
.soft_max = 4.0f,
.mappings = {
@ -134,6 +165,7 @@ BrushChannelType brush_builtin_channels[] = {
.type = BRUSH_CHANNEL_FLOAT,
.min = 0.0001f,
.max = 1.0f,
.fvalue = 1.0f,
.soft_min = 0.1f,
.soft_max = 1.0f,
.mappings = {
@ -215,12 +247,13 @@ void BKE_brush_channel_free(BrushChannel *ch)
}
}
ATTR_NO_OPT void BKE_brush_channel_copy(BrushChannel *dst, BrushChannel *src)
ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src)
{
*dst = *src;
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
BKE_curvemapping_copy_data(&dst->mappings[i].curve, &src->mappings[i].curve);
BKE_brush_mapping_copy_data(dst->mappings + i, src->mappings + i);
dst->mappings[i].type = i;
}
}
@ -241,6 +274,8 @@ ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
BrushMapping *map = ch->mappings + i;
CurveMapping *curve = &map->curve;
map->type = i;
memset(curve, 0, sizeof(*curve));
float min, max;
@ -262,9 +297,11 @@ ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
int slope = CURVEMAP_SLOPE_POSITIVE;
BKE_curvemapping_set_defaults(curve, 1, 0, min, 1, max);
for (int i = 0; i < 4; i++) {
BKE_curvemap_reset(&curve->cm[i],
&(struct rctf){.xmax = 0, .ymax = min, .xmax = 1, .ymax = max},
&(struct rctf){.xmin = 0, .ymin = min, .xmax = 1, .ymax = max},
mdef->curve,
slope);
}
@ -308,7 +345,7 @@ void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch)
chset->channels = MEM_recallocN(chset->channels, sizeof(BrushChannel) * chset->totchannel);
}
memcpy(chset->channels + chset->totchannel - 1, ch, sizeof(BrushChannel));
BKE_brush_channel_copy_data(chset->channels + chset->totchannel - 1, ch);
}
ATTR_NO_OPT BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname)
@ -391,6 +428,14 @@ bool BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idn
return false;
}
void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset, BrushChannel *existing)
{
if (BKE_brush_channelset_has(chset, existing->idname)) {
return;
}
BKE_brush_channelset_add(chset, existing);
}
#define ADDCH(name) BKE_brush_channelset_ensure_builtin(chset, name)
#define GETCH(name) BKE_brush_channelset_lookup(chset, name)
@ -411,7 +456,7 @@ void BKE_brush_channelset_merge(BrushChannelSet *dst,
}
BrushChannel ch2;
BKE_brush_channel_copy(&ch2, ch);
BKE_brush_channel_copy_data(&ch2, ch);
BKE_brush_channelset_add(chset, &ch2);
}
}
@ -425,7 +470,7 @@ void BKE_brush_channelset_merge(BrushChannelSet *dst,
if (ch->flag & BRUSH_CHANNEL_INHERIT) {
BKE_brush_channel_free(mch);
BKE_brush_channel_copy(mch, pch);
BKE_brush_channel_copy_data(mch, pch);
continue;
}
@ -435,6 +480,28 @@ void BKE_brush_channelset_merge(BrushChannelSet *dst,
}
}
BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *src)
{
BrushChannelSet *chset = BKE_brush_channelset_create();
*chset = *src;
if (!chset->totchannel) {
return chset;
}
chset->channels = MEM_calloc_arrayN(
src->totchannel, sizeof(BrushChannel), "chset->channels copied");
for (int i = 0; i < chset->totchannel; i++) {
BrushChannel *ch = chset->channels + i;
BKE_brush_channel_copy_data(ch, src->channels + i);
}
return chset;
}
void BKE_brush_resolve_channels(Brush *brush, Sculpt *sd)
{
if (brush->channels_final) {
@ -655,6 +722,12 @@ void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *cset)
for (int j = 0; j < BRUSH_MAPPING_MAX; j++) {
BKE_curvemapping_blend_read(reader, &ch->mappings[j].curve);
BKE_curvemapping_init(&ch->mappings[j].curve);
check_corrupted_curve(ch->mappings + j);
// paranoia check to make sure BrushMapping.type is correct
ch->mappings[j].type = j;
}
ch->def = BKE_brush_builtin_channel_def_find(ch->idname);
@ -680,6 +753,59 @@ void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet *cset)
}
}
const char *BKE_brush_mapping_type_to_str(BrushMappingType mapping)
{
switch (mapping) {
case BRUSH_MAPPING_PRESSURE:
return "Pressure";
case BRUSH_MAPPING_ANGLE:
return "Angle";
case BRUSH_MAPPING_SPEED:
return "Speed";
case BRUSH_MAPPING_XTILT:
return "X Tilt";
case BRUSH_MAPPING_YTILT:
return "Y Tilt";
case BRUSH_MAPPING_MAX:
return "Error";
}
return "Error";
}
const char *BKE_brush_mapping_type_to_typename(BrushMappingType mapping)
{
switch (mapping) {
case BRUSH_MAPPING_PRESSURE:
return "PRESSURE";
case BRUSH_MAPPING_ANGLE:
return "ANGLE";
case BRUSH_MAPPING_SPEED:
return "SPEED";
case BRUSH_MAPPING_XTILT:
return "XTILT";
case BRUSH_MAPPING_YTILT:
return "YTILT";
case BRUSH_MAPPING_MAX:
return "Error";
}
return "Error";
}
void BKE_brush_mapping_copy_data(BrushMapping *dst, BrushMapping *src)
{
// do not copy .type
int type = dst->type;
*dst = *src;
dst->type = type;
BKE_curvemapping_copy_data(&dst->curve, &src->curve);
BKE_curvemapping_init(&dst->curve);
check_corrupted_curve(dst);
}
/* clang-format on */
/* idea for building built-in preset node graphs:

View File

@ -1060,6 +1060,9 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_data_address(reader, &sce->toolsettings->sculpt->channels);
BKE_brush_channelset_read(reader, sce->toolsettings->sculpt->channels);
}
else {
sce->toolsettings->sculpt->channels = BKE_brush_channelset_create();
}
/* relink grease pencil interpolation curves */
BLO_read_data_address(reader, &sce->toolsettings->gp_interpolate.custom_ipo);
@ -1608,6 +1611,14 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
}
if (ts->sculpt) {
ts->sculpt = MEM_dupallocN(ts->sculpt);
if (ts->sculpt->channels) {
ts->sculpt->channels = BKE_brush_channelset_copy(ts->sculpt->channels);
}
else {
ts->sculpt->channels = BKE_brush_channelset_create();
}
BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag);
}
if (ts->uvsculpt) {
@ -1663,6 +1674,11 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
}
if (toolsettings->sculpt) {
BKE_paint_free(&toolsettings->sculpt->paint);
if (toolsettings->sculpt->channels) {
BKE_brush_channelset_free(toolsettings->sculpt->channels);
}
MEM_freeN(toolsettings->sculpt);
}
if (toolsettings->uvsculpt) {

View File

@ -7193,7 +7193,7 @@ static bool ui_numedit_but_CURVE(uiBlock *block,
return changed;
}
static int ui_do_but_CURVE(
ATTR_NO_OPT static int ui_do_but_CURVE(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
bool changed = false;

View File

@ -30,7 +30,7 @@ typedef struct BrushMapping {
float factor;
short blendmode;
short input_channel;
int flag, _pad[1];
int flag, type;
} BrushMapping;
typedef struct BrushChannel {
@ -52,17 +52,21 @@ typedef struct BrushChannelSet {
} BrushChannelSet;
// mapping flags
enum { BRUSH_MAPPING_ENABLED = 1 << 0, BRUSH_MAPPING_INVERT = 1 << 1 };
enum {
BRUSH_MAPPING_ENABLED = 1 << 0,
BRUSH_MAPPING_INVERT = 1 << 1,
BRUSH_MAPPING_UI_EXPANDED = 1 << 2
};
// mapping types
enum {
typedef enum {
BRUSH_MAPPING_PRESSURE = 0,
BRUSH_MAPPING_XTILT = 1,
BRUSH_MAPPING_YTILT = 2,
BRUSH_MAPPING_ANGLE = 3,
BRUSH_MAPPING_SPEED = 4,
BRUSH_MAPPING_MAX = 5 // see BrushChannel.mappings
};
} BrushMappingType;
static_assert(offsetof(BrushChannel, type) - offsetof(BrushChannel, mappings) ==
sizeof(BrushMapping) * BRUSH_MAPPING_MAX,
@ -72,7 +76,8 @@ static_assert(offsetof(BrushChannel, type) - offsetof(BrushChannel, mappings) ==
enum {
BRUSH_CHANNEL_INHERIT = 1 << 0,
BRUSH_CHANNEL_INHERIT_IF_UNSET = 1 << 1,
BRUSH_CHANNEL_NO_MAPPINGS = 1 << 2
BRUSH_CHANNEL_NO_MAPPINGS = 1 << 2,
BRUSH_CHANNEL_UI_EXPANDED = 1 << 3
};
// BrushChannelType->type

View File

@ -29,6 +29,7 @@
#include "DNA_workspace_types.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@ -38,6 +39,7 @@
#include "IMB_imbuf.h"
#include "BKE_brush_engine.h"
#include "BKE_colortools.h"
#include "DNA_sculpt_brush_types.h"
#include "WM_types.h"
@ -61,7 +63,7 @@ int rna_BrushChannelSet_channels_assignint(struct PointerRNA *ptr,
BrushChannel *ch = chset->channels + key;
BrushChannel *src = assign_ptr->data;
BKE_brush_channel_copy(ch, src);
BKE_brush_channel_copy_data(ch, src);
return 1;
}
@ -97,8 +99,102 @@ void rna_BrushChannel_value_range(
*soft_max = 1.0f;
}
}
PointerRNA rna_BrushMapping_curve_get(PointerRNA *ptr)
{
BrushMapping *mapping = (BrushMapping *)ptr->data;
return rna_pointer_inherit_refine(ptr, &RNA_CurveMapping, &mapping->curve);
}
int rna_BrushChannel_mappings_begin(CollectionPropertyIterator *iter, struct PointerRNA *ptr)
{
BrushChannel *ch = ptr->data;
rna_iterator_array_begin(
iter, ch->mappings, sizeof(BrushMapping), BRUSH_MAPPING_MAX, false, NULL);
return 1;
}
int rna_BrushChannel_mappings_assignint(struct PointerRNA *ptr,
int key,
const struct PointerRNA *assign_ptr)
{
BrushChannel *ch = ptr->data;
BrushMapping *dst = ch->mappings + key;
BrushMapping *src = assign_ptr->data;
BKE_brush_mapping_copy_data(dst, src);
return 1;
}
int rna_BrushChannel_mappings_lookupstring(PointerRNA *rna, const char *key, PointerRNA *r_ptr)
{
BrushChannel *ch = (BrushChannel *)rna->data;
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
if (STREQ(key, BKE_brush_mapping_type_to_typename(i))) {
if (r_ptr) {
*r_ptr = rna_pointer_inherit_refine(rna, &RNA_BrushMapping, ch->mappings + i);
}
return 1;
}
}
return 0;
}
int rna_BrushChannel_mappings_length(PointerRNA *ptr)
{
return BRUSH_MAPPING_MAX;
}
#endif
static EnumPropertyItem mapping_type_items[] = {
{BRUSH_MAPPING_PRESSURE, "PRESSURE", ICON_NONE, "Pressure"},
{BRUSH_MAPPING_XTILT, "XTILT", ICON_NONE, "X Tilt"},
{BRUSH_MAPPING_YTILT, "YTILT", ICON_NONE, "Y Tilt"},
{BRUSH_MAPPING_ANGLE, "ANGLE", ICON_NONE, "Angle"},
{BRUSH_MAPPING_SPEED, "SPEED", ICON_NONE, "Speed"},
{-1, NULL, -1, -1},
};
void RNA_def_brush_mapping(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "BrushMapping", NULL);
RNA_def_struct_sdna(srna, "BrushMapping");
RNA_def_struct_ui_text(srna, "Brush Mapping", "Brush Mapping");
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_BrushMapping_curve_get", NULL, NULL, NULL);
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, "BrushMapping", "type");
RNA_def_property_enum_items(prop, mapping_type_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Type", "Channel Type");
prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushMapping", "flag", BRUSH_MAPPING_ENABLED);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Enabled", "Input Mapping Is Enabled");
prop = RNA_def_property(srna, "ui_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushMapping", "flag", BRUSH_MAPPING_UI_EXPANDED);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Expanded", "View advanced properties");
}
extern BrushChannelType *brush_builtin_channels;
extern const int builtin_channel_len;
@ -148,21 +244,46 @@ void RNA_def_brush_channel(BlenderRNA *brna)
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Inherit", "Inherit from scene defaults");
prop = RNA_def_property(srna, "ui_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushChannel", "flag", BRUSH_CHANNEL_UI_EXPANDED);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Expanded", "View advanced properties");
prop = RNA_def_property(srna, "inherit_if_unset", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushChannel", "flag", BRUSH_CHANNEL_INHERIT_IF_UNSET);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Inherit If Unset", "Combine with default settings");
prop = RNA_def_property(srna, "mappings", PROP_COLLECTION, PROP_NONE);
// RNA_def_property_collection_sdna(prop, "BrushChannel", "mappings", NULL);
RNA_def_property_collection_funcs(prop,
"rna_BrushChannel_mappings_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_get",
"rna_BrushChannel_mappings_length",
NULL,
"rna_BrushChannel_mappings_lookupstring",
"rna_BrushChannel_mappings_assignint");
RNA_def_property_struct_type(prop, "BrushMapping");
}
void RNA_def_brush_channelset(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
srna = RNA_def_struct(brna, "BrushChannelSet", NULL);
RNA_def_struct_sdna(srna, "BrushChannelSet");
RNA_def_struct_ui_text(srna, "Channel Set", "Brush Channel Collection");
func = RNA_def_function(srna, "ensure", "BKE_brush_channelset_ensure_existing");
parm = RNA_def_pointer(
func, "channel", "BrushChannel", "", "Ensure a copy of channel exists in this channel set");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
prop = RNA_def_property(srna, "channels", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "channels", "totchannel");
RNA_def_property_collection_funcs(prop,
@ -181,6 +302,7 @@ void RNA_def_brush_channelset(BlenderRNA *brna)
void RNA_def_brush_engine(BlenderRNA *brna)
{
RNA_def_brush_mapping(brna);
RNA_def_brush_channel(brna);
RNA_def_brush_channelset(brna);
}

View File

@ -830,6 +830,12 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_Sculpt_path");
RNA_def_struct_ui_text(srna, "Sculpt", "");
prop = RNA_def_property(srna, "channels", PROP_POINTER, 0);
RNA_def_property_pointer_sdna(prop, NULL, "channels");
RNA_def_property_struct_type(prop, "BrushChannelSet");
RNA_def_property_ui_text(prop, "Channels", "");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "radial_symmetry", PROP_INT, PROP_XYZ);
RNA_def_property_int_sdna(prop, NULL, "radial_symm");
RNA_def_property_int_default(prop, 1);