diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_brush_engine.h | 34 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/brush.c | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/brush_engine.c | 734 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/brush_engine_presets.c | 464 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/colortools.c | 4 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_300.c | 10 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_sculpt_brush_types.h | 15 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_brush_engine.c | 25 |
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, |