[Bf-blender-cvs] [336b263b568] sculpt-dev: Sculpt: brush engine stuff

Joseph Eagar noreply at git.blender.org
Mon Sep 20 12:14:53 CEST 2021


Commit: 336b263b568fad2547014fe50d5810f03daa1677
Author: Joseph Eagar
Date:   Sun Sep 19 15:35:10 2021 -0700
Branches: sculpt-dev
https://developer.blender.org/rB336b263b568fad2547014fe50d5810f03daa1677

Sculpt: brush engine stuff

BrushChannels are now stored in linked lists
instead of simple arrays.  This helps to
avoid memory corruption.

I had originally wanted to be able to pass
BrushChannels by value, but that doesn't really
work since they heap allocd data (the input
mapping curves).

===================================================================

M	release/scripts/startup/bl_ui/properties_paint_common.py
M	source/blender/blenkernel/BKE_brush_engine.h
M	source/blender/blenkernel/intern/brush.c
M	source/blender/blenkernel/intern/brush_engine.c
M	source/blender/blenkernel/intern/brush_engine_presets.c
M	source/blender/blenkernel/intern/colortools.c
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/makesdna/DNA_sculpt_brush_types.h
M	source/blender/makesrna/intern/rna_brush_engine.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index b3d9230974e..ee748af74b3 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -137,7 +137,7 @@ class UnifiedPaintPanel:
         if ch.inherit:
             sd = context.tool_settings.sculpt
             #ensure channel exists in tool settings channel set
-            sd.channels.ensure(ch, queue=True)
+            sd.channels.ensure(ch)
 
             finalch = sd.channels.channels[prop_name]
 
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 (ch

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list