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
diff options
context:
space:
mode:
authorJoseph Eagar <joeedh@gmail.com>2021-09-17 06:29:33 +0300
committerJoseph Eagar <joeedh@gmail.com>2021-09-17 06:29:33 +0300
commit04c3690299c51b79412fe395c2507a28fbae7b56 (patch)
tree50692b216a2ad00b7e81770dbf02d721a937bd1b
parent627edd1efabb0baaed3127bd127215ffb0ddfbac (diff)
Sculpt dyntopo: Roughed out skeleton of new brush engine API
Command Lists * The new system will be based on command lists generated by (eventually) a node editor. * For now, the lists will be hardcoded. * Idea is to make a minimal viable brush engine that won't cause file breakage when the upgrade to node-based brushes happen. Brush Channels * Wrote new structures and API to wrange brush parameters: BrushChannel. * Supports, floats, ints, enums, bitmasks, with plans for vec3 and vec4. * This will replace UnifiedPaintStruct, most of the members of Brush and the DynTopoSettings struct. * Brush channels can be mapped to various input device channels (e.g. pen pressure); each mapping has its own associated curve (CurveMapping instance) and bounds. Brush channel inheritence chaining * Brush channels can form inheritence chains * Channel sets are stored in three places: in the scene toolsettings, in Brush, and in individual brush commands. * Node groups will also have a channel set. * Channels in each set can be flagged to inherit from the parent set. * Inheritence happens in seperate merged channel sets at runtime. The final Brush channels live in Brush->channels_final, while the final command channels live in BrushCommand->params_final.
-rw-r--r--source/blender/blenkernel/BKE_brush_engine.h129
-rw-r--r--source/blender/blenkernel/CMakeLists.txt4
-rw-r--r--source/blender/blenkernel/intern/brush.c10
-rw-r--r--source/blender/blenkernel/intern/brush_engine.c667
-rw-r--r--source/blender/blenkernel/intern/scene.c11
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_brush_machine.c316
-rw-r--r--source/blender/makesdna/DNA_brush_enums.h5
-rw-r--r--source/blender/makesdna/DNA_brush_types.h8
-rw-r--r--source/blender/makesdna/DNA_scene_types.h3
-rw-r--r--source/blender/makesdna/DNA_sculpt_brush_types.h84
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt1
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt1
-rw-r--r--source/blender/makesrna/intern/makesrna.c1
-rw-r--r--source/blender/makesrna/intern/rna_brush_engine.c47
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
16 files changed, 972 insertions, 318 deletions
diff --git a/source/blender/blenkernel/BKE_brush_engine.h b/source/blender/blenkernel/BKE_brush_engine.h
new file mode 100644
index 00000000000..5695cae3649
--- /dev/null
+++ b/source/blender/blenkernel/BKE_brush_engine.h
@@ -0,0 +1,129 @@
+#pragma once
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ * \brief New brush engine for sculpt
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "RNA_types.h"
+
+/*
+The new brush engine is based on command lists. These lists
+will eventually be created by a node editor.
+
+Key is the concept of BrushChannels. A brush channel is
+a logical parameter with a type, input settings (e.g. pen),
+a falloff curve, etc.
+
+Brush channels have a concept of inheritance. There is a
+BrushChannelSet (collection of channels) in Sculpt,
+in Brush, and in BrushCommand. Inheritence behavior
+is controller via BrushChannel->flag.
+
+This should completely replace UnifiedPaintSettings.
+*/
+struct BrushChannel;
+
+#include "BLO_read_write.h"
+#include "DNA_sculpt_brush_types.h"
+
+typedef struct BrushMappingDef {
+ int curve;
+ bool enabled;
+ bool inv;
+ float min, max;
+ int blendmode;
+} BrushMappingDef;
+
+typedef struct BrushMappingPreset {
+ // must match order of BRUSH_MAPPING_XXX enums
+ struct BrushMappingDef pressure, xtilt, ytilt, angle, speed;
+} BrushMappingPreset;
+
+#define MAX_BRUSH_ENUM_DEF 32
+
+typedef struct BrushEnumDef {
+ EnumPropertyItem items[MAX_BRUSH_ENUM_DEF];
+} BrushEnumDef;
+
+typedef struct BrushChannelType {
+ char name[32], idname[32];
+ float min, max, soft_min, soft_max;
+ BrushMappingPreset mappings;
+
+ int type, flag;
+ int ivalue;
+ float fvalue;
+ BrushEnumDef enumdef; // if an enum type
+} BrushChannelType;
+
+typedef struct BrushCommand {
+ int tool;
+ struct BrushChannelSet *params;
+ struct BrushChannelSet *params_final;
+ int totparam;
+} BrushCommand;
+
+typedef struct BrushCommandList {
+ BrushCommand *commands;
+ int totcommand;
+} BrushCommandList;
+
+void BKE_brush_channel_free(BrushChannel *ch);
+void BKE_brush_channel_copy(BrushChannel *dst, BrushChannel *src);
+void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def);
+BrushChannelSet *BKE_brush_channelset_create();
+
+void BKE_brush_channelset_free(BrushChannelSet *chset);
+void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch);
+
+BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname);
+
+bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname);
+
+void BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname);
+bool BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname);
+
+void BKE_brush_channelset_merge(BrushChannelSet *dst,
+ BrushChannelSet *child,
+ BrushChannelSet *parent);
+
+void BKE_brush_resolve_channels(struct Brush *brush, struct Sculpt *sd);
+int BKE_brush_channel_get_int(BrushChannelSet *chset, char *idname);
+float BKE_brush_channel_get_float(BrushChannelSet *chset, char *idname);
+float BKE_brush_channel_set_float(BrushChannelSet *chset, char *idname, float val);
+void BKE_brush_init_toolsettings(struct Sculpt *sd);
+void BKE_brush_builtin_create(struct Brush *brush, int tool);
+BrushCommandList *BKE_brush_commandlist_create();
+void BKE_brush_commandlist_free(BrushCommandList *cl);
+BrushCommand *BKE_brush_commandlist_add(BrushCommandList *cl);
+BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool);
+void BKE_builtin_commandlist_create(BrushChannelSet *chset, BrushCommandList *cl, int tool);
+void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *cset);
+void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet *cset);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index c652632aca8..56a221ff09b 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -289,7 +289,8 @@ set(SRC
intern/workspace.c
intern/world.c
intern/writeavi.c
-
+ intern/brush_engine.c
+
BKE_DerivedMesh.h
BKE_action.h
BKE_action.hh
@@ -451,6 +452,7 @@ set(SRC
BKE_workspace.h
BKE_world.h
BKE_writeavi.h
+ BKE_brush_engine.h
nla_private.h
particle_private.h
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 7d7b13fe872..552708722ad 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -34,6 +34,7 @@
#include "BLT_translation.h"
#include "BKE_brush.h"
+#include "BKE_brush_engine.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
@@ -262,12 +263,21 @@ static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_addres
if (brush->gradient) {
BLO_write_struct(writer, ColorBand, brush->gradient);
}
+
+ if (brush->channels) {
+ BKE_brush_channelset_write(writer, brush->channels);
+ }
}
static void brush_blend_read_data(BlendDataReader *reader, ID *id)
{
Brush *brush = (Brush *)id;
+ if (brush->channels) {
+ BLO_read_data_address(reader, &brush->channels);
+ BKE_brush_channelset_read(reader, brush->channels);
+ }
+
if (brush->dyntopo.radius_scale == 0.0f) {
brush->dyntopo.radius_scale = 1.0f;
brush->dyntopo.inherit |= DYNTOPO_INHERIT_RADIUS_SCALE;
diff --git a/source/blender/blenkernel/intern/brush_engine.c b/source/blender/blenkernel/intern/brush_engine.c
new file mode 100644
index 00000000000..a917c92879e
--- /dev/null
+++ b/source/blender/blenkernel/intern/brush_engine.c
@@ -0,0 +1,667 @@
+#include "MEM_guardedalloc.h"
+
+#include "BLI_alloca.h"
+#include "BLI_array.h"
+#include "BLI_bitmap.h"
+#include "BLI_compiler_attrs.h"
+#include "BLI_compiler_compat.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+
+#include "DNA_brush_enums.h"
+#include "DNA_brush_types.h"
+#include "DNA_color_types.h"
+#include "DNA_curveprofile_types.h"
+#include "DNA_node_types.h"
+#include "DNA_sculpt_brush_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_colorband.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_node.h"
+#include "BKE_paint.h"
+
+#include "BKE_brush_engine.h"
+#include "BKE_curveprofile.h"
+
+#include "BLO_read_write.h"
+
+#define ICON_NONE -1
+
+/*
+Brush command lists.
+
+Command lists are built dynamically from
+brush flags, pen input settings, etc.
+
+Eventually they will be generated by node
+networks. BrushCommandPreset will be
+generated from the node group inputs.
+*/
+
+/* clang-format off */
+BrushChannelType brush_builtin_channels[] = {
+ {
+ .name = "Radius",
+ .idname = "RADIUS",
+ .min = 0.001f,
+ .type = BRUSH_CHANNEL_FLOAT,
+ .max = 2048.0f,
+ .soft_min = 0.1f,
+ .soft_max = 1024.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = false},
+ }
+ },
+ {
+ .name = "Strength",
+ .idname = "STRENGTH",
+ .min = -1.0f,
+ .type = BRUSH_CHANNEL_FLOAT,
+ .max = 4.0f,
+ .soft_min = 0.0f,
+ .soft_max = 1.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = true},
+ }
+ },
+ {
+ .name = "Spacing",
+ .idname = "SPACING",
+ .min = 0.001f,
+ .type = BRUSH_CHANNEL_FLOAT,
+ .max = 4.0f,
+ .soft_min = 0.005f,
+ .soft_max = 2.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = true},
+ }
+ },
+ {
+ .name = "Autosmooth",
+ .idname = "AUTOSMOOTH",
+ .type = BRUSH_CHANNEL_FLOAT,
+ .min = -1.0f,
+ .max = 4.0f,
+ .soft_min = 0.0f,
+ .soft_max = 1.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = false, .inv = true},
+ }
+ },
+ {
+ .name = "Topology Rake",
+ .idname = "TOPOLOGY_RAKE",
+ .type = BRUSH_CHANNEL_FLOAT,
+ .min = -1.0f,
+ .max = 4.0f,
+ .soft_min = 0.0f,
+ .soft_max = 1.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = false},
+ }
+ },
+ {
+ .name = "Autosmooth Radius Scale",
+ .idname = "AUTOSMOOTH_RADIUS_SCALE",
+ .type = BRUSH_CHANNEL_FLOAT,
+ .min = 0.0001f,
+ .max = 25.0f,
+ .soft_min = 0.1f,
+ .soft_max = 4.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = false},
+ }
+ },
+ {
+ .name = "Rake Radius Scale",
+ .idname = "TOPOLOGY_RAKE_RADIUS_SCALE",
+ .type = BRUSH_CHANNEL_FLOAT,
+ .min = 0.0001f,
+ .max = 25.0f,
+ .soft_min = 0.1f,
+ .soft_max = 4.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = false},
+ }
+ },
+ {
+ .name = "Face Set Slide",
+ .idname = "FSET_SLIDE",
+ .type = BRUSH_CHANNEL_FLOAT,
+ .min = 0.0001f,
+ .max = 1.0f,
+ .soft_min = 0.1f,
+ .soft_max = 1.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = false},
+ }
+ },
+ {
+ .name = "Boundary Smooth",
+ .idname = "BOUNDARY_SMOOTH",
+ .type = BRUSH_CHANNEL_FLOAT,
+ .min = 0.0001f,
+ .max = 1.0f,
+ .soft_min = 0.1f,
+ .soft_max = 1.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = false},
+ }
+ },
+ {
+ .name = "Projection",
+ .idname = "PROJECTION",
+ .type = BRUSH_CHANNEL_FLOAT,
+ .min = 0.0001f,
+ .max = 1.0f,
+ .soft_min = 0.1f,
+ .soft_max = 1.0f,
+ .mappings = {
+ .pressure = {.curve = CURVE_PRESET_SMOOTH, .min = 0.0f, .max = 1.0f, .enabled = false},
+ }
+ },
+ {
+ .name = "Topology Rake Mode",
+ .idname = "TOPOLOGY_RAKE_MODE",
+ .type = BRUSH_CHANNEL_ENUM,
+ .enumdef = {.items = {
+ {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 = {
+ {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",
+ .idname = "DYNTOPO_DISABLED",
+ .type = BRUSH_CHANNEL_INT,
+ .flag = BRUSH_CHANNEL_NO_MAPPINGS,
+ .ivalue = 0
+ },
+ {
+ .name = "Detail Range",
+ .idname = "DYNTOPO_DETAIL_RANGE",
+ .type = BRUSH_CHANNEL_FLOAT,
+ .min = 0.001,
+ .max = 0.99,
+ .ivalue = 0
+ },
+};
+
+/* clang-format on */
+const int builtin_channel_len = ARRAY_SIZE(brush_builtin_channels);
+
+void BKE_brush_channel_free(BrushChannel *ch)
+{
+ for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
+ BKE_curvemapping_free_data(&ch->mappings[i].curve);
+ }
+}
+
+void BKE_brush_channel_copy(BrushChannel *dst, BrushChannel *src)
+{
+ *dst = *src;
+
+ for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
+ BKE_curvemapping_copy_data(&dst->mappings[i].curve, &src->mappings[i].curve);
+ }
+}
+
+void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
+{
+ memset(ch, 0, sizeof(*ch));
+
+ strcpy(ch->name, def->name);
+ strcpy(ch->idname, def->idname);
+
+ ch->flag = def->flag;
+ ch->fvalue = def->fvalue;
+ ch->ivalue = def->ivalue;
+
+ ch->def = def;
+
+ for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
+ BrushMapping *map = ch->mappings + i;
+ CurveMapping *curve = &map->curve;
+
+ BKE_curvemapping_init(curve);
+
+ float min, max;
+
+ BrushMappingDef *mdef = (&def->mappings.pressure) + i;
+
+ if (mdef->min != mdef->max) {
+ min = mdef->min;
+ max = mdef->max;
+ }
+ else {
+ min = 0.0f;
+ max = 1.0f;
+ }
+
+ if (mdef->inv) {
+ ch->mappings[i].flag |= BRUSH_MAPPING_INVERT;
+ }
+
+ map->blendmode = mdef->blendmode;
+ map->factor = 1.0f;
+
+ if (mdef->enabled) {
+ map->flag |= BRUSH_MAPPING_ENABLED;
+ }
+ }
+}
+
+BrushChannelSet *BKE_brush_channelset_create()
+{
+ return (BrushChannelSet *)MEM_callocN(sizeof(BrushChannelSet), "BrushChannelSet");
+}
+
+void BKE_brush_channelset_free(BrushChannelSet *chset)
+{
+ if (chset->channels) {
+ for (int i = 0; i < chset->totchannel; i++) {
+ BKE_brush_channel_free(chset->channels + i);
+ }
+
+ MEM_freeN(chset->channels);
+ }
+ MEM_freeN(chset);
+}
+
+void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch)
+{
+ chset->totchannel++;
+
+ if (!chset->channels) {
+ chset->channels = MEM_callocN(sizeof(BrushChannelSet) * chset->totchannel, "chset->channels");
+ }
+ else {
+ chset->channels = MEM_recallocN(chset->channels,
+ sizeof(BrushChannelSet) * sizeof(chset->totchannel));
+ }
+
+ memcpy(chset->channels + chset->totchannel - 1, ch, sizeof(BrushChannelSet));
+}
+
+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;
+}
+
+bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname)
+{
+ return BKE_brush_channelset_lookup(chset, idname) != NULL;
+}
+
+void BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname)
+{
+ BrushChannelType *def = NULL;
+
+ for (int i = 0; i < builtin_channel_len; i++) {
+ BrushChannelType *def2 = builtin_channel_len + i;
+
+ if (STREQ(def2->idname, idname)) {
+ def = def2;
+ break;
+ }
+ }
+
+ if (!def) {
+ printf("%s: Could not find brush %s\n", __func__, idname);
+ return;
+ }
+
+ BrushChannel ch;
+
+ BKE_brush_channel_init(&ch, def);
+ BKE_brush_channelset_add(chset, &ch);
+}
+
+bool BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname)
+{
+ if (!BKE_brush_channelset_has(chset, idname)) {
+ BKE_brush_channelset_add_builtin(chset, idname);
+ return true;
+ }
+
+ return false;
+}
+
+#define ADDCH(name) BKE_brush_channelset_ensure_builtin(chset, name)
+#define GETCH(name) BKE_brush_channelset_lookup(chset, name)
+
+void BKE_brush_channelset_merge(BrushChannelSet *dst,
+ BrushChannelSet *child,
+ BrushChannelSet *parent)
+{
+ // first add missing channels
+
+ for (int step = 0; step < 2; step++) {
+ BrushChannelSet *chset = step ? parent : child;
+
+ for (int i = 0; i < chset->totchannel; i++) {
+ BrushChannel *ch = chset->channels + i;
+
+ if (BKE_brush_channelset_has(dst, ch->idname)) {
+ continue;
+ }
+
+ BrushChannel ch2;
+ BKE_brush_channel_copy(&ch2, ch);
+ BKE_brush_channelset_add(chset, &ch2);
+ }
+ }
+
+ for (int i = 0; i < child->totchannel; i++) {
+ BrushChannel *ch = child->channels + i;
+ BrushChannel *mch = BKE_brush_channelset_lookup(dst, ch->idname);
+ BrushChannel *pch = BKE_brush_channelset_lookup(parent, ch->name);
+
+ bool ok = ch->flag & BRUSH_CHANNEL_INHERIT;
+
+ if (ch->flag & BRUSH_CHANNEL_INHERIT) {
+ BKE_brush_channel_free(mch);
+ BKE_brush_channel_copy(mch, pch);
+ continue;
+ }
+
+ if (ch->type == BRUSH_CHANNEL_BITMASK && (ch->flag & BRUSH_CHANNEL_INHERIT_IF_UNSET)) {
+ mch->ivalue = ch->ivalue | pch->ivalue;
+ }
+ }
+}
+
+void BKE_brush_resolve_channels(Brush *brush, Sculpt *sd)
+{
+ if (brush->channels_final) {
+ BKE_brush_channelset_free(brush->channels_final);
+ }
+
+ brush->channels_final = BKE_brush_channelset_create();
+
+ BKE_brush_channelset_merge(brush->channels_final, brush->channels, sd->channels);
+
+ if (!brush->commandlist) {
+ return;
+ }
+
+ BrushCommandList *cl = brush->commandlist;
+
+ for (int i = 0; i < cl->totcommand; i++) {
+ BrushCommand *command = cl->commands + i;
+
+ if (command->params_final) {
+ BKE_brush_channelset_free(command->params_final);
+ }
+
+ command->params_final = BKE_brush_channelset_create();
+ BKE_brush_channelset_merge(command->params_final, command->params, brush->channels_final);
+ }
+}
+
+int BKE_brush_channel_get_int(BrushChannelSet *chset, char *idname)
+{
+ BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
+
+ if (!ch) {
+ printf("%s, unknown channel %s", __func__, idname);
+ return 0;
+ }
+
+ return ch->ivalue;
+}
+
+float BKE_brush_channel_get_float(BrushChannelSet *chset, char *idname)
+{
+ BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
+
+ if (!ch) {
+ printf("%s, unknown channel %s", __func__, idname);
+ return 0;
+ }
+
+ return ch->fvalue;
+}
+
+float BKE_brush_channel_set_float(BrushChannelSet *chset, char *idname, float val)
+{
+ BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
+
+ if (!ch) {
+ printf("%s, unknown channel %s", __func__, idname);
+ return 0;
+ }
+
+ float old = ch->fvalue;
+
+ ch->fvalue = val;
+
+ return old;
+}
+
+void BKE_brush_init_toolsettings(Sculpt *sd)
+{
+ BrushChannelSet *chset = sd->channels = BKE_brush_channelset_create();
+
+ ADDCH("RADIUS");
+ ADDCH("STRENGTH");
+ ADDCH("AUTOMASKING");
+ ADDCH("DYNTOPO_DISABLED");
+ ADDCH("DYNTOPO_DETAIL_RANGE");
+}
+
+void BKE_brush_builtin_create(Brush *brush, int tool)
+{
+ if (brush->channels) {
+ BKE_brush_channelset_free(brush->channels);
+ }
+
+ BrushChannelSet *chset = brush->channels = BKE_brush_channelset_create();
+
+ ADDCH("RADIUS");
+ ADDCH("STRENGTH");
+ ADDCH("AUTOSMOOTH");
+ ADDCH("TOPOLOGY_RAKE");
+ ADDCH("AUTOSMOOTH_RADIUS_SCLAE");
+ ADDCH("RAKE_RADIUS_SCALE");
+
+ ADDCH("AUTOMASKING");
+
+ switch (tool) {
+ case SCULPT_TOOL_DRAW: {
+ BrushChannel *ch = GETCH("STRENGTH");
+
+ ch->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
+ ch->flag = BRUSH_CHANNEL_INHERIT;
+ break;
+ }
+ }
+}
+
+BrushCommandList *BKE_brush_commandlist_create()
+{
+ return MEM_callocN(sizeof(BrushCommandList), "BrushCommandList");
+}
+void BKE_brush_commandlist_free(BrushCommandList *cl)
+{
+ for (int i = 0; i < cl->totcommand; i++) {
+ BrushCommand *cmd = cl->commands + i;
+
+ if (cmd->params) {
+ BKE_brush_channelset_free(cmd->params);
+ }
+
+ if (cmd->params_final) {
+ BKE_brush_channelset_free(cmd->params_final);
+ }
+ }
+
+ MEM_SAFE_FREE(cl->commands);
+
+ MEM_freeN(cl);
+}
+BrushCommand *BKE_brush_commandlist_add(BrushCommandList *cl)
+{
+ cl->totcommand++;
+
+ if (!cl->commands) {
+ cl->commands = MEM_callocN(sizeof(BrushCommand) * cl->totcommand, "BrushCommand");
+ }
+ else {
+ cl->commands = MEM_recallocN(cl->commands, sizeof(BrushCommand) * cl->totcommand);
+ }
+
+ BrushCommand *cmd = cl->commands + cl->totcommand - 1;
+ cmd->params = BKE_brush_channelset_create();
+ cmd->params_final = NULL;
+
+ return cmd;
+}
+
+BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool)
+{
+ BrushChannelSet *chset = command->params;
+
+ ADDCH("SPACING");
+
+ switch (tool) {
+ case SCULPT_TOOL_DRAW:
+ ADDCH("RADIUS");
+ ADDCH("STRENGTH");
+ break;
+ case SCULPT_TOOL_SMOOTH:
+ ADDCH("RADIUS");
+ ADDCH("STRENGTH");
+ ADDCH("FSET_SLIDE");
+ ADDCH("BOUNDARY_SMOOTH");
+ ADDCH("PROJECTION");
+ break;
+ case SCULPT_TOOL_TOPOLOGY_RAKE:
+ ADDCH("RADIUS");
+ ADDCH("STRENGTH");
+ // ADDCH("FSET_SLIDE");
+ // ADDCH("BOUNDARY_SMOOTH");
+ ADDCH("PROJECTION");
+ ADDCH("TOPOLOGY_RAKE_MODE");
+ break;
+ case SCULPT_TOOL_DYNTOPO:
+ break;
+ }
+
+ return command;
+}
+
+void BKE_builtin_commandlist_create(BrushChannelSet *chset, BrushCommandList *cl, int tool)
+{
+ BrushCommand *cmd;
+
+ cmd = BKE_brush_commandlist_add(cl);
+ BKE_brush_command_init(cmd, tool);
+
+ for (int i = 0; i < cmd->totparam; i++) {
+ // inherit from brush channels for main tool
+ cmd->params->channels[i].flag |= BRUSH_CHANNEL_INHERIT;
+ }
+
+ float radius = BKE_brush_channel_get_float(chset, "RADIUS");
+ float autosmooth_scale = BKE_brush_channel_get_float(chset, "AUTOSMOOTH_RADIUS_SCALE");
+
+ float autosmooth = BKE_brush_channel_get_float(chset, "AUTOSMOOTH");
+ if (autosmooth > 0.0f) {
+ cmd = BKE_brush_command_init(BKE_brush_commandlist_add(cl), SCULPT_TOOL_SMOOTH);
+ BKE_brush_channel_set_float(cmd->params, "STRENGTH", autosmooth);
+ BKE_brush_channel_set_float(cmd->params, "RADIUS", radius * autosmooth_scale);
+ BKE_brush_channel_set_float(
+ cmd->params, "PROJECTION", BKE_brush_channel_get_float(chset, "AUTOSMOOTH_PROJECTION"));
+ }
+}
+
+void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *cset)
+{
+ BLO_read_data_address(reader, &cset->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_read(reader, &ch->mappings[j].curve);
+ }
+ }
+}
+
+void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet *cset)
+{
+ BLO_write_struct(writer, BrushChannelSet, cset);
+ BLO_write_struct_array_by_name(writer, "BrushChannel", cset->totchannel, cset->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);
+ }
+ }
+}
+
+/* clang-format on */
+
+/* idea for building built-in preset node graphs:
+from brush_builder import Builder;
+
+def build(input, output):
+ input.add("Strength", "float", "strength").range(0.0, 3.0)
+ input.add("Radius", "float", "radius").range(0.01, 1024.0)
+ input.add("Autosmooth", "float", "autosmooth").range(0.0, 4.0)
+ input.add("Topology Rake", "float", "topology rake").range(0.0, 4.0)
+ input.add("Smooth Radius Scale", "float", "autosmooth_radius_scale").range(0.01, 5.0)
+ input.add("Rake Radius Scale", "float", "toporake_radius_scale").range(0.01, 5.0)
+
+ draw = input.make.tool("DRAW")
+ draw.radius = input.radius
+ draw.strength = input.strength
+
+ smooth = input.make.tool("SMOOTH")
+ smooth.radius = input.radius * input.autosmooth_radius_scale
+ smooth.strength = input.autosmooth;
+ smooth.flow = draw.outflow
+
+ rake = input.make.tool("TOPORAKE")
+ rake.radius = input.radius * input.toporake_radius_scale
+ rake.strength = input.topology;
+ rake.flow = smooth.outflow
+
+ output.out = rake.outflow
+
+preset = Builder(build)
+
+*/
+
+/*
+bNodeType sculpt_tool_node = {
+ .idname = "SculptTool",
+ .ui_name = "SculptTool",
+};*/
+/* cland-format on */
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 10517f76b04..74fc5e6de7a 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -69,6 +69,7 @@
#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
+#include "BKE_brush_engine.h"
#include "BKE_cachefile.h"
#include "BKE_collection.h"
#include "BKE_colortools.h"
@@ -849,6 +850,11 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
}
if (tos->sculpt) {
BLO_write_struct(writer, Sculpt, tos->sculpt);
+
+ if (tos->sculpt->channels) {
+ BKE_brush_channelset_write(writer, tos->sculpt->channels);
+ }
+
BKE_paint_blend_write(writer, &tos->sculpt->paint);
}
if (tos->uvsculpt) {
@@ -1050,6 +1056,11 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
sce->toolsettings->particle.object = NULL;
sce->toolsettings->gp_sculpt.paintcursor = NULL;
+ if (sce->toolsettings->sculpt && sce->toolsettings->sculpt->channels) {
+ BLO_read_data_address(reader, &sce->toolsettings->sculpt->channels);
+ BKE_brush_channelset_read(reader, sce->toolsettings->sculpt->channels);
+ }
+
/* relink grease pencil interpolation curves */
BLO_read_data_address(reader, &sce->toolsettings->gp_interpolate.custom_ipo);
if (sce->toolsettings->gp_interpolate.custom_ipo) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_brush_machine.c b/source/blender/editors/sculpt_paint/sculpt_brush_machine.c
index b4771bd783d..e69de29bb2d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_brush_machine.c
+++ b/source/blender/editors/sculpt_paint/sculpt_brush_machine.c
@@ -1,316 +0,0 @@
-#if 1
-# include "MEM_guardedalloc.h"
-
-# include "BLI_alloca.h"
-# include "BLI_array.h"
-# include "BLI_bitmap.h"
-# include "BLI_compiler_attrs.h"
-# include "BLI_compiler_compat.h"
-# include "BLI_listbase.h"
-# include "BLI_math.h"
-# include "BLI_memarena.h"
-
-# include "DNA_brush_enums.h"
-# include "DNA_brush_types.h"
-# include "DNA_color_types.h"
-# include "DNA_curveprofile_types.h"
-# include "DNA_node_types.h"
-
-# include "BKE_brush.h"
-# include "BKE_colorband.h"
-# include "BKE_colortools.h"
-# include "BKE_context.h"
-# include "BKE_node.h"
-# include "BKE_paint.h"
-
-# include "BKE_curveprofile.h"
-
-# define MAX_BRUSH_COMMAND_PARAMS 16
-# define MAX_BRUSH_CHANNEL_CURVES 3
-
-enum {
- BRUSH_CHANNEL_RADIUS = 1 << 0,
- BRUSH_CHANNEL_STRENGTH = 1 << 1,
- BRUSH_CHANNEL_CLOTH_TYPE = 1 << 2, // int
- BRUSH_CHANNEL_RADIUS_SCALE = 1 << 3,
- // BRUSH_CHANNEL_ITERATIONS = 1 << 3, // int
- // BRUSH_CHANNEL_BOUNDARY_TYPE = 1 << 4,
- // BRUSH_CHANNEL_AUTOMASKING_TYPE = 1 << 5,
- CHANNEL_CUSTOM = 1 << 20
-};
-
-typedef struct BrushChannel {
- int type;
- char name[32]; // for custom types
-
- float value;
- CurveMapping curves[MAX_BRUSH_CHANNEL_CURVES];
- int flag;
-} BrushChannel;
-
-# define MAX_BRUSH_ENUM_DEF 32
-
-typedef struct BrushEnumDef {
- EnumPropertyItem items[MAX_BRUSH_ENUM_DEF];
-} BrushEnumDef;
-
-typedef struct BrushChannelType {
- char name[32];
- int channel;
- float min, max, softmin, softmax;
- int curve_presets[MAX_BRUSH_CHANNEL_CURVES];
- int type, subtype;
- BrushEnumDef enumdef; // if an enum type
-} BrushChannelType;
-
-// curves
-enum { BRUSH_CHANNEL_PRESSURE, BRUSH_CHANNEL_XTILT, BRUSH_CHANNEL_YTILT };
-
-enum {
- BRUSH_CHANNEL_FLOAT = 1 << 0,
- BRUSH_CHANNEL_INT = 1 << 1,
- BRUSH_CHANNEL_ENUM = 1 << 0 // subtype
-};
-
-/* BrushChannel->flag */
-enum {
- /*float only flags*/
- BRUSH_CHANNEL_USE_PRESSURE = 1 << 0,
- BRUSH_CHANNEL_INV_PRESSURE = 1 << 1,
- BRUSH_CHANNEL_USE_TILT = 1 << 2,
-};
-
-/*
-Brush command lists.
-
-Command lists are built dynamically from
-brush flags, pen input settings, etc.
-
-Eventually they will be generated by node
-networks. BrushCommandPreset will be
-generated from the node group inputs.
-*/
-
-typedef struct BrushCommandPreset {
- char name[64];
- int tool;
-
- struct {
- char name[32];
- int type;
- float defval;
- BrushChannelType *custom_type;
- } channels[32];
-} BrushCommandPreset;
-
-/* clang-format off */
-BrushCommandPreset DrawBrush = {
- .name = "Draw",
- .tool = SCULPT_TOOL_DRAW,
- .channels = {
- {.name = "Radius", .type = BRUSH_CHANNEL_RADIUS, .defval = 50.0f},
- {.name = "Strength", .type = BRUSH_CHANNEL_STRENGTH, .defval = 1.0f},
- {.name = "Autosmooth", .type = BRUSH_CHANNEL_STRENGTH, .defval = 0.0f},
- {.name = "Autosmooth Radius Scale", .type = BRUSH_CHANNEL_RADIUS_SCALE, .defval = 1.0f},
- {.name = "Topology Rake", .type = BRUSH_CHANNEL_STRENGTH, .defval = 0.0f},
- {.name = "Topology Rake Radius Scale", .type = BRUSH_CHANNEL_RADIUS_SCALE, .defval = 1.0f},
- {.type = -1}
- }
-};
-
-typedef struct BrushCommand {
- int tool;
- BrushChannel params[MAX_BRUSH_COMMAND_PARAMS];
- int totparam;
-} BrushCommand;
-
-typedef struct BrushCommandList {
- BrushCommand *commands;
- int totcommand;
-} BrushCommandList;
-
-static BrushChannelType brush_builtin_channels[] = {
- {.name = "Radius",
- .channel = BRUSH_CHANNEL_RADIUS,
- .type = BRUSH_CHANNEL_FLOAT,
- .min = 0.001,
- .max = 1024,
- .softmin = 0.001,
- .softmax = 700,
- .curve_presets = {CURVE_PRESET_SMOOTH}},
- {.name = "Strength",
- .channel = BRUSH_CHANNEL_STRENGTH,
- .type = BRUSH_CHANNEL_FLOAT,
- .min = 0.001,
- .max = 1024,
- .softmin = 0.001,
- .softmax = 700,
- .curve_presets = {CURVE_PRESET_SMOOTH}},
- {.name = "Cloth Deform Type",
- .channel = BRUSH_CHANNEL_CLOTH_TYPE,
- .type = BRUSH_CHANNEL_INT,
- .subtype = BRUSH_CHANNEL_ENUM,
- .enumdef =
- {
- {BRUSH_CLOTH_DEFORM_DRAG, "DRAG", 0, "Drag", ""},
- {BRUSH_CLOTH_DEFORM_PUSH, "PUSH", 0, "Push", ""},
- {BRUSH_CLOTH_DEFORM_PINCH_POINT, "PINCH_POINT", 0, "Pinch Point", ""},
- {BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR,
- "PINCH_PERPENDICULAR",
- 0,
- "Pinch Perpendicular",
- ""},
- {BRUSH_CLOTH_DEFORM_INFLATE, "INFLATE", 0, "Inflate", ""},
- {BRUSH_CLOTH_DEFORM_GRAB, "GRAB", 0, "Grab", ""},
- {BRUSH_CLOTH_DEFORM_EXPAND, "EXPAND", 0, "Expand", ""},
- {BRUSH_CLOTH_DEFORM_SNAKE_HOOK, "SNAKE_HOOK", 0, "Snake Hook", ""},
- {0, NULL, 0, NULL, NULL},
- }},
- {.name = "Radius Scale",
- .channel = BRUSH_CHANNEL_RADIUS,
- .type = BRUSH_CHANNEL_FLOAT,
- .min = 0.001,
- .max = 15.0,
- .softmin = 0.1,
- .softmax = 4.0,
- .curve_presets = {CURVE_PRESET_SMOOTH}}};
-
-enum {
- BRUSH_COMMAND_TOPOLOGY_RAKE = 500,
- BRUSH_COMMAND_DYNTOPO = 501,
- BRUSH_COMMAND_SMOOTH_LAP = 502,
- BRUSH_COMMAND_SMOOTH_SURFACE = 503,
-};
-
-/* clang-format on */
-
-enum {
- SCULPT_OP_INT = 1 << 0,
- SCULPT_OP_FLOAT = 1 << 1,
- SCULPT_OP_VEC2 = 1 << 2,
- SCULPT_OP_VEC3 = 1 << 3,
- SCULPT_OP_VEC4 = 1 << 4,
- SCULPT_OP_VEC5 = 1 << 5,
- SCULPT_OP_PTR = 1 << 6
-};
-
-typedef union SculptReg {
- float f;
- int i;
- float v[5];
- void *p;
- char ch[32];
- // BrushChannel *ch;
-} SculptReg;
-
-typedef struct SculptOpCode {
- int code;
- SculptReg params[16];
-} SculptOpCode;
-
-# define SCULPT_MAXREG 32
-
-typedef struct SculptVM {
- SculptOpCode *opcodes;
- int totopcode;
- SculptReg regs[SCULPT_MAXREG];
-};
-
-enum {
- SOP_LOADF = 0, // reg, float
- SOP_LOADI,
- SOP_LOADF2, // reg, float, float
- SOP_LOADF3, // reg, float, float, float
- SOP_LOADF4, // reg, float, float, float, float
- SOP_LOADPTR, // reg, ptr
-
- SOP_PUSH, // reg
- SOP_POP, // reg
- SOP_POP_DISCARD, //
- SOP_MUL, // dstreg reg reg
- SOP_ADD, // dstreg reg reg
- SOP_SUB, // dstreg reg reg
- SOP_DIV, // dstreg reg reg
-
- SOP_LOAD_CHANNEL_F, // reg channel
- SOP_LOAD_CHANNEL_I, // reg channel
- SOP_TOOL_EXEC, // tool, ...
-};
-
-# define BRUSH_VALUE_DEFAULT FLT_MAX;
-
-/* clang-format off */
-#define REG_RADIUS 10
-#define REG_STRENGTH 11
-#define REG_AUTOSMOOTH 12
-#define REG_TOPORAKE 13
-
-#define OP(op) {op},
-#define OP_I_CH(op, i1, ch1) {op, {{.i = i1}, {.ch = ch1}, {.i = -1}}},
-#define OP_I(op, i1, i2) {op, {{.i = i1}, {.i = -1}}},
-#define OP_I2(op, i1, i2) {op, {{.i = i1}, {.i = i2}, {.i = -1}}},
-#define OP_I3(op, i1, i2, i3) {op, {{.i = i1}, {.i = i2}, {.i = i3}, {.i = -1}}},
-#define OP_I4(op, i1, i2, i3, i4) {op, {{.i = i1}, {.i = i2}, {.i = i3}, {.i = i4}, {.i = -1}}},
-
-SculptOpCode preset[] = {
- OP_I_CH(SOP_LOAD_CHANNEL_F, REG_RADIUS, "Radius")
- OP_I_CH(SOP_LOAD_CHANNEL_F, REG_STRENGTH, "Strength")
- OP_I3(SOP_TOOL_EXEC, SCULPT_TOOL_DRAW, REG_RADIUS, REG_STRENGTH)
-
- OP_I_CH(SOP_LOAD_CHANNEL_F, REG_AUTOSMOOTH, "Radius")
- OP_I_CH(SOP_LOAD_CHANNEL_F, REG_AUTOSMOOTH, "Autosmooth Radius Scale")
- OP_I3(SOP_MUL, REG_AUTOSMOOTH, REG_AUTOSMOOTH, REG_RADIUS)
-};
-
-typedef struct GraphNode {
- char name[32];
- char id[32];
-
- struct {
- char src[32];
- char node[32];
- char dst[32];
- } inputs[32];
-} GraphNode;
-
-/* node preset solution b:
-
-from brush_builder import Builder;
-
-def build(input, output):
- input.add("Strength", "float", "strength").range(0.0, 3.0)
- input.add("Radius", "float", "radius").range(0.01, 1024.0)
- input.add("Autosmooth", "float", "autosmooth").range(0.0, 4.0)
- input.add("Topology Rake", "float", "topology rake").range(0.0, 4.0)
- input.add("Smooth Radius Scale", "float", "autosmooth_radius_scale").range(0.01, 5.0)
- input.add("Rake Radius Scale", "float", "toporake_radius_scale").range(0.01, 5.0)
-
- draw = input.make.tool("DRAW")
- draw.radius = input.radius
- draw.strength = input.strength
-
- smooth = input.make.tool("SMOOTH")
- smooth.radius = input.radius * input.autosmooth_radius_scale
- smooth.strength = input.autosmooth;
- smooth.flow = draw.outflow
-
- rake = input.make.tool("TOPORAKE")
- rake.radius = input.radius * input.toporake_radius_scale
- rake.strength = input.topology;
- rake.flow = smooth.outflow
-
- output.out = rake.outflow
-
-preset = Builder(build)
-
-*/
-
-
-
-/*
-bNodeType sculpt_tool_node = {
- .idname = "SculptTool",
- .ui_name = "SculptTool",
-};*/
-/* cland-format on */
-#endif
diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h
index 2f838513bf0..6f0b09614c7 100644
--- a/source/blender/makesdna/DNA_brush_enums.h
+++ b/source/blender/makesdna/DNA_brush_enums.h
@@ -477,7 +477,10 @@ typedef enum eBrushSculptTool {
SCULPT_TOOL_DISPLACEMENT_ERASER = 31,
SCULPT_TOOL_DISPLACEMENT_SMEAR = 32,
SCULPT_TOOL_VCOL_BOUNDARY = 33,
- SCULPT_TOOL_UV_SMOOTH = 34
+ SCULPT_TOOL_UV_SMOOTH = 34,
+
+ SCULPT_TOOL_TOPOLOGY_RAKE = 35,
+ SCULPT_TOOL_DYNTOPO = 36
} eBrushSculptTool;
/* Brush.uv_sculpt_tool */
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 84809daeb00..42135992477 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -36,6 +36,8 @@ struct CurveMapping;
struct Image;
struct MTex;
struct Material;
+struct BrushChannelSet;
+struct BrushCommandList;
typedef struct BrushClone {
/** Image for clone tool. */
@@ -399,6 +401,12 @@ typedef struct Brush {
struct BrushGpencilSettings *gpencil_settings;
DynTopoSettings dyntopo, cached_dyntopo;
+
+ /* new brush engine stuff */
+
+ struct BrushChannelSet *channels;
+ struct BrushChannelSet *channels_final;
+ struct BrushCommandList *commandlist;
} Brush;
/* Struct to hold palette colors for sorting. */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 3538d1d01f5..70146d02108 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -971,6 +971,8 @@ typedef struct ParticleEditSettings {
/* ------------------------------------------- */
/* Sculpt */
+struct BrushChannelSet;
+
/* Sculpt */
typedef struct Sculpt {
Paint paint;
@@ -1004,6 +1006,7 @@ typedef struct Sculpt {
struct Object *gravity_object;
float dyntopo_radius_scale;
int _pad[1];
+ struct BrushChannelSet *channels;
} Sculpt;
typedef struct UvSculpt {
diff --git a/source/blender/makesdna/DNA_sculpt_brush_types.h b/source/blender/makesdna/DNA_sculpt_brush_types.h
new file mode 100644
index 00000000000..eba4c89c5b5
--- /dev/null
+++ b/source/blender/makesdna/DNA_sculpt_brush_types.h
@@ -0,0 +1,84 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup DNA
+ *
+ * Structs used for the sculpt brush system
+ */
+#pragma once
+
+typedef struct BrushMapping {
+ char name[64];
+ CurveMapping curve;
+ float factor;
+ short blendmode;
+ short input_channel;
+ int flag, _pad[1];
+} BrushMapping;
+
+typedef struct BrushChannel {
+ char idname[64];
+ char name[64];
+
+ struct BrushChannelType *def;
+
+ float fvalue;
+ int ivalue;
+ BrushMapping mappings[5]; // should always be BRUSH_MAPPING_MAX
+
+ int type, flag;
+} BrushChannel;
+
+typedef struct BrushChannelSet {
+ BrushChannel *channels;
+ int totchannel, _pad[1];
+} BrushChannelSet;
+
+// mapping flags
+enum { BRUSH_MAPPING_ENABLED = 1 << 0, BRUSH_MAPPING_INVERT = 1 << 1 };
+
+// mapping types
+enum {
+ BRUSH_MAPPING_PRESSURE = 0,
+ BRUSH_MAPPING_XTILT = 1,
+ BRUSH_MAPPING_YTILT = 2,
+ BRUSH_MAPPING_ANGLE = 3,
+ BRUSH_MAPPING_SPEED = 4,
+ BRUSH_MAPPING_MAX = 5 // see BrushChannel.mappings
+};
+
+static_assert(offsetof(BrushChannel, type) - offsetof(BrushChannel, mappings) ==
+ sizeof(BrushMapping) * BRUSH_MAPPING_MAX,
+ "BrushChannel.mappings must == BRUSH_MAPPING_MAX");
+
+// BrushChannel->flag
+enum {
+ BRUSH_CHANNEL_INHERIT = 1 << 0,
+ BRUSH_CHANNEL_INHERIT_IF_UNSET = 1 << 1,
+ BRUSH_CHANNEL_NO_MAPPINGS = 1 << 2
+};
+
+// BrushChannelType->type
+enum {
+ BRUSH_CHANNEL_FLOAT = 1 << 0,
+ BRUSH_CHANNEL_INT = 1 << 1,
+ BRUSH_CHANNEL_ENUM = 1 << 2,
+ BRUSH_CHANNEL_BITMASK = 1 << 3,
+};
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index db34cf83fa9..41e95205ccc 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -165,6 +165,7 @@ set(SRC
../DNA_view3d_defaults.h
../DNA_volume_defaults.h
../DNA_world_defaults.h
+ ../DNA_sculpt_brush_types.h
)
set(LIB
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 061c3462a69..6822c48380a 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -142,6 +142,7 @@ static const char *includefiles[] = {
"DNA_simulation_types.h",
"DNA_pointcache_types.h",
"DNA_asset_types.h",
+ "DNA_sculpt_brush_types.h",
/* see comment above before editing! */
@@ -1666,6 +1667,7 @@ int main(int argc, char **argv)
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_sculpt_brush_types.h"
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
#include "DNA_session_uuid_types.h"
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 7e6d0aea2ee..cdbd7fe023e 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -34,6 +34,7 @@ set(DEFSRC
rna_attribute.c
rna_boid.c
rna_brush.c
+ rna_brush_engine.c
rna_cachefile.c
rna_camera.c
rna_cloth.c
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 36f19907080..eda878f378d 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -4365,6 +4365,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_asset.c", NULL, RNA_def_asset},
{"rna_boid.c", NULL, RNA_def_boid},
{"rna_brush.c", NULL, RNA_def_brush},
+ {"rna_brush_engine.c", NULL, RNA_def_brush_engine},
{"rna_cachefile.c", NULL, RNA_def_cachefile},
{"rna_camera.c", "rna_camera_api.c", RNA_def_camera},
{"rna_cloth.c", NULL, RNA_def_cloth},
diff --git a/source/blender/makesrna/intern/rna_brush_engine.c b/source/blender/makesrna/intern/rna_brush_engine.c
new file mode 100644
index 00000000000..2c4011b956b
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_brush_engine.c
@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup RNA
+ */
+
+#include <stdlib.h>
+
+#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.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_math.h"
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "IMB_imbuf.h"
+
+#include "WM_types.h"
+
+#ifdef RNA_RUNTIME
+#endif
+
+void RNA_def_brush_engine(BlenderRNA *brna)
+{
+}
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 0bb76fd933a..157ec9fbd90 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -156,6 +156,7 @@ void RNA_def_attribute(struct BlenderRNA *brna);
void RNA_def_asset(struct BlenderRNA *brna);
void RNA_def_boid(struct BlenderRNA *brna);
void RNA_def_brush(struct BlenderRNA *brna);
+void RNA_def_brush_engine(struct BlenderRNA *brna);
void RNA_def_cachefile(struct BlenderRNA *brna);
void RNA_def_camera(struct BlenderRNA *brna);
void RNA_def_cloth(struct BlenderRNA *brna);