Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_brush_engine.h34
-rw-r--r--source/blender/blenkernel/intern/brush.c7
-rw-r--r--source/blender/blenkernel/intern/brush_engine.c734
-rw-r--r--source/blender/blenkernel/intern/brush_engine_presets.c464
-rw-r--r--source/blender/blenkernel/intern/colortools.c4
-rw-r--r--source/blender/blenloader/intern/versioning_300.c10
-rw-r--r--source/blender/makesdna/DNA_sculpt_brush_types.h15
-rw-r--r--source/blender/makesrna/intern/rna_brush_engine.c25
8 files changed, 709 insertions, 584 deletions
diff --git a/source/blender/blenkernel/BKE_brush_engine.h b/source/blender/blenkernel/BKE_brush_engine.h
index 25c6227cf32..8fd2ded7075 100644
--- a/source/blender/blenkernel/BKE_brush_engine.h
+++ b/source/blender/blenkernel/BKE_brush_engine.h
@@ -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
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index e2e33db0fd8..0151cc4e16d 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -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);
}
diff --git a/source/blender/blenkernel/intern/brush_engine.c b/source/blender/blenkernel/intern/brush_engine.c
index ee345bccd3a..4a67ffd2e37 100644
--- a/source/blender/blenkernel/intern/brush_engine.c
+++ b/source/blender/blenkernel/intern/brush_engine.c
@@ -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");
-void BKE_brush_apply_queued_channels(BrushChannelSet *chset, bool do_override)
-{
- if (!chset->tot_queued_channel) {
- return;
- }
+ chset->namemap = BLI_ghash_str_new("BrushChannelSet");
- for (int i = 0; i < chset->tot_queued_channel; i++) {
- BrushChannel *ch = chset->queued_channels;
+ return chset;
+}
- BrushChannel *exist = BKE_brush_channelset_lookup(chset, ch->idname);
+ATTR_NO_OPT void BKE_brush_channelset_free(BrushChannelSet *chset)
+{
+ BrushChannel *ch, *next;
- if (exist) {
- if (!do_override) {
- continue;
- }
+ BLI_ghash_free(chset->namemap, NULL, NULL);
- BKE_brush_channel_free(exist);
- *exist = *ch;
+ for (ch = chset->channels.first; ch; ch = next) {
+ next = ch->next;
- continue;
- }
- else {
- BKE_brush_channelset_add(chset, ch);
- BKE_brush_channel_free(ch);
- }
+ BKE_brush_channel_free(ch);
}
- MEM_SAFE_FREE(chset->queued_channels);
- chset->queued_channels = NULL;
- chset->tot_queued_channel = NULL;
+ MEM_freeN(chset);
}
-void BKE_brush_channelset_free(BrushChannelSet *chset)
+static int _rng_seed = 0;
+
+ATTR_NO_OPT void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *ch)
{
- for (int step = 0; step < 2; step++) {
- BrushChannel *channels = step ? chset->queued_channels : chset->channels;
- int totchannel = step ? chset->tot_queued_channel : chset->totchannel;
+ BrushChannel *ch2;
+ int i = 1;
+ char idname[512];
- if (channels) {
- for (int i = 0; i < totchannel; i++) {
- BKE_brush_channel_free(channels + i);
- }
+ 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';
- MEM_freeN(channels);
+ i = 0;
+ ch->idname[j] = chr;
+ strcpy(idname, ch->idname);
+ }
+
+ i++;
+ break;
+ }
}
}
- MEM_freeN(chset);
+ BLI_strncpy(ch->idname, idname, sizeof(ch->idname));
+
+ // BLI_strncpy
+ BLI_rng_free(rng);
}
void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch)
{
- chset->totchannel++;
+ BKE_brush_channel_ensure_unque_name(chset, ch);
- 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");
- }
+ BLI_addtail(&chset->channels, ch);
+ BLI_ghash_insert(chset->namemap, ch->idname, ch);
- namestack_push(__func__);
- BKE_brush_channel_copy_data(chset->channels + chset->totchannel - 1, ch);
- namestack_pop();
+ chset->totchannel++;
}
-// used to avoid messing up pointers in ui
-void BKE_brush_channelset_queue(BrushChannelSet *chset, BrushChannel *ch)
+ATTR_NO_OPT void BKE_brush_channel_rename(BrushChannelSet *chset,
+ BrushChannel *ch,
+ const char *newname)
{
- chset->tot_queued_channel++;
+ 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);
+}
- 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");
+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);
}
}
}
diff --git a/source/blender/blenkernel/intern/brush_engine_presets.c b/source/blender/blenkernel/intern/brush_engine_presets.c
index 79b4e86885f..098b38b84f4 100644
--- a/source/blender/blenkernel/intern/brush_engine_presets.c
+++ b/source/blender/blenkernel/intern/brush_engine_presets.c
@@ -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();
+}
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index e739b776570..d360911f0f9 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -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;
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 47d59567218..602aad729bd 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -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.
diff --git a/source/blender/makesdna/DNA_sculpt_brush_types.h b/source/blender/makesdna/DNA_sculpt_brush_types.h
index 4e219805e59..22337ac37e5 100644
--- a/source/blender/makesdna/DNA_sculpt_brush_types.h
+++ b/source/blender/makesdna/DNA_sculpt_brush_types.h
@@ -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,
diff --git a/source/blender/makesrna/intern/rna_brush_engine.c b/source/blender/makesrna/intern/rna_brush_engine.c
index b7e9f16a817..935b7493b5a 100644
--- a/source/blender/makesrna/intern/rna_brush_engine.c
+++ b/source/blender/makesrna/intern/rna_brush_engine.c
@@ -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,