Sculpt: brush engine stuff
BrushChannels are now stored in linked lists instead of simple arrays. This helps to avoid memory corruption. I had originally wanted to be able to pass BrushChannels by value, but that doesn't really work since they heap allocd data (the input mapping curves).
This commit is contained in:
parent
b3ed969b86
commit
336b263b56
|
@ -137,7 +137,7 @@ class UnifiedPaintPanel:
|
|||
if ch.inherit:
|
||||
sd = context.tool_settings.sculpt
|
||||
#ensure channel exists in tool settings channel set
|
||||
sd.channels.ensure(ch, queue=True)
|
||||
sd.channels.ensure(ch)
|
||||
|
||||
finalch = sd.channels.channels[prop_name]
|
||||
|
||||
|
|
|
@ -73,18 +73,26 @@ typedef struct BrushMappingData {
|
|||
#define MAX_BRUSH_ENUM_DEF 32
|
||||
|
||||
typedef struct BrushEnumDef {
|
||||
EnumPropertyItem items[MAX_BRUSH_ENUM_DEF];
|
||||
int value;
|
||||
const char identifier[64];
|
||||
int icon;
|
||||
const char name[64];
|
||||
const char description[512];
|
||||
} BrushEnumDef;
|
||||
|
||||
typedef struct BrushChannelType {
|
||||
char name[32], idname[32], tooltip[512];
|
||||
char name[64], idname[64], tooltip[512];
|
||||
float min, max, soft_min, soft_max;
|
||||
BrushMappingPreset mappings;
|
||||
|
||||
int type, flag;
|
||||
int ivalue;
|
||||
float fvalue;
|
||||
BrushEnumDef enumdef; // if an enum type
|
||||
|
||||
BrushEnumDef enumdef[MAX_BRUSH_ENUM_DEF]; // for enum/bitmask types
|
||||
EnumPropertyItem *rna_enumdef;
|
||||
|
||||
bool user_defined;
|
||||
} BrushChannelType;
|
||||
|
||||
typedef struct BrushCommand {
|
||||
|
@ -98,6 +106,7 @@ typedef struct BrushCommandList {
|
|||
int totcommand;
|
||||
} BrushCommandList;
|
||||
|
||||
void BKE_brush_channel_free_data(BrushChannel *ch);
|
||||
void BKE_brush_channel_free(BrushChannel *ch);
|
||||
void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src);
|
||||
void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def);
|
||||
|
@ -106,14 +115,22 @@ 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);
|
||||
void BKE_brush_channelset_queue(BrushChannelSet *chset, BrushChannel *ch);
|
||||
|
||||
// makes a copy of ch
|
||||
void BKE_brush_channelset_add_duplicate(BrushChannelSet *chset, BrushChannel *ch);
|
||||
|
||||
// does not add to namemap ghash
|
||||
void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *ch);
|
||||
|
||||
// does not free ch or its data
|
||||
void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChannel *ch);
|
||||
|
||||
// does not free ch or its data
|
||||
bool BKE_brush_channelset_remove_named(BrushChannelSet *chset, const char *idname);
|
||||
|
||||
// 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,
|
||||
bool queue);
|
||||
void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset, BrushChannel *existing);
|
||||
|
||||
BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname);
|
||||
|
||||
|
@ -193,6 +210,7 @@ void BKE_brush_channelset_compat_load(BrushChannelSet *chset,
|
|||
|
||||
// merge in channels the ui requested
|
||||
void BKE_brush_apply_queued_channels(BrushChannelSet *chset, bool do_override);
|
||||
void BKE_brush_channeltype_rna_check(BrushChannelType *def);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -315,6 +315,7 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
|
||||
if (brush->channels) {
|
||||
BLO_read_data_address(reader, &brush->channels);
|
||||
|
||||
BKE_brush_channelset_read(reader, brush->channels);
|
||||
BKE_brush_builtin_patch(brush, brush->sculpt_tool);
|
||||
}
|
||||
|
@ -1798,12 +1799,12 @@ void BKE_brush_sculpt_reset(Brush *br)
|
|||
// BKE_brush_debug_print_state(br);
|
||||
|
||||
BKE_brush_builtin_create(br, br->sculpt_tool);
|
||||
BrushChannel *ch;
|
||||
|
||||
for (int i = 0; i < br->channels->totchannel; i++) {
|
||||
BrushChannel *ch = br->channels->channels + i;
|
||||
for (ch = (BrushChannel *)br->channels->channels.first; ch; ch = ch->next) {
|
||||
BrushChannelType *def = ch->def;
|
||||
|
||||
BKE_brush_channel_free(ch);
|
||||
BKE_brush_channel_free_data(ch);
|
||||
BKE_brush_channel_init(ch, def);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,12 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_mempool.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_smallhash.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_brush_enums.h"
|
||||
#include "DNA_brush_types.h"
|
||||
|
@ -38,7 +42,7 @@ static struct {
|
|||
} namestack[256] = {0};
|
||||
int namestack_i = 1;
|
||||
|
||||
ATTR_NO_OPT void namestack_push(const char *name)
|
||||
void namestack_push(const char *name)
|
||||
{
|
||||
namestack_i++;
|
||||
|
||||
|
@ -50,6 +54,7 @@ void namestack_pop()
|
|||
{
|
||||
namestack_i--;
|
||||
}
|
||||
|
||||
#define namestack_head_name strdup(namestack[namestack_i].tag)
|
||||
|
||||
void BKE_curvemapping_copy_data_tag_ex(CurveMapping *target,
|
||||
|
@ -59,7 +64,7 @@ void BKE_curvemapping_copy_data_tag_ex(CurveMapping *target,
|
|||
#define BKE_curvemapping_copy_data(dst, src) \
|
||||
BKE_curvemapping_copy_data_tag_ex(dst, src, namestack_head_name)
|
||||
|
||||
static bool check_corrupted_curve(BrushMapping *dst)
|
||||
ATTR_NO_OPT static bool check_corrupted_curve(BrushMapping *dst)
|
||||
{
|
||||
|
||||
const float clip_size_x = BLI_rctf_size_x(&dst->curve.curr);
|
||||
|
@ -100,13 +105,44 @@ generated from the node group inputs.
|
|||
extern BrushChannelType brush_builtin_channels[];
|
||||
extern const int brush_builtin_channel_len;
|
||||
|
||||
void BKE_brush_channel_free(BrushChannel *ch)
|
||||
ATTR_NO_OPT void BKE_brush_channeltype_rna_check(BrushChannelType *def)
|
||||
{
|
||||
if (def->rna_enumdef) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!def->user_defined) {
|
||||
// builtin channel types are never freed, don't use guardedalloc
|
||||
def->rna_enumdef = malloc(sizeof(EnumPropertyItem) * ARRAY_SIZE(def->enumdef));
|
||||
}
|
||||
|
||||
else {
|
||||
def->rna_enumdef = MEM_calloc_arrayN(
|
||||
ARRAY_SIZE(def->enumdef), sizeof(EnumPropertyItem), "def->rna_enumdef");
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(def->enumdef); i++) {
|
||||
def->rna_enumdef[i].value = def->enumdef[i].value;
|
||||
def->rna_enumdef[i].identifier = def->enumdef[i].identifier;
|
||||
def->rna_enumdef[i].icon = def->enumdef[i].icon;
|
||||
def->rna_enumdef[i].name = def->enumdef[i].name;
|
||||
def->rna_enumdef[i].description = def->enumdef[i].description;
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channel_free_data(BrushChannel *ch)
|
||||
{
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
BKE_curvemapping_free_data(&ch->mappings[i].curve);
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channel_free(BrushChannel *ch)
|
||||
{
|
||||
BKE_brush_channel_free_data(ch);
|
||||
MEM_freeN(ch);
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src)
|
||||
{
|
||||
// we have to free old curvemappings here,
|
||||
|
@ -116,8 +152,14 @@ ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *sr
|
|||
BKE_curvemapping_free_data(&dst->mappings[i].curve);
|
||||
}
|
||||
|
||||
// preserve linked list pointers
|
||||
void *next = dst->next, *prev = dst->prev;
|
||||
|
||||
*dst = *src;
|
||||
|
||||
dst->next = next;
|
||||
dst->prev = prev;
|
||||
|
||||
// clear curves in dst, see comment above
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
memset(&dst->mappings[i].curve, 0, sizeof(CurveMapping));
|
||||
|
@ -135,7 +177,12 @@ ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *sr
|
|||
|
||||
ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
|
||||
{
|
||||
// preserve linked list pointers
|
||||
BrushChannel *next = ch->next, *prev = ch->prev;
|
||||
|
||||
memset(ch, 0, sizeof(*ch));
|
||||
ch->next = next;
|
||||
ch->prev = prev;
|
||||
|
||||
strcpy(ch->name, def->name);
|
||||
strcpy(ch->idname, def->idname);
|
||||
|
@ -197,108 +244,137 @@ ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
|
|||
|
||||
BrushChannelSet *BKE_brush_channelset_create()
|
||||
{
|
||||
return (BrushChannelSet *)MEM_callocN(sizeof(BrushChannelSet), "BrushChannelSet");
|
||||
BrushChannelSet *chset = (BrushChannelSet *)MEM_callocN(sizeof(BrushChannelSet),
|
||||
"BrushChannelSet");
|
||||
|
||||
chset->namemap = BLI_ghash_str_new("BrushChannelSet");
|
||||
|
||||
return chset;
|
||||
}
|
||||
|
||||
void BKE_brush_apply_queued_channels(BrushChannelSet *chset, bool do_override)
|
||||
ATTR_NO_OPT void BKE_brush_channelset_free(BrushChannelSet *chset)
|
||||
{
|
||||
if (!chset->tot_queued_channel) {
|
||||
return;
|
||||
}
|
||||
BrushChannel *ch, *next;
|
||||
|
||||
for (int i = 0; i < chset->tot_queued_channel; i++) {
|
||||
BrushChannel *ch = chset->queued_channels;
|
||||
BLI_ghash_free(chset->namemap, NULL, NULL);
|
||||
|
||||
BrushChannel *exist = BKE_brush_channelset_lookup(chset, ch->idname);
|
||||
for (ch = chset->channels.first; ch; ch = next) {
|
||||
next = ch->next;
|
||||
|
||||
if (exist) {
|
||||
if (!do_override) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BKE_brush_channel_free(exist);
|
||||
*exist = *ch;
|
||||
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
BKE_brush_channelset_add(chset, ch);
|
||||
BKE_brush_channel_free(ch);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(chset->queued_channels);
|
||||
chset->queued_channels = NULL;
|
||||
chset->tot_queued_channel = NULL;
|
||||
}
|
||||
|
||||
void BKE_brush_channelset_free(BrushChannelSet *chset)
|
||||
{
|
||||
for (int step = 0; step < 2; step++) {
|
||||
BrushChannel *channels = step ? chset->queued_channels : chset->channels;
|
||||
int totchannel = step ? chset->tot_queued_channel : chset->totchannel;
|
||||
|
||||
if (channels) {
|
||||
for (int i = 0; i < totchannel; i++) {
|
||||
BKE_brush_channel_free(channels + i);
|
||||
}
|
||||
|
||||
MEM_freeN(channels);
|
||||
}
|
||||
BKE_brush_channel_free(ch);
|
||||
}
|
||||
|
||||
MEM_freeN(chset);
|
||||
}
|
||||
|
||||
void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch)
|
||||
static int _rng_seed = 0;
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *ch)
|
||||
{
|
||||
chset->totchannel++;
|
||||
BrushChannel *ch2;
|
||||
int i = 1;
|
||||
char idname[512];
|
||||
|
||||
if (!chset->channels) {
|
||||
chset->channels = MEM_callocN(sizeof(BrushChannel) * chset->totchannel, "chset->channels");
|
||||
}
|
||||
else {
|
||||
chset->channels = MEM_recallocN_id(
|
||||
chset->channels, sizeof(BrushChannel) * chset->totchannel, "chset->channels");
|
||||
strcpy(idname, ch->idname);
|
||||
bool bad = true;
|
||||
|
||||
RNG *rng = BLI_rng_new(_rng_seed++);
|
||||
|
||||
while (bad) {
|
||||
bad = false;
|
||||
|
||||
for (ch2 = chset->channels.first; ch2; ch2 = ch2->next) {
|
||||
if (ch2 != ch && STREQ(ch2->idname, ch->idname)) {
|
||||
bad = true;
|
||||
sprintf(idname, "%s %d", ch->idname, i);
|
||||
|
||||
printf("%s: name collision: %s\n", __func__, idname);
|
||||
|
||||
if (strlen(idname) > sizeof(ch->idname) - 1) {
|
||||
// we've hit the limit of idname;
|
||||
// start randomizing characters
|
||||
printf(
|
||||
"Cannot build unique name for brush channel; will have to randomize a few "
|
||||
"characters\n");
|
||||
printf(" requested idname: %s, ran out of buffer space at: %s\n", ch->idname, idname);
|
||||
|
||||
int j = BLI_rng_get_int(rng) % strlen(ch->idname);
|
||||
int chr = (BLI_rng_get_int(rng) % ('a' - 'A')) + 'A';
|
||||
|
||||
i = 0;
|
||||
ch->idname[j] = chr;
|
||||
strcpy(idname, ch->idname);
|
||||
}
|
||||
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namestack_push(__func__);
|
||||
BKE_brush_channel_copy_data(chset->channels + chset->totchannel - 1, ch);
|
||||
namestack_pop();
|
||||
BLI_strncpy(ch->idname, idname, sizeof(ch->idname));
|
||||
|
||||
// BLI_strncpy
|
||||
BLI_rng_free(rng);
|
||||
}
|
||||
|
||||
// used to avoid messing up pointers in ui
|
||||
void BKE_brush_channelset_queue(BrushChannelSet *chset, BrushChannel *ch)
|
||||
void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch)
|
||||
{
|
||||
chset->tot_queued_channel++;
|
||||
BKE_brush_channel_ensure_unque_name(chset, ch);
|
||||
|
||||
if (!chset->queued_channels) {
|
||||
chset->queued_channels = MEM_callocN(sizeof(BrushChannel) * chset->tot_queued_channel,
|
||||
"chset->channels");
|
||||
}
|
||||
else {
|
||||
chset->queued_channels = MEM_recallocN_id(chset->queued_channels,
|
||||
sizeof(BrushChannel) * chset->tot_queued_channel,
|
||||
"chset->queued_channels");
|
||||
BLI_addtail(&chset->channels, ch);
|
||||
BLI_ghash_insert(chset->namemap, ch->idname, ch);
|
||||
|
||||
chset->totchannel++;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channel_rename(BrushChannelSet *chset,
|
||||
BrushChannel *ch,
|
||||
const char *newname)
|
||||
{
|
||||
BLI_ghash_remove(chset->namemap, ch->idname, NULL, NULL);
|
||||
BLI_strncpy(ch->idname, newname, sizeof(ch->idname));
|
||||
BKE_brush_channel_ensure_unque_name(chset, ch);
|
||||
BLI_ghash_insert(chset->namemap, ch->idname, ch);
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChannel *ch)
|
||||
{
|
||||
BLI_ghash_remove(chset->namemap, ch->idname, NULL, NULL);
|
||||
BLI_remlink(&chset->channels, ch);
|
||||
|
||||
chset->totchannel--;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT bool BKE_brush_channelset_remove_named(BrushChannelSet *chset, const char *idname)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
|
||||
if (ch) {
|
||||
BKE_brush_channelset_remove(chset, ch);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channelset_add_duplicate(BrushChannelSet *chset, BrushChannel *ch)
|
||||
{
|
||||
BrushChannel *chnew = MEM_callocN(sizeof(*chnew), "brush channel copy");
|
||||
|
||||
namestack_push(__func__);
|
||||
BKE_brush_channel_copy_data(chset->queued_channels + chset->tot_queued_channel - 1, ch);
|
||||
|
||||
BKE_brush_channel_copy_data(chnew, ch);
|
||||
BKE_brush_channelset_add(chset, chnew);
|
||||
|
||||
namestack_pop();
|
||||
}
|
||||
|
||||
ATTR_NO_OPT BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname)
|
||||
{
|
||||
for (int i = 0; i < chset->totchannel; i++) {
|
||||
if (STREQ(chset->channels[i].idname, idname)) {
|
||||
return chset->channels + i;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return BLI_ghash_lookup(chset->namemap, idname);
|
||||
}
|
||||
|
||||
bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname)
|
||||
ATTR_NO_OPT bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname)
|
||||
{
|
||||
return BKE_brush_channelset_lookup(chset, idname) != NULL;
|
||||
}
|
||||
|
@ -324,7 +400,7 @@ BrushChannelType *BKE_brush_default_channel_def()
|
|||
return &brush_default_channel_type;
|
||||
}
|
||||
|
||||
void BKE_brush_channel_def_copy(BrushChannelType *dst, BrushChannelType *src)
|
||||
ATTR_NO_OPT void BKE_brush_channel_def_copy(BrushChannelType *dst, BrushChannelType *src)
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
@ -351,13 +427,12 @@ ATTR_NO_OPT void BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const
|
|||
return;
|
||||
}
|
||||
|
||||
BrushChannel ch = {0};
|
||||
|
||||
namestack_push(__func__);
|
||||
|
||||
BKE_brush_channel_init(&ch, def);
|
||||
BKE_brush_channelset_add(chset, &ch);
|
||||
BKE_brush_channel_free(&ch);
|
||||
BrushChannel *ch = MEM_callocN(sizeof(*ch), "BrushChannel");
|
||||
|
||||
BKE_brush_channel_init(ch, def);
|
||||
BKE_brush_channelset_add(chset, ch);
|
||||
|
||||
namestack_pop();
|
||||
}
|
||||
|
@ -376,26 +451,17 @@ bool BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idn
|
|||
return false;
|
||||
}
|
||||
|
||||
void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset,
|
||||
BrushChannel *existing,
|
||||
bool queue)
|
||||
ATTR_NO_OPT void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset,
|
||||
BrushChannel *existing)
|
||||
{
|
||||
if (BKE_brush_channelset_has(chset, existing->idname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
namestack_push(__func__);
|
||||
if (!queue) {
|
||||
BKE_brush_channelset_add(chset, existing);
|
||||
}
|
||||
else {
|
||||
BKE_brush_channelset_queue(chset, existing);
|
||||
}
|
||||
|
||||
BKE_brush_channelset_add_duplicate(chset, existing);
|
||||
namestack_pop();
|
||||
}
|
||||
#define ADDCH(name) BKE_brush_channelset_ensure_builtin(chset, name)
|
||||
#define GETCH(name) BKE_brush_channelset_lookup(chset, name)
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channelset_merge(BrushChannelSet *dst,
|
||||
BrushChannelSet *child,
|
||||
|
@ -406,9 +472,9 @@ ATTR_NO_OPT void BKE_brush_channelset_merge(BrushChannelSet *dst,
|
|||
|
||||
for (int step = 0; step < 2; step++) {
|
||||
BrushChannelSet *chset = step ? parent : child;
|
||||
BrushChannel *ch;
|
||||
|
||||
for (int i = 0; i < chset->totchannel; i++) {
|
||||
BrushChannel *ch = chset->channels + i;
|
||||
for (ch = chset->channels.first; ch; ch = ch->next) {
|
||||
BrushChannel *ch2 = BKE_brush_channelset_lookup(dst, ch->idname);
|
||||
|
||||
if (ch2 && step > 0) {
|
||||
|
@ -416,12 +482,7 @@ ATTR_NO_OPT void BKE_brush_channelset_merge(BrushChannelSet *dst,
|
|||
}
|
||||
|
||||
if (!ch2) {
|
||||
BrushChannel ch3 = {0};
|
||||
|
||||
BKE_brush_channel_copy_data(&ch3, ch);
|
||||
BKE_brush_channelset_add(dst, &ch3);
|
||||
|
||||
BKE_brush_channel_free(&ch3);
|
||||
BKE_brush_channelset_add_duplicate(dst, ch);
|
||||
}
|
||||
else {
|
||||
BKE_brush_channel_copy_data(ch2, ch);
|
||||
|
@ -429,8 +490,9 @@ ATTR_NO_OPT void BKE_brush_channelset_merge(BrushChannelSet *dst,
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < parent->totchannel; i++) {
|
||||
BrushChannel *pch = parent->channels + i;
|
||||
BrushChannel *pch;
|
||||
|
||||
for (pch = parent->channels.first; pch; pch = pch->next) {
|
||||
BrushChannel *mch = BKE_brush_channelset_lookup(dst, pch->idname);
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(child, pch->idname);
|
||||
|
||||
|
@ -451,25 +513,19 @@ ATTR_NO_OPT void BKE_brush_channelset_merge(BrushChannelSet *dst,
|
|||
namestack_pop();
|
||||
}
|
||||
|
||||
BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *src)
|
||||
ATTR_NO_OPT BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *src)
|
||||
{
|
||||
BrushChannelSet *chset = BKE_brush_channelset_create();
|
||||
|
||||
*chset = *src;
|
||||
|
||||
if (!chset->totchannel) {
|
||||
if (!src->totchannel) {
|
||||
return chset;
|
||||
}
|
||||
|
||||
namestack_push(__func__);
|
||||
|
||||
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);
|
||||
BrushChannel *ch;
|
||||
for (ch = src->channels.first; ch; ch = ch->next) {
|
||||
BKE_brush_channelset_add_duplicate(chset, ch);
|
||||
}
|
||||
|
||||
namestack_pop();
|
||||
|
@ -646,26 +702,6 @@ bool BKE_brush_channelset_set_float(BrushChannelSet *chset, char *idname, float
|
|||
return true;
|
||||
}
|
||||
|
||||
void BKE_brush_init_toolsettings(Sculpt *sd)
|
||||
{
|
||||
namestack_push(__func__);
|
||||
|
||||
if (sd->channels) {
|
||||
BKE_brush_channelset_free(sd->channels);
|
||||
}
|
||||
|
||||
BrushChannelSet *chset = sd->channels = BKE_brush_channelset_create();
|
||||
|
||||
ADDCH("RADIUS");
|
||||
ADDCH("STRENGTH");
|
||||
ADDCH("AUTOMASKING");
|
||||
ADDCH("TOPOLOGY_RAKE_MODE");
|
||||
ADDCH("DYNTOPO_DISABLED");
|
||||
ADDCH("DYNTOPO_DETAIL_RANGE");
|
||||
|
||||
namestack_pop();
|
||||
}
|
||||
|
||||
void BKE_brush_channelset_flag_clear(BrushChannelSet *chset, const char *channel, int flag)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, channel);
|
||||
|
@ -690,391 +726,6 @@ void BKE_brush_channelset_flag_set(BrushChannelSet *chset, const char *channel,
|
|||
ch->flag |= flag;
|
||||
}
|
||||
|
||||
// adds any missing channels to brushes
|
||||
void BKE_brush_builtin_patch(Brush *brush, int tool)
|
||||
{
|
||||
namestack_push(__func__);
|
||||
|
||||
if (!brush->channels) {
|
||||
brush->channels = BKE_brush_channelset_create();
|
||||
}
|
||||
|
||||
BrushChannelSet *chset = brush->channels;
|
||||
|
||||
ADDCH("RADIUS");
|
||||
ADDCH("SPACING");
|
||||
ADDCH("STRENGTH");
|
||||
|
||||
ADDCH("AUTOSMOOTH");
|
||||
ADDCH("AUTOSMOOTH_RADIUS_SCALE");
|
||||
ADDCH("AUTOSMOOTH_SPACING");
|
||||
ADDCH("AUTOSMOOTH_USE_SPACING");
|
||||
ADDCH("AUTOSMOOTH_PROJECTION");
|
||||
|
||||
ADDCH("TOPOLOGY_RAKE");
|
||||
ADDCH("TOPOLOGY_RAKE_MODE");
|
||||
ADDCH("TOPOLOGY_RAKE_RADIUS_SCALE");
|
||||
ADDCH("TOPOLOGY_RAKE_USE_SPACING");
|
||||
ADDCH("TOPOLOGY_RAKE_SPACING");
|
||||
ADDCH("TOPOLOGY_RAKE_PROJECTION");
|
||||
|
||||
ADDCH("HARDNESS");
|
||||
ADDCH("TIP_ROUNDNESS");
|
||||
ADDCH("NORMAL_RADIUS_FACTOR");
|
||||
|
||||
ADDCH("AUTOMASKING");
|
||||
|
||||
ADDCH("DYNTOPO_DISABLED");
|
||||
ADDCH("DYNTOPO_DETAIL_RANGE");
|
||||
ADDCH("DYNTOPO_OPS");
|
||||
|
||||
ADDCH("ACCUMULATE");
|
||||
ADDCH("ORIGINAL_NORMAL");
|
||||
ADDCH("ORIGINAL_PLANE");
|
||||
ADDCH("JITTER");
|
||||
ADDCH("JITTER_ABSOLUTE");
|
||||
ADDCH("USE_WEIGHTED_SMOOTH");
|
||||
ADDCH("PRESERVE_FACESET_BOUNDARY");
|
||||
ADDCH("HARD_EDGE_MODE");
|
||||
ADDCH("GRAB_SILHOUETTE");
|
||||
|
||||
ADDCH("PROJECTION");
|
||||
ADDCH("BOUNDARY_SMOOTH");
|
||||
ADDCH("FSET_SLIDE");
|
||||
|
||||
switch (tool) {
|
||||
case SCULPT_TOOL_DRAW: {
|
||||
break;
|
||||
}
|
||||
case SCULPT_TOOL_SLIDE_RELAX:
|
||||
ADDCH("SLIDE_DEFORM_TYPE");
|
||||
break;
|
||||
}
|
||||
|
||||
namestack_pop();
|
||||
}
|
||||
|
||||
void BKE_brush_init_scene_defaults(Sculpt *sd)
|
||||
{
|
||||
if (!sd->channels) {
|
||||
sd->channels = BKE_brush_channelset_create();
|
||||
}
|
||||
|
||||
BrushChannelSet *chset = sd->channels;
|
||||
}
|
||||
|
||||
void BKE_brush_builtin_create(Brush *brush, int tool)
|
||||
{
|
||||
namestack_push(__func__);
|
||||
|
||||
if (!brush->channels) {
|
||||
brush->channels = BKE_brush_channelset_create();
|
||||
}
|
||||
|
||||
BrushChannelSet *chset = brush->channels;
|
||||
|
||||
BKE_brush_builtin_patch(brush, tool);
|
||||
|
||||
GETCH("STRENGTH")->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
GETCH("RADIUS")->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
|
||||
switch (tool) {
|
||||
case SCULPT_TOOL_DRAW: {
|
||||
break;
|
||||
}
|
||||
case SCULPT_TOOL_DRAW_SHARP:
|
||||
GETCH("SPACING")->ivalue = 5;
|
||||
GETCH("RADIUS")->mappings[BRUSH_MAPPING_PRESSURE].blendmode = true;
|
||||
break;
|
||||
case SCULPT_TOOL_DISPLACEMENT_ERASER:
|
||||
case SCULPT_TOOL_FAIRING:
|
||||
case SCULPT_TOOL_SCENE_PROJECT:
|
||||
GETCH("SPACING")->ivalue = 10;
|
||||
GETCH("STRENGTH")->fvalue = 1.0f;
|
||||
GETCH("DYNTOPO_DISABLED")->ivalue = 1;
|
||||
break;
|
||||
case SCULPT_TOOL_SLIDE_RELAX:
|
||||
GETCH("SPACING")->ivalue = 10;
|
||||
GETCH("STRENGTH")->fvalue = 1.0f;
|
||||
GETCH("DYNTOPO_DISABLED")->ivalue = 1;
|
||||
GETCH("SLIDE_DEFORM_TYPE")->ivalue = BRUSH_SLIDE_DEFORM_DRAG;
|
||||
break;
|
||||
case SCULPT_TOOL_CLAY:
|
||||
GETCH("RADIUS")->mappings[BRUSH_MAPPING_PRESSURE].flag |= BRUSH_MAPPING_ENABLED;
|
||||
GETCH("SPACING")->ivalue = 3;
|
||||
GETCH("AUTOSMOOTH")->fvalue = 0.25f;
|
||||
GETCH("NORMAL_RADIUS_FACTOR")->fvalue = 0.75f;
|
||||
GETCH("HARDNESS")->fvalue = 0.65;
|
||||
break;
|
||||
case SCULPT_TOOL_TWIST:
|
||||
GETCH("STRENGTH")->fvalue = 0.5f;
|
||||
GETCH("NORMAL_RADIUS_FACTOR")->fvalue = 1.0f;
|
||||
GETCH("SPACING")->ivalue = 6;
|
||||
GETCH("HARDNESS")->fvalue = 0.5;
|
||||
break;
|
||||
case SCULPT_TOOL_CLAY_STRIPS: {
|
||||
GETCH("RADIUS")->mappings[BRUSH_MAPPING_PRESSURE].flag |= BRUSH_MAPPING_ENABLED;
|
||||
GETCH("TIP_ROUNDNESS")->fvalue = 0.18f;
|
||||
GETCH("NORMAL_RADIUS_FACTOR")->fvalue = 1.35f;
|
||||
GETCH("STRENGTH")->fvalue = 0.8f;
|
||||
GETCH("ACCUMULATE")->ivalue = 1;
|
||||
|
||||
CurveMapping *curve = &GETCH("RADIUS")->mappings[BRUSH_MAPPING_PRESSURE].curve;
|
||||
CurveMap *cuma = curve->cm;
|
||||
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.55f;
|
||||
BKE_curvemap_insert(cuma, 0.5f, 0.7f);
|
||||
cuma->curve[2].x = 1.0f;
|
||||
cuma->curve[2].y = 1.0f;
|
||||
BKE_curvemapping_changed(curve, true);
|
||||
|
||||
cuma = curve->cm;
|
||||
BKE_curvemap_insert(cuma, 0.6f, 0.25f);
|
||||
BKE_curvemapping_changed(curve, true);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// implement me!
|
||||
// BKE_brush_channelset_free(chset);
|
||||
// brush->channels = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
namestack_pop();
|
||||
}
|
||||
|
||||
#ifdef FLOAT
|
||||
# undef FLOAT
|
||||
#endif
|
||||
#ifdef INT
|
||||
# undef INT
|
||||
#endif
|
||||
#ifdef BOOL
|
||||
# undef BOOL
|
||||
#endif
|
||||
|
||||
#define FLOAT BRUSH_CHANNEL_FLOAT
|
||||
#define INT BRUSH_CHANNEL_INT
|
||||
#define BOOL BRUSH_CHANNEL_BOOL
|
||||
#define FLOAT3 BRUSH_CHANNEL_VEC3
|
||||
#define FLOAT4 BRUSH_CHANNEL_VEC4
|
||||
|
||||
/* clang-format off */
|
||||
#define DEF(brush_member, channel_name, btype, ctype) \
|
||||
{offsetof(Brush, brush_member), #channel_name, btype, ctype, sizeof(((Brush){0}).brush_member)},
|
||||
/* clang-format on */
|
||||
|
||||
typedef struct BrushSettingsMap {
|
||||
int brush_offset;
|
||||
const char *channel_name;
|
||||
int brush_type;
|
||||
int channel_type;
|
||||
int member_size;
|
||||
} BrushSettingsMap;
|
||||
|
||||
/* clang-format off */
|
||||
static BrushSettingsMap brush_settings_map[] = {
|
||||
DEF(size, RADIUS, INT, FLOAT)
|
||||
DEF(alpha, STRENGTH, FLOAT, FLOAT)
|
||||
DEF(autosmooth_factor, AUTOSMOOTH, FLOAT, FLOAT)
|
||||
DEF(autosmooth_projection, SMOOTH_PROJECTION, FLOAT, FLOAT)
|
||||
DEF(topology_rake_projection, TOPOLOGY_RAKE_PROJECTION, FLOAT, FLOAT)
|
||||
DEF(topology_rake_radius_factor, TOPOLOGY_RAKE_RADIUS_SCALE, FLOAT, FLOAT)
|
||||
DEF(topology_rake_spacing, TOPOLOGY_RAKE_SPACING, INT, FLOAT)
|
||||
DEF(topology_rake_factor, TOPOLOGY_RAKE, FLOAT, FLOAT)
|
||||
DEF(autosmooth_fset_slide, FSET_SLIDE, FLOAT, FLOAT)
|
||||
DEF(boundary_smooth_factor, BOUNDARY_SMOOTH, FLOAT, FLOAT)
|
||||
DEF(autosmooth_radius_factor, AUTOSMOOTH_RADIUS_SCALE, FLOAT, FLOAT)
|
||||
DEF(normal_weight, NORMAL_WEIGHT, FLOAT, FLOAT)
|
||||
DEF(rake_factor, RAKE_FACTOR, FLOAT, FLOAT)
|
||||
DEF(weight, WEIGHT, FLOAT, FLOAT)
|
||||
DEF(jitter, JITTER, FLOAT, FLOAT)
|
||||
DEF(jitter_absolute, JITTER_ABSOLITE, INT, INT)
|
||||
DEF(smooth_stroke_radius, SMOOTH_STROKE_RADIUS, INT, FLOAT)
|
||||
DEF(smooth_stroke_factor, SMOOTH_STROKE_FACTOR, FLOAT, FLOAT)
|
||||
DEF(rate, RATE, FLOAT, FLOAT)
|
||||
DEF(flow, FLOW, FLOAT, FLOAT)
|
||||
DEF(wet_mix, WET_MIX, FLOAT, FLOAT)
|
||||
DEF(wet_persistence, WET_PERSISTENCE, FLOAT, FLOAT)
|
||||
DEF(density, DENSITY, FLOAT, FLOAT)
|
||||
DEF(tip_scale_x, TIP_SCALE_X, FLOAT, FLOAT)
|
||||
};
|
||||
static const int brush_settings_map_len = ARRAY_SIZE(brush_settings_map);
|
||||
|
||||
/* clang-format on */
|
||||
#undef DEF
|
||||
|
||||
typedef struct BrushFlagMap {
|
||||
int member_offset;
|
||||
char *channel_name;
|
||||
int flag;
|
||||
int member_size;
|
||||
} BrushFlagMap;
|
||||
|
||||
/* clang-format off */
|
||||
#define DEF(member, channel, flag)\
|
||||
{offsetof(Brush, member), #channel, flag, sizeof(((Brush){0}).member)},
|
||||
|
||||
BrushFlagMap brush_flags_map[] = {
|
||||
DEF(flag, ORIGINAL_NORMAL, BRUSH_ORIGINAL_NORMAL)
|
||||
DEF(flag, ORIGINAL_PLANE, BRUSH_ORIGINAL_PLANE)
|
||||
DEF(flag, ACCUMULATE, BRUSH_ACCUMULATE)
|
||||
DEF(flag2, USE_WEIGHTED_SMOOTH, BRUSH_SMOOTH_USE_AREA_WEIGHT)
|
||||
DEF(flag2, PRESERVE_FACESET_BOUNDARY, BRUSH_SMOOTH_PRESERVE_FACE_SETS)
|
||||
DEF(flag2, HARD_EDGE_MODE, BRUSH_HARD_EDGE_MODE)
|
||||
DEF(flag2, GRAB_SILHOUETTE, BRUSH_GRAB_SILHOUETTE)
|
||||
};
|
||||
int brush_flags_map_len = ARRAY_SIZE(brush_flags_map);
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
static ATTR_NO_OPT void do_coerce(
|
||||
int type1, void *ptr1, int size1, int type2, void *ptr2, int size2)
|
||||
{
|
||||
double val = 0;
|
||||
|
||||
switch (type1) {
|
||||
case BRUSH_CHANNEL_FLOAT:
|
||||
val = *(float *)ptr1;
|
||||
break;
|
||||
case BRUSH_CHANNEL_INT:
|
||||
case BRUSH_CHANNEL_ENUM:
|
||||
case BRUSH_CHANNEL_BITMASK:
|
||||
case BRUSH_CHANNEL_BOOL:
|
||||
switch (size1) {
|
||||
case 1:
|
||||
val = (double)*(char *)ptr1;
|
||||
break;
|
||||
case 2:
|
||||
val = (double)*(unsigned short *)ptr1;
|
||||
break;
|
||||
case 4:
|
||||
val = (double)*(int *)ptr1;
|
||||
break;
|
||||
case 8:
|
||||
val = (double)*(int64_t *)ptr1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type2) {
|
||||
case BRUSH_CHANNEL_FLOAT:
|
||||
*(float *)ptr2 = (float)val;
|
||||
break;
|
||||
case BRUSH_CHANNEL_INT:
|
||||
case BRUSH_CHANNEL_ENUM:
|
||||
case BRUSH_CHANNEL_BITMASK:
|
||||
case BRUSH_CHANNEL_BOOL: {
|
||||
switch (size2) {
|
||||
case 1:
|
||||
*(char *)ptr2 = (char)val;
|
||||
break;
|
||||
case 2:
|
||||
*(unsigned short *)ptr2 = (unsigned short)val;
|
||||
break;
|
||||
case 4:
|
||||
*(int *)ptr2 = (int)val;
|
||||
break;
|
||||
case 8:
|
||||
*(int64_t *)ptr2 = (int64_t)val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *get_channel_value_pointer(BrushChannel *ch, int *r_data_size)
|
||||
{
|
||||
*r_data_size = 4;
|
||||
|
||||
switch (ch->type) {
|
||||
case BRUSH_CHANNEL_FLOAT:
|
||||
return &ch->fvalue;
|
||||
case BRUSH_CHANNEL_INT:
|
||||
case BRUSH_CHANNEL_ENUM:
|
||||
case BRUSH_CHANNEL_BITMASK:
|
||||
case BRUSH_CHANNEL_BOOL:
|
||||
return &ch->ivalue;
|
||||
case BRUSH_CHANNEL_VEC3:
|
||||
*r_data_size = sizeof(float) * 3;
|
||||
printf("implement me!\n");
|
||||
return NULL;
|
||||
case BRUSH_CHANNEL_VEC4:
|
||||
*r_data_size = sizeof(float) * 4;
|
||||
printf("implement me!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channelset_compat_load(BrushChannelSet *chset,
|
||||
Brush *brush,
|
||||
bool brush_to_channels)
|
||||
{
|
||||
for (int i = 0; i < brush_flags_map_len; i++) {
|
||||
BrushFlagMap *mf = brush_flags_map + i;
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, mf->channel_name);
|
||||
|
||||
if (!ch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char *ptr = (char *)brush;
|
||||
ptr += mf->member_offset;
|
||||
|
||||
switch (mf->member_size) {
|
||||
case 1: {
|
||||
char *f = (char *)ptr;
|
||||
ch->ivalue = (*f & mf->flag) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
ushort *f = (ushort *)ptr;
|
||||
ch->ivalue = (*f & mf->flag) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
uint *f = (uint *)ptr;
|
||||
ch->ivalue = (*f & mf->flag) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
uint64_t *f = (uint64_t *)ptr;
|
||||
ch->ivalue = (*f & mf->flag) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < brush_settings_map_len; i++) {
|
||||
BrushSettingsMap *mp = brush_settings_map + i;
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, mp->channel_name);
|
||||
|
||||
if (!ch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char *bptr = (char *)brush;
|
||||
bptr += mp->brush_offset;
|
||||
|
||||
int csize;
|
||||
void *cptr = get_channel_value_pointer(ch, &csize);
|
||||
|
||||
if (brush_to_channels) {
|
||||
do_coerce(mp->brush_type, bptr, mp->member_size, ch->type, cptr, csize);
|
||||
}
|
||||
else {
|
||||
do_coerce(ch->type, cptr, csize, mp->brush_type, bptr, mp->member_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BrushCommandList *BKE_brush_commandlist_create()
|
||||
{
|
||||
return MEM_callocN(sizeof(BrushCommandList), "BrushCommandList");
|
||||
|
@ -1116,10 +767,12 @@ BrushCommand *BKE_brush_commandlist_add(BrushCommandList *cl,
|
|||
if (chset_template) {
|
||||
cmd->params = BKE_brush_channelset_copy(chset_template);
|
||||
|
||||
for (int i = 0; auto_inherit && i < cmd->params->totchannel; i++) {
|
||||
BrushChannel *ch = cmd->params->channels + i;
|
||||
if (auto_inherit) {
|
||||
BrushChannel *ch;
|
||||
|
||||
ch->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
for (ch = cmd->params->channels.first; ch; ch = ch->next) {
|
||||
ch->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1131,6 +784,12 @@ BrushCommand *BKE_brush_commandlist_add(BrushCommandList *cl,
|
|||
return cmd;
|
||||
}
|
||||
|
||||
#ifdef ADDCH
|
||||
# undef ADDCH
|
||||
#endif
|
||||
|
||||
#define ADDCH(name) BKE_brush_channelset_ensure_builtin(chset, name)
|
||||
|
||||
BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool)
|
||||
{
|
||||
BrushChannelSet *chset = command->params;
|
||||
|
@ -1260,25 +919,29 @@ ATTR_NO_OPT void BKE_builtin_commandlist_create(Brush *brush,
|
|||
// if (!BKE_brush_channelset_get_int)
|
||||
}
|
||||
|
||||
void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *cset)
|
||||
void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *chset)
|
||||
{
|
||||
BLO_read_data_address(reader, &cset->channels);
|
||||
BLO_read_list(reader, &chset->channels);
|
||||
|
||||
// drop any queued channels, we don't save them.
|
||||
cset->queued_channels = NULL;
|
||||
cset->tot_queued_channel = 0;
|
||||
chset->namemap = BLI_ghash_str_new("BrushChannelSet");
|
||||
|
||||
for (int i = 0; i < cset->totchannel; i++) {
|
||||
BrushChannel *ch = cset->channels + i;
|
||||
BrushChannel *ch;
|
||||
// regenerate chset->totchannel just to be safe
|
||||
chset->totchannel = 0;
|
||||
|
||||
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);
|
||||
for (ch = chset->channels.first; ch; ch = ch->next) {
|
||||
chset->totchannel++;
|
||||
|
||||
check_corrupted_curve(ch->mappings + j);
|
||||
BLI_ghash_insert(chset->namemap, ch->idname, ch);
|
||||
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
BKE_curvemapping_blend_read(reader, &ch->mappings[i].curve);
|
||||
BKE_curvemapping_init(&ch->mappings[i].curve);
|
||||
|
||||
check_corrupted_curve(ch->mappings + i);
|
||||
|
||||
// paranoia check to make sure BrushMapping.type is correct
|
||||
ch->mappings[j].type = j;
|
||||
ch->mappings[i].type = i;
|
||||
}
|
||||
|
||||
ch->def = BKE_brush_builtin_channel_def_find(ch->idname);
|
||||
|
@ -1294,16 +957,15 @@ void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *cset)
|
|||
}
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet *cset)
|
||||
ATTR_NO_OPT void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet *chset)
|
||||
{
|
||||
BLO_write_struct(writer, BrushChannelSet, cset);
|
||||
BLO_write_struct_array_by_name(writer, "BrushChannel", cset->totchannel, cset->channels);
|
||||
BLO_write_struct(writer, BrushChannelSet, chset);
|
||||
BLO_write_struct_list(writer, BrushChannel, &chset->channels);
|
||||
|
||||
for (int i = 0; i < cset->totchannel; i++) {
|
||||
BrushChannel *ch = cset->channels + i;
|
||||
|
||||
for (int j = 0; j < BRUSH_MAPPING_MAX; j++) {
|
||||
BKE_curvemapping_blend_write(writer, &ch->mappings[j].curve);
|
||||
BrushChannel *ch;
|
||||
for (ch = chset->channels.first; ch; ch = ch->next) {
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
BKE_curvemapping_blend_write(writer, &ch->mappings[i].curve);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
#include "DNA_brush_enums.h"
|
||||
#include "DNA_brush_types.h"
|
||||
|
@ -26,9 +28,8 @@
|
|||
#include "BKE_paint.h"
|
||||
|
||||
#include "BKE_brush_engine.h"
|
||||
#include "BKE_curveprofile.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
static bool check_builtin_init();
|
||||
|
||||
/*
|
||||
Instructions to add a built-in channel:
|
||||
|
@ -85,7 +86,11 @@ To enable converting to/from old data:
|
|||
#define MAKE_BOOL(idname, name, tooltip, value)\
|
||||
MAKE_BOOL_EX_OPEN(idname, name, tooltip, value) }
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
/*
|
||||
This is where all the builtin brush channels are defined.
|
||||
That includes per-brush enums and bitflags!
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
BrushChannelType brush_builtin_channels[] = {
|
||||
|
@ -102,6 +107,7 @@ BrushChannelType brush_builtin_channels[] = {
|
|||
.pressure = {.curve = CURVE_PRESET_LINE, .factor = 1.0f, .min = 0.0f, .max = 1.0f, .enabled = false},
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.name = "Strength",
|
||||
.idname = "STRENGTH",
|
||||
|
@ -296,25 +302,25 @@ BrushChannelType brush_builtin_channels[] = {
|
|||
.name = "Topology Rake Mode",
|
||||
.idname = "TOPOLOGY_RAKE_MODE",
|
||||
.type = BRUSH_CHANNEL_ENUM,
|
||||
.enumdef = {.items = {
|
||||
.enumdef = {
|
||||
{0, "BRUSH_DIRECTION", ICON_NONE, "Stroke", "Stroke Direction"},
|
||||
{1, "CURVATURE", ICON_NONE, "Curvature", "Follow mesh curvature"},
|
||||
{-1, 0}
|
||||
}}
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "Automasking",
|
||||
.idname = "AUTOMASKING",
|
||||
.flag = BRUSH_CHANNEL_INHERIT_IF_UNSET | BRUSH_CHANNEL_INHERIT,
|
||||
.type = BRUSH_CHANNEL_BITMASK,
|
||||
.enumdef = {.items = {
|
||||
.enumdef = {
|
||||
{BRUSH_AUTOMASKING_BOUNDARY_EDGES, "BOUNDARY_EDGE", ICON_NONE, "Boundary Edges", ""},
|
||||
{BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS, "BOUNDARY_FACE_SETS", ICON_NONE, "Boundary Face Sets", ""},
|
||||
{BRUSH_AUTOMASKING_CONCAVITY, "CONCAVITY", ICON_NONE, "Concave", ""},
|
||||
{BRUSH_AUTOMASKING_INVERT_CONCAVITY, "INVERT_CONCAVITY", ICON_NONE, "Invert Concave", "Invert Concave Map"},
|
||||
{BRUSH_AUTOMASKING_FACE_SETS, "FACE_SETS", ICON_NONE, "Face Sets", ""},
|
||||
{BRUSH_AUTOMASKING_TOPOLOGY, "TOPOLOGY", ICON_NONE, "Topology", ""}
|
||||
}}
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "Disable Dyntopo",
|
||||
|
@ -347,7 +353,6 @@ BrushChannelType brush_builtin_channels[] = {
|
|||
{-1, NULL, -1, NULL, NULL}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.name = "Slide Deform Type",
|
||||
.idname = "SLIDE_DEFORM_TYPE",
|
||||
|
@ -399,7 +404,6 @@ BrushChannelType brush_builtin_channels[] = {
|
|||
.type = BRUSH_CHANNEL_BOOL,
|
||||
.ivalue = 0
|
||||
},
|
||||
|
||||
MAKE_FLOAT("NORMAL_WEIGHT", "Normal Weight", "", 0.0f, 0.0f, 1.0f),
|
||||
MAKE_FLOAT("RAKE_FACTOR", "Rake Factor", "How much grab will follow cursor rotation", 0.0f, 0.0f, 10.0f),
|
||||
MAKE_FLOAT("WEIGHT", "Weight", "", 0.5f, 0.0f, 1.0f),
|
||||
|
@ -425,3 +429,445 @@ BrushChannelType brush_builtin_channels[] = {
|
|||
|
||||
/* clang-format on */
|
||||
const int brush_builtin_channel_len = ARRAY_SIZE(brush_builtin_channels);
|
||||
|
||||
static bool do_builtin_init = true;
|
||||
ATTR_NO_OPT static bool check_builtin_init()
|
||||
{
|
||||
if (!do_builtin_init || !BLI_thread_is_main()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
do_builtin_init = false;
|
||||
|
||||
for (int i = 0; i < brush_builtin_channel_len; i++) {
|
||||
BKE_brush_channeltype_rna_check(brush_builtin_channels + i);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void namestack_push(const char *name);
|
||||
void namestack_pop();
|
||||
#define namestack_head_name strdup(namestack[namestack_i].tag)
|
||||
|
||||
#ifdef FLOAT
|
||||
# undef FLOAT
|
||||
#endif
|
||||
#ifdef INT
|
||||
# undef INT
|
||||
#endif
|
||||
#ifdef BOOL
|
||||
# undef BOOL
|
||||
#endif
|
||||
|
||||
#define FLOAT BRUSH_CHANNEL_FLOAT
|
||||
#define INT BRUSH_CHANNEL_INT
|
||||
#define BOOL BRUSH_CHANNEL_BOOL
|
||||
#define FLOAT3 BRUSH_CHANNEL_VEC3
|
||||
#define FLOAT4 BRUSH_CHANNEL_VEC4
|
||||
|
||||
#ifdef ADDCH
|
||||
# undef ADDCH
|
||||
#endif
|
||||
#ifdef GETCH
|
||||
# undef GETCH
|
||||
#endif
|
||||
|
||||
#define ADDCH(name) BKE_brush_channelset_ensure_builtin(chset, name)
|
||||
#define GETCH(name) BKE_brush_channelset_lookup(chset, name)
|
||||
|
||||
/* clang-format off */
|
||||
#define DEF(brush_member, channel_name, btype, ctype) \
|
||||
{offsetof(Brush, brush_member), #channel_name, btype, ctype, sizeof(((Brush){0}).brush_member)},
|
||||
/* clang-format on */
|
||||
|
||||
typedef struct BrushSettingsMap {
|
||||
int brush_offset;
|
||||
const char *channel_name;
|
||||
int brush_type;
|
||||
int channel_type;
|
||||
int member_size;
|
||||
} BrushSettingsMap;
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
/* This lookup table is used convert data to/from brush channels
|
||||
and the old settings fields in Brush*/
|
||||
static BrushSettingsMap brush_settings_map[] = {
|
||||
DEF(size, RADIUS, INT, FLOAT)
|
||||
DEF(alpha, STRENGTH, FLOAT, FLOAT)
|
||||
DEF(autosmooth_factor, AUTOSMOOTH, FLOAT, FLOAT)
|
||||
DEF(autosmooth_projection, SMOOTH_PROJECTION, FLOAT, FLOAT)
|
||||
DEF(topology_rake_projection, TOPOLOGY_RAKE_PROJECTION, FLOAT, FLOAT)
|
||||
DEF(topology_rake_radius_factor, TOPOLOGY_RAKE_RADIUS_SCALE, FLOAT, FLOAT)
|
||||
DEF(topology_rake_spacing, TOPOLOGY_RAKE_SPACING, INT, FLOAT)
|
||||
DEF(topology_rake_factor, TOPOLOGY_RAKE, FLOAT, FLOAT)
|
||||
DEF(autosmooth_fset_slide, FSET_SLIDE, FLOAT, FLOAT)
|
||||
DEF(boundary_smooth_factor, BOUNDARY_SMOOTH, FLOAT, FLOAT)
|
||||
DEF(autosmooth_radius_factor, AUTOSMOOTH_RADIUS_SCALE, FLOAT, FLOAT)
|
||||
DEF(normal_weight, NORMAL_WEIGHT, FLOAT, FLOAT)
|
||||
DEF(rake_factor, RAKE_FACTOR, FLOAT, FLOAT)
|
||||
DEF(weight, WEIGHT, FLOAT, FLOAT)
|
||||
DEF(jitter, JITTER, FLOAT, FLOAT)
|
||||
DEF(jitter_absolute, JITTER_ABSOLITE, INT, INT)
|
||||
DEF(smooth_stroke_radius, SMOOTH_STROKE_RADIUS, INT, FLOAT)
|
||||
DEF(smooth_stroke_factor, SMOOTH_STROKE_FACTOR, FLOAT, FLOAT)
|
||||
DEF(rate, RATE, FLOAT, FLOAT)
|
||||
DEF(flow, FLOW, FLOAT, FLOAT)
|
||||
DEF(wet_mix, WET_MIX, FLOAT, FLOAT)
|
||||
DEF(wet_persistence, WET_PERSISTENCE, FLOAT, FLOAT)
|
||||
DEF(density, DENSITY, FLOAT, FLOAT)
|
||||
DEF(tip_scale_x, TIP_SCALE_X, FLOAT, FLOAT)
|
||||
};
|
||||
static const int brush_settings_map_len = ARRAY_SIZE(brush_settings_map);
|
||||
|
||||
/* clang-format on */
|
||||
#undef DEF
|
||||
|
||||
typedef struct BrushFlagMap {
|
||||
int member_offset;
|
||||
char *channel_name;
|
||||
int flag;
|
||||
int member_size;
|
||||
} BrushFlagMap;
|
||||
|
||||
/* clang-format off */
|
||||
#define DEF(member, channel, flag)\
|
||||
{offsetof(Brush, member), #channel, flag, sizeof(((Brush){0}).member)},
|
||||
|
||||
/* This lookup table is like brush_settings_map except it converts
|
||||
individual bitflags instead of whole struct members.*/
|
||||
BrushFlagMap brush_flags_map[] = {
|
||||
DEF(flag, ORIGINAL_NORMAL, BRUSH_ORIGINAL_NORMAL)
|
||||
DEF(flag, ORIGINAL_PLANE, BRUSH_ORIGINAL_PLANE)
|
||||
DEF(flag, ACCUMULATE, BRUSH_ACCUMULATE)
|
||||
DEF(flag2, USE_WEIGHTED_SMOOTH, BRUSH_SMOOTH_USE_AREA_WEIGHT)
|
||||
DEF(flag2, PRESERVE_FACESET_BOUNDARY, BRUSH_SMOOTH_PRESERVE_FACE_SETS)
|
||||
DEF(flag2, HARD_EDGE_MODE, BRUSH_HARD_EDGE_MODE)
|
||||
DEF(flag2, GRAB_SILHOUETTE, BRUSH_GRAB_SILHOUETTE)
|
||||
};
|
||||
int brush_flags_map_len = ARRAY_SIZE(brush_flags_map);
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
static ATTR_NO_OPT void do_coerce(
|
||||
int type1, void *ptr1, int size1, int type2, void *ptr2, int size2)
|
||||
{
|
||||
double val = 0;
|
||||
|
||||
switch (type1) {
|
||||
case BRUSH_CHANNEL_FLOAT:
|
||||
val = *(float *)ptr1;
|
||||
break;
|
||||
case BRUSH_CHANNEL_INT:
|
||||
case BRUSH_CHANNEL_ENUM:
|
||||
case BRUSH_CHANNEL_BITMASK:
|
||||
case BRUSH_CHANNEL_BOOL:
|
||||
switch (size1) {
|
||||
case 1:
|
||||
val = (double)*(char *)ptr1;
|
||||
break;
|
||||
case 2:
|
||||
val = (double)*(unsigned short *)ptr1;
|
||||
break;
|
||||
case 4:
|
||||
val = (double)*(int *)ptr1;
|
||||
break;
|
||||
case 8:
|
||||
val = (double)*(int64_t *)ptr1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type2) {
|
||||
case BRUSH_CHANNEL_FLOAT:
|
||||
*(float *)ptr2 = (float)val;
|
||||
break;
|
||||
case BRUSH_CHANNEL_INT:
|
||||
case BRUSH_CHANNEL_ENUM:
|
||||
case BRUSH_CHANNEL_BITMASK:
|
||||
case BRUSH_CHANNEL_BOOL: {
|
||||
switch (size2) {
|
||||
case 1:
|
||||
*(char *)ptr2 = (char)val;
|
||||
break;
|
||||
case 2:
|
||||
*(unsigned short *)ptr2 = (unsigned short)val;
|
||||
break;
|
||||
case 4:
|
||||
*(int *)ptr2 = (int)val;
|
||||
break;
|
||||
case 8:
|
||||
*(int64_t *)ptr2 = (int64_t)val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *get_channel_value_pointer(BrushChannel *ch, int *r_data_size)
|
||||
{
|
||||
*r_data_size = 4;
|
||||
|
||||
switch (ch->type) {
|
||||
case BRUSH_CHANNEL_FLOAT:
|
||||
return &ch->fvalue;
|
||||
case BRUSH_CHANNEL_INT:
|
||||
case BRUSH_CHANNEL_ENUM:
|
||||
case BRUSH_CHANNEL_BITMASK:
|
||||
case BRUSH_CHANNEL_BOOL:
|
||||
return &ch->ivalue;
|
||||
case BRUSH_CHANNEL_VEC3:
|
||||
*r_data_size = sizeof(float) * 3;
|
||||
printf("implement me!\n");
|
||||
return NULL;
|
||||
case BRUSH_CHANNEL_VEC4:
|
||||
*r_data_size = sizeof(float) * 4;
|
||||
printf("implement me!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channelset_compat_load(BrushChannelSet *chset,
|
||||
Brush *brush,
|
||||
bool brush_to_channels)
|
||||
{
|
||||
for (int i = 0; i < brush_flags_map_len; i++) {
|
||||
BrushFlagMap *mf = brush_flags_map + i;
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, mf->channel_name);
|
||||
|
||||
if (!ch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char *ptr = (char *)brush;
|
||||
ptr += mf->member_offset;
|
||||
|
||||
switch (mf->member_size) {
|
||||
case 1: {
|
||||
char *f = (char *)ptr;
|
||||
ch->ivalue = (*f & mf->flag) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
ushort *f = (ushort *)ptr;
|
||||
ch->ivalue = (*f & mf->flag) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
uint *f = (uint *)ptr;
|
||||
ch->ivalue = (*f & mf->flag) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
uint64_t *f = (uint64_t *)ptr;
|
||||
ch->ivalue = (*f & mf->flag) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < brush_settings_map_len; i++) {
|
||||
BrushSettingsMap *mp = brush_settings_map + i;
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, mp->channel_name);
|
||||
|
||||
if (!ch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char *bptr = (char *)brush;
|
||||
bptr += mp->brush_offset;
|
||||
|
||||
int csize;
|
||||
void *cptr = get_channel_value_pointer(ch, &csize);
|
||||
|
||||
if (brush_to_channels) {
|
||||
do_coerce(mp->brush_type, bptr, mp->member_size, ch->type, cptr, csize);
|
||||
}
|
||||
else {
|
||||
do_coerce(ch->type, cptr, csize, mp->brush_type, bptr, mp->member_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adds any missing channels to brushes
|
||||
void BKE_brush_builtin_patch(Brush *brush, int tool)
|
||||
{
|
||||
check_builtin_init();
|
||||
|
||||
namestack_push(__func__);
|
||||
|
||||
if (!brush->channels) {
|
||||
brush->channels = BKE_brush_channelset_create();
|
||||
}
|
||||
|
||||
BrushChannelSet *chset = brush->channels;
|
||||
|
||||
ADDCH("RADIUS");
|
||||
ADDCH("SPACING");
|
||||
ADDCH("STRENGTH");
|
||||
|
||||
ADDCH("AUTOSMOOTH");
|
||||
ADDCH("AUTOSMOOTH_RADIUS_SCALE");
|
||||
ADDCH("AUTOSMOOTH_SPACING");
|
||||
ADDCH("AUTOSMOOTH_USE_SPACING");
|
||||
ADDCH("AUTOSMOOTH_PROJECTION");
|
||||
|
||||
ADDCH("TOPOLOGY_RAKE");
|
||||
ADDCH("TOPOLOGY_RAKE_MODE");
|
||||
ADDCH("TOPOLOGY_RAKE_RADIUS_SCALE");
|
||||
ADDCH("TOPOLOGY_RAKE_USE_SPACING");
|
||||
ADDCH("TOPOLOGY_RAKE_SPACING");
|
||||
ADDCH("TOPOLOGY_RAKE_PROJECTION");
|
||||
|
||||
ADDCH("HARDNESS");
|
||||
ADDCH("TIP_ROUNDNESS");
|
||||
ADDCH("NORMAL_RADIUS_FACTOR");
|
||||
|
||||
ADDCH("AUTOMASKING");
|
||||
|
||||
ADDCH("DYNTOPO_DISABLED");
|
||||
ADDCH("DYNTOPO_DETAIL_RANGE");
|
||||
ADDCH("DYNTOPO_OPS");
|
||||
|
||||
ADDCH("ACCUMULATE");
|
||||
ADDCH("ORIGINAL_NORMAL");
|
||||
ADDCH("ORIGINAL_PLANE");
|
||||
ADDCH("JITTER");
|
||||
ADDCH("JITTER_ABSOLUTE");
|
||||
ADDCH("USE_WEIGHTED_SMOOTH");
|
||||
ADDCH("PRESERVE_FACESET_BOUNDARY");
|
||||
ADDCH("HARD_EDGE_MODE");
|
||||
ADDCH("GRAB_SILHOUETTE");
|
||||
|
||||
ADDCH("PROJECTION");
|
||||
ADDCH("BOUNDARY_SMOOTH");
|
||||
ADDCH("FSET_SLIDE");
|
||||
|
||||
switch (tool) {
|
||||
case SCULPT_TOOL_DRAW: {
|
||||
break;
|
||||
}
|
||||
case SCULPT_TOOL_SLIDE_RELAX:
|
||||
ADDCH("SLIDE_DEFORM_TYPE");
|
||||
break;
|
||||
}
|
||||
|
||||
namestack_pop();
|
||||
}
|
||||
|
||||
void BKE_brush_init_scene_defaults(Sculpt *sd)
|
||||
{
|
||||
if (!sd->channels) {
|
||||
sd->channels = BKE_brush_channelset_create();
|
||||
}
|
||||
|
||||
BrushChannelSet *chset = sd->channels;
|
||||
}
|
||||
|
||||
void BKE_brush_builtin_create(Brush *brush, int tool)
|
||||
{
|
||||
namestack_push(__func__);
|
||||
|
||||
if (!brush->channels) {
|
||||
brush->channels = BKE_brush_channelset_create();
|
||||
}
|
||||
|
||||
BrushChannelSet *chset = brush->channels;
|
||||
|
||||
BKE_brush_builtin_patch(brush, tool);
|
||||
|
||||
GETCH("STRENGTH")->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
GETCH("RADIUS")->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
|
||||
switch (tool) {
|
||||
case SCULPT_TOOL_DRAW: {
|
||||
break;
|
||||
}
|
||||
case SCULPT_TOOL_DRAW_SHARP:
|
||||
GETCH("SPACING")->ivalue = 5;
|
||||
GETCH("RADIUS")->mappings[BRUSH_MAPPING_PRESSURE].blendmode = true;
|
||||
break;
|
||||
case SCULPT_TOOL_DISPLACEMENT_ERASER:
|
||||
case SCULPT_TOOL_FAIRING:
|
||||
case SCULPT_TOOL_SCENE_PROJECT:
|
||||
GETCH("SPACING")->ivalue = 10;
|
||||
GETCH("STRENGTH")->fvalue = 1.0f;
|
||||
GETCH("DYNTOPO_DISABLED")->ivalue = 1;
|
||||
break;
|
||||
case SCULPT_TOOL_SLIDE_RELAX:
|
||||
GETCH("SPACING")->ivalue = 10;
|
||||
GETCH("STRENGTH")->fvalue = 1.0f;
|
||||
GETCH("DYNTOPO_DISABLED")->ivalue = 1;
|
||||
GETCH("SLIDE_DEFORM_TYPE")->ivalue = BRUSH_SLIDE_DEFORM_DRAG;
|
||||
break;
|
||||
case SCULPT_TOOL_CLAY:
|
||||
GETCH("RADIUS")->mappings[BRUSH_MAPPING_PRESSURE].flag |= BRUSH_MAPPING_ENABLED;
|
||||
GETCH("SPACING")->ivalue = 3;
|
||||
GETCH("AUTOSMOOTH")->fvalue = 0.25f;
|
||||
GETCH("NORMAL_RADIUS_FACTOR")->fvalue = 0.75f;
|
||||
GETCH("HARDNESS")->fvalue = 0.65;
|
||||
break;
|
||||
case SCULPT_TOOL_TWIST:
|
||||
GETCH("STRENGTH")->fvalue = 0.5f;
|
||||
GETCH("NORMAL_RADIUS_FACTOR")->fvalue = 1.0f;
|
||||
GETCH("SPACING")->ivalue = 6;
|
||||
GETCH("HARDNESS")->fvalue = 0.5;
|
||||
break;
|
||||
case SCULPT_TOOL_CLAY_STRIPS: {
|
||||
GETCH("RADIUS")->mappings[BRUSH_MAPPING_PRESSURE].flag |= BRUSH_MAPPING_ENABLED;
|
||||
GETCH("TIP_ROUNDNESS")->fvalue = 0.18f;
|
||||
GETCH("NORMAL_RADIUS_FACTOR")->fvalue = 1.35f;
|
||||
GETCH("STRENGTH")->fvalue = 0.8f;
|
||||
GETCH("ACCUMULATE")->ivalue = 1;
|
||||
|
||||
CurveMapping *curve = &GETCH("RADIUS")->mappings[BRUSH_MAPPING_PRESSURE].curve;
|
||||
CurveMap *cuma = curve->cm;
|
||||
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.55f;
|
||||
BKE_curvemap_insert(cuma, 0.5f, 0.7f);
|
||||
cuma->curve[2].x = 1.0f;
|
||||
cuma->curve[2].y = 1.0f;
|
||||
BKE_curvemapping_changed(curve, true);
|
||||
|
||||
cuma = curve->cm;
|
||||
BKE_curvemap_insert(cuma, 0.6f, 0.25f);
|
||||
BKE_curvemapping_changed(curve, true);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// implement me!
|
||||
// BKE_brush_channelset_free(chset);
|
||||
// brush->channels = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
namestack_pop();
|
||||
}
|
||||
|
||||
void BKE_brush_init_toolsettings(Sculpt *sd)
|
||||
{
|
||||
namestack_push(__func__);
|
||||
|
||||
if (sd->channels) {
|
||||
BKE_brush_channelset_free(sd->channels);
|
||||
}
|
||||
|
||||
BrushChannelSet *chset = sd->channels = BKE_brush_channelset_create();
|
||||
|
||||
ADDCH("RADIUS");
|
||||
ADDCH("STRENGTH");
|
||||
ADDCH("AUTOMASKING");
|
||||
ADDCH("TOPOLOGY_RAKE_MODE");
|
||||
ADDCH("DYNTOPO_DISABLED");
|
||||
ADDCH("DYNTOPO_DETAIL_RANGE");
|
||||
|
||||
namestack_pop();
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ void BKE_curvemapping_set_defaults(
|
|||
cumap->changed_timestamp = 0;
|
||||
}
|
||||
|
||||
CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
|
||||
ATTR_NO_OPT CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
|
||||
{
|
||||
CurveMapping *cumap;
|
||||
|
||||
|
@ -96,7 +96,7 @@ CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx,
|
|||
return cumap;
|
||||
}
|
||||
|
||||
void BKE_curvemapping_free_data(CurveMapping *cumap)
|
||||
ATTR_NO_OPT void BKE_curvemapping_free_data(CurveMapping *cumap)
|
||||
{
|
||||
int a;
|
||||
|
||||
|
|
|
@ -1372,16 +1372,6 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
BKE_brush_builtin_create(brush, brush->sculpt_tool);
|
||||
BKE_brush_channelset_compat_load(brush->channels, brush, true);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
if (scene->toolsettings->sculpt) {
|
||||
printf("scene channels: %p\n", scene->toolsettings->sculpt->channels);
|
||||
if (scene->toolsettings->sculpt->channels) {
|
||||
BKE_brush_channelset_free(scene->toolsettings->sculpt->channels);
|
||||
scene->toolsettings->sculpt->channels = BKE_brush_channelset_create();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "DNA_color_types.h"
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
struct GHash;
|
||||
|
||||
typedef struct BrushMapping {
|
||||
char name[64];
|
||||
|
@ -36,6 +39,8 @@ typedef struct BrushMapping {
|
|||
} BrushMapping;
|
||||
|
||||
typedef struct BrushChannel {
|
||||
struct BrushChannel *next, *prev;
|
||||
|
||||
char idname[64];
|
||||
char name[64];
|
||||
|
||||
|
@ -49,13 +54,13 @@ typedef struct BrushChannel {
|
|||
} BrushChannel;
|
||||
|
||||
typedef struct BrushChannelSet {
|
||||
BrushChannel *channels;
|
||||
/*cannot add channels within the UI loop. Since it's
|
||||
hard to avoid it they're put here.*/
|
||||
BrushChannel *queued_channels;
|
||||
int totchannel, tot_queued_channel;
|
||||
ListBase channels;
|
||||
int totchannel, _pad[1];
|
||||
struct GHash *namemap;
|
||||
} BrushChannelSet;
|
||||
|
||||
#define BRUSH_CHANNEL_MAX_IDNAME sizeof(((BrushChannel){0}).idname)
|
||||
|
||||
// mapping flags
|
||||
enum {
|
||||
BRUSH_MAPPING_ENABLED = 1 << 0,
|
||||
|
|
|
@ -22,12 +22,14 @@
|
|||
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
#include "DNA_workspace_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -43,7 +45,7 @@
|
|||
#include "DNA_sculpt_brush_types.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
static EnumPropertyItem null_enum[1] = {{0, "null", 0, 0}, {-1, NULL, -1, -1}};
|
||||
static EnumPropertyItem null_enum[2] = {{0, "null", 0, 0}, {-1, NULL, -1, NULL, NULL}};
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
|
@ -51,8 +53,7 @@ int rna_BrushChannelSet_channels_begin(CollectionPropertyIterator *iter, struct
|
|||
{
|
||||
BrushChannelSet *chset = ptr->data;
|
||||
|
||||
rna_iterator_array_begin(
|
||||
iter, chset->channels, sizeof(BrushChannel), chset->totchannel, false, NULL);
|
||||
rna_iterator_listbase_begin(iter, &chset->channels, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -62,10 +63,12 @@ int rna_BrushChannelSet_channels_assignint(struct PointerRNA *ptr,
|
|||
const struct PointerRNA *assign_ptr)
|
||||
{
|
||||
BrushChannelSet *chset = ptr->data;
|
||||
BrushChannel *ch = chset->channels + key;
|
||||
BrushChannel *src = assign_ptr->data;
|
||||
BrushChannel *ch = BLI_findlink(&chset->channels, key);
|
||||
|
||||
BKE_brush_channel_copy_data(ch, src);
|
||||
if (ch) {
|
||||
BKE_brush_channel_copy_data(ch, src);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -213,7 +216,9 @@ ATTR_NO_OPT const EnumPropertyItem *rna_BrushChannel_enum_value_get_items(struct
|
|||
return null_enum;
|
||||
}
|
||||
|
||||
return ch->def->enumdef.items;
|
||||
BKE_brush_channeltype_rna_check(ch->def);
|
||||
|
||||
return ch->def->rna_enumdef;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -406,17 +411,15 @@ void RNA_def_brush_channelset(BlenderRNA *brna)
|
|||
func, "channel", "BrushChannel", "", "Ensure a copy of channel exists in this channel set");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
|
||||
parm = RNA_def_boolean(
|
||||
func, "queue", true, "queue", "Add channel to an internal queue to avoid corrupting the UI");
|
||||
// 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,
|
||||
"rna_BrushChannelSet_channels_begin",
|
||||
"rna_iterator_array_next",
|
||||
"rna_iterator_array_end",
|
||||
"rna_iterator_array_get",
|
||||
"rna_iterator_listbase_next",
|
||||
"rna_iterator_listbase_end",
|
||||
"rna_iterator_listbase_get",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
|
Loading…
Reference in New Issue