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:
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py4
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py157
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py26
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_paint.h7
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/brush.c20
-rw-r--r--source/blender/blenkernel/intern/library_query.c3
-rw-r--r--source/blender/blenkernel/intern/paint.c7
-rw-r--r--source/blender/blenkernel/intern/paint_toolslots.c126
-rw-r--r--source/blender/blenloader/intern/readfile.c7
-rw-r--r--source/blender/blenloader/intern/versioning_280.c11
-rw-r--r--source/blender/blenloader/intern/writefile.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c14
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c6
-rw-r--r--source/blender/makesdna/DNA_brush_types.h21
-rw-r--r--source/blender/makesdna/DNA_scene_types.h12
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_brush.c67
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c113
21 files changed, 414 insertions, 198 deletions
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 91892e010b7..363cc5f1797 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -341,10 +341,10 @@ class GreasePencilAppearancePanel:
layout.prop(gp_settings, "use_cursor", text="Show Brush")
- if gp_settings.tool == 'DRAW':
+ if brush.gpencil_tool == 'DRAW':
layout.prop(gp_settings, "show_lasso", text="Show fill color while drawing")
- if gp_settings.tool == 'FILL':
+ if brush.gpencil_tool == 'FILL':
layout.prop(brush, "cursor_color_add", text="Color")
elif ob.mode in {'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}:
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 04b64325771..caffcf829c5 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -38,65 +38,40 @@ from .properties_grease_pencil_common import (
AnnotationDataPanel,
)
-def generate_from_brushes_ex(
- context, *,
+
+def generate_from_brushes_tool_slots_ex(
+ context, paint, *,
icon_prefix,
- brush_test_attr,
brush_category_attr,
brush_category_layout,
+ # Optional
+ icon_fn=None,
+ tooldef_keywords={},
):
# Categories
brush_categories = {}
- if context.mode != 'GPENCIL_PAINT':
- for brush in context.blend_data.brushes:
- if getattr(brush, brush_test_attr) and brush.gpencil_settings is None:
- category = getattr(brush, brush_category_attr)
- name = brush.name
- brush_categories.setdefault(category, []).append(
- ToolDef.from_dict(
- dict(
- text=name,
- icon=icon_prefix + category.lower(),
- data_block=name,
- )
- )
- )
- else:
- def draw_settings(context, layout, tool):
- _defs_gpencil_paint.draw_settings_common(context, layout, tool)
+ for paint_slot in paint.tool_slots:
+ brush = paint_slot.brush
+ if brush is None:
+ continue
+ category = getattr(brush, brush_category_attr)
+
+ if icon_fn is not None:
+ icon_id = icon_fn(brush)
+ else:
+ icon_id = category.lower()
- for brush_type in brush_category_layout:
- for brush in context.blend_data.brushes:
- if brush.gpencil_settings and getattr(brush, brush_test_attr) and brush.gpencil_settings.gp_icon == brush_type[0]:
- category = brush_type[0]
- name = brush.name
- text = name
-
- # Define icon.
- icon_name = {
- 'PENCIL': 'draw_pencil',
- 'PEN': 'draw_pen',
- 'INK': 'draw_ink',
- 'INKNOISE': 'draw_noise',
- 'BLOCK': 'draw_block',
- 'MARKER': 'draw_marker',
- 'FILL': 'draw_fill',
- 'SOFT': 'draw.eraser_soft',
- 'HARD': 'draw.eraser_hard',
- 'STROKE': 'draw.eraser_stroke',
- }[category]
- brush_categories.setdefault(category, []).append(
- ToolDef.from_dict(
- dict(
- text=text,
- icon=icon_prefix + icon_name,
- data_block=name,
- widget=None,
- operator="gpencil.draw",
- draw_settings=draw_settings,
- )
- )
- )
+ name = brush.name
+ brush_categories.setdefault(category, []).append(
+ ToolDef.from_dict(
+ dict(
+ text=name,
+ icon=icon_prefix + icon_id,
+ data_block=name,
+ **tooldef_keywords,
+ )
+ )
+ )
def tools_from_brush_group(groups):
assert(type(groups) is tuple)
@@ -1052,10 +1027,9 @@ class _defs_sculpt:
@staticmethod
def generate_from_brushes(context):
- return generate_from_brushes_ex(
- context,
+ return generate_from_brushes_tool_slots_ex(
+ context, context.tool_settings.sculpt,
icon_prefix="brush.sculpt.",
- brush_test_attr="use_paint_sculpt",
brush_category_attr="sculpt_tool",
brush_category_layout=(
('DRAW',),
@@ -1070,7 +1044,7 @@ class _defs_sculpt:
('FILL',),
('SIMPLIFY',),
('MASK',),
- )
+ ),
)
@ToolDef.from_fn
@@ -1108,10 +1082,9 @@ class _defs_vertex_paint:
@staticmethod
def generate_from_brushes(context):
- return generate_from_brushes_ex(
- context,
+ return generate_from_brushes_tool_slots_ex(
+ context, context.tool_settings.vertex_paint,
icon_prefix="brush.paint_vertex.",
- brush_test_attr="use_paint_vertex",
brush_category_attr="vertex_tool",
brush_category_layout=(
('MIX',),
@@ -1123,7 +1096,7 @@ class _defs_vertex_paint:
'OVERLAY', 'SOFTLIGHT', 'EXCLUSION', 'LUMINOCITY',
'SATURATION', 'HUE', 'ERASE_ALPHA', 'ADD_ALPHA',
),
- )
+ ),
)
@@ -1131,10 +1104,9 @@ class _defs_texture_paint:
@staticmethod
def generate_from_brushes(context):
- return generate_from_brushes_ex(
- context,
+ return generate_from_brushes_tool_slots_ex(
+ context, context.tool_settings.image_paint,
icon_prefix="brush.paint_texture.",
- brush_test_attr="use_paint_image",
brush_category_attr="image_tool",
brush_category_layout=(
('DRAW',),
@@ -1143,7 +1115,7 @@ class _defs_texture_paint:
('CLONE',),
('FILL',),
('MASK',),
- )
+ ),
)
@@ -1158,10 +1130,9 @@ class _defs_weight_paint:
@staticmethod
def generate_from_brushes(context):
- return generate_from_brushes_ex(
- context,
+ return generate_from_brushes_tool_slots_ex(
+ context, context.tool_settings.weight_paint,
icon_prefix="brush.paint_weight.",
- brush_test_attr="use_paint_weight",
brush_category_attr="vertex_tool",
brush_category_layout=(
('MIX',),
@@ -1173,7 +1144,7 @@ class _defs_weight_paint:
'OVERLAY', 'SOFTLIGHT', 'EXCLUSION', 'LUMINOCITY',
'SATURATION', 'HUE',
),
- )
+ ),
)
@ToolDef.from_fn
@@ -1368,9 +1339,11 @@ class _defs_gpencil_paint:
ob = context.active_object
if ob and ob.mode == 'GPENCIL_PAINT':
brush = context.active_gpencil_brush
+ if brush is None:
+ return
gp_settings = brush.gpencil_settings
- if gp_settings.tool == 'ERASE':
+ if brush.gpencil_tool == 'ERASE':
row = layout.row(align=True)
row.prop(brush, "size", text="Radius")
row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
@@ -1378,7 +1351,7 @@ class _defs_gpencil_paint:
row = layout.row(align=True)
row.prop(gp_settings, "pen_strength", slider=True)
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
- elif gp_settings.tool == 'FILL':
+ elif brush.gpencil_tool == 'FILL':
row = layout.row()
row.prop(gp_settings, "fill_leak", text="Leak Size")
row.prop(brush, "size", text="Thickness")
@@ -1402,26 +1375,42 @@ class _defs_gpencil_paint:
@staticmethod
def generate_from_brushes(context):
- return generate_from_brushes_ex(
- context,
+
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_paint.draw_settings_common(context, layout, tool)
+
+ def icon_fn(brush):
+ return {
+ 'PENCIL': 'draw_pencil',
+ 'PEN': 'draw_pen',
+ 'INK': 'draw_ink',
+ 'INKNOISE': 'draw_noise',
+ 'BLOCK': 'draw_block',
+ 'MARKER': 'draw_marker',
+ 'FILL': 'draw_fill',
+ 'SOFT': 'draw.eraser_soft',
+ 'HARD': 'draw.eraser_hard',
+ 'STROKE': 'draw.eraser_stroke',
+ }[brush.gpencil_settings.gp_icon]
+
+ return generate_from_brushes_tool_slots_ex(
+ context, context.tool_settings.gpencil_paint,
icon_prefix="brush.gpencil.",
- brush_test_attr="use_paint_grease_pencil",
- brush_category_attr="grease_pencil_tool",
+ brush_category_attr="gpencil_tool",
brush_category_layout=(
- ('PENCIL',),
- ('PEN',),
- ('INK',),
- ('INKNOISE',),
- ('BLOCK',),
- ('MARKER',),
+ ('DRAW',),
('FILL',),
- ('SOFT',),
- ('HARD',),
- ('STROKE',),
- )
+ ('ERASE',),
+ ),
+ tooldef_keywords=dict(
+ operator="gpencil.draw",
+ draw_settings=draw_settings,
+ ),
+ icon_fn=icon_fn,
)
+
class _defs_gpencil_edit:
@ToolDef.from_fn
def bend():
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index f3c11023608..1abfb92917b 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1492,11 +1492,11 @@ class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
if brush is not None:
# XXX: Items in "sub" currently show up beside the brush selector in a separate column
- if gp_settings.tool == 'ERASE':
+ if brush.gpencil_tool == 'ERASE':
sub.prop(gp_settings, "use_default_eraser", text="")
# Brush details
- if gp_settings.tool == 'ERASE':
+ if brush.gpencil_tool == 'ERASE':
row = layout.row(align=True)
row.prop(brush, "size", text="Radius")
row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
@@ -1509,7 +1509,7 @@ class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
row.prop(gp_settings, "eraser_strength_factor")
row = layout.row(align=True)
row.prop(gp_settings, "eraser_thickness_factor")
- elif gp_settings.tool == 'FILL':
+ elif brush.gpencil_tool == 'FILL':
col = layout.column(align=True)
col.prop(gp_settings, "fill_leak", text="Leak Size")
col.separator()
@@ -1550,9 +1550,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_option(View3DPanel, Panel):
@classmethod
def poll(cls, context):
brush = context.active_gpencil_brush
- gp_settings = brush.gpencil_settings
-
- return brush is not None and gp_settings.tool != 'ERASE'
+ return brush is not None and brush.gpencil_tool != 'ERASE'
def draw_header_preset(self, context):
VIEW3D_PT_gpencil_brush_presets.draw_panel_header(self.layout)
@@ -1588,9 +1586,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(View3DPanel, Panel):
@classmethod
def poll(cls, context):
brush = context.active_gpencil_brush
- gp_settings = brush.gpencil_settings
-
- return brush is not None and gp_settings.tool == 'DRAW'
+ return brush is not None and brush.gpencil_tool == 'DRAW'
def draw_header(self, context):
brush = context.active_gpencil_brush
@@ -1620,9 +1616,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_settings(View3DPanel, Panel):
@classmethod
def poll(cls, context):
brush = context.active_gpencil_brush
- gp_settings = brush.gpencil_settings
-
- return brush is not None and gp_settings.tool != 'ERASE'
+ return brush is not None and brush.gpencil_tool != 'ERASE'
def draw_header(self, context):
brush = context.active_gpencil_brush
@@ -1661,9 +1655,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
@classmethod
def poll(cls, context):
brush = context.active_gpencil_brush
- gp_settings = brush.gpencil_settings
-
- return brush is not None and gp_settings.tool != 'ERASE'
+ return brush is not None and brush.gpencil_tool != 'ERASE'
def draw_header(self, context):
brush = context.active_gpencil_brush
@@ -1698,9 +1690,7 @@ class VIEW3D_PT_tools_grease_pencil_brushcurves(View3DPanel, Panel):
@classmethod
def poll(cls, context):
brush = context.active_gpencil_brush
- gp_settings = brush.gpencil_settings
-
- return brush is not None and gp_settings.tool != 'ERASE'
+ return brush is not None and brush.gpencil_tool != 'ERASE'
@staticmethod
def draw(self, context):
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index b95e2e504d0..b695132416e 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -28,7 +28,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 280
-#define BLENDER_SUBVERSION 29
+#define BLENDER_SUBVERSION 30
/* Several breakages with 280, e.g. collections vs layers */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 3782d26fc1b..b8938c87275 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -168,6 +168,13 @@ void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups, struct B
void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
+
+/* Tool slot API. */
+void BKE_paint_toolslots_init_from_main(struct Main *bmain);
+void BKE_paint_toolslots_len_ensure(struct Paint *paint, int len);
+void BKE_paint_toolslots_brush_update_ex(struct Scene *scene, struct Paint *paint, struct Brush *brush);
+void BKE_paint_toolslots_brush_update(struct Scene *scene, struct Paint *paint);
+
/* Used for both vertex color and weight paint */
struct SculptVertexPaintGeomMap {
int *vert_map_mem;
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 77c9df12428..f2e2c0406af 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -168,6 +168,7 @@ set(SRC
intern/outliner_treehash.c
intern/packedFile.c
intern/paint.c
+ intern/paint_toolslots.c
intern/particle.c
intern/particle_child.c
intern/particle_distribute.c
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 13087877d5d..94ff7f3f2e5 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -304,7 +304,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->gpencil_settings->draw_subdivide = 1;
brush->gpencil_settings->draw_random_sub = 0.0f;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
@@ -336,7 +336,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->gpencil_settings->thick_smoothlvl = 3;
brush->gpencil_settings->draw_random_sub = 0.0f;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
@@ -365,7 +365,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->gpencil_settings->draw_subdivide = 1;
brush->gpencil_settings->draw_random_sub = 0.0f;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INK;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
@@ -402,7 +402,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->gpencil_settings->draw_subdivide = 1;
brush->gpencil_settings->draw_random_sub = 0.0f;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INKNOISE;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
@@ -438,7 +438,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->gpencil_settings->draw_subdivide = 0;
brush->gpencil_settings->draw_random_sub = 0;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_BLOCK;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
@@ -469,7 +469,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->gpencil_settings->draw_subdivide = 1;
brush->gpencil_settings->draw_random_sub = 0.0f;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
@@ -483,7 +483,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->gpencil_settings->fill_threshold = 0.1f;
brush->gpencil_settings->fill_simplylvl = 1;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_FILL;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_FILL;
+ brush->gpencil_tool = GPAINT_TOOL_FILL;
brush->gpencil_settings->draw_smoothfac = 0.1f;
brush->gpencil_settings->draw_smoothlvl = 1;
@@ -501,7 +501,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->size = 30.0f;
brush->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
+ brush->gpencil_tool = GPAINT_TOOL_ERASE;
brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
brush->gpencil_settings->era_strength_f = 100.0f;
brush->gpencil_settings->era_thickness_f = 0.10f;
@@ -511,7 +511,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->size = 30.0f;
brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_HARD;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
+ brush->gpencil_tool = GPAINT_TOOL_ERASE;
brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_HARD;
/* Stroke Eraser brush */
@@ -519,7 +519,7 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->size = 30.0f;
brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_STROKE;
- brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
+ brush->gpencil_tool = GPAINT_TOOL_ERASE;
brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_STROKE;
/* set default brush */
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index e82e1cf2d6b..ea1b35e4c1e 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -280,6 +280,9 @@ static void library_foreach_mtex(LibraryForeachIDData *data, MTex *mtex)
static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint)
{
FOREACH_CALLBACK_INVOKE(data, paint->brush, IDWALK_CB_USER);
+ for (int i = 0; i < paint->tool_slots_len; i++) {
+ FOREACH_CALLBACK_INVOKE(data, paint->tool_slots[i].brush, IDWALK_CB_USER);
+ }
FOREACH_CALLBACK_INVOKE(data, paint->palette, IDWALK_CB_USER);
FOREACH_FINALIZE_VOID;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 545581e65ec..93b54fcb132 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -549,6 +549,7 @@ void BKE_paint_init(Main *bmain, Scene *sce, ePaintMode mode, const char col[3])
void BKE_paint_free(Paint *paint)
{
curvemapping_free(paint->cavity_curve);
+ MEM_SAFE_FREE(paint->tool_slots);
}
/* called when copying scene settings, so even if 'src' and 'tar' are the same
@@ -559,10 +560,16 @@ void BKE_paint_copy(Paint *src, Paint *tar, const int flag)
{
tar->brush = src->brush;
tar->cavity_curve = curvemapping_copy(src->cavity_curve);
+ tar->tool_slots = MEM_dupallocN(src->tool_slots);
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
id_us_plus((ID *)tar->brush);
id_us_plus((ID *)tar->palette);
+ if (src->tool_slots != NULL) {
+ for (int i = 0; i < tar->tool_slots_len; i++) {
+ id_us_plus((ID *)tar->tool_slots[i].brush);
+ }
+ }
}
}
diff --git a/source/blender/blenkernel/intern/paint_toolslots.c b/source/blender/blenkernel/intern/paint_toolslots.c
new file mode 100644
index 00000000000..bdafe217276
--- /dev/null
+++ b/source/blender/blenkernel/intern/paint_toolslots.c
@@ -0,0 +1,126 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/paint_toolslots.c
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_brush_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_main.h"
+#include "BKE_library.h"
+#include "BKE_paint.h"
+
+void BKE_paint_toolslots_len_ensure(Paint *paint, int len)
+{
+ if (paint->tool_slots_len < len) {
+ paint->tool_slots = MEM_recallocN(paint->tool_slots, sizeof(*paint->tool_slots) * len);
+ paint->tool_slots_len = len;
+ }
+}
+
+typedef bool (*BrushCompatFn)(const Brush *brush);
+typedef char (*BrushToolFn)(const Brush *brush);
+
+static void paint_toolslots_init_paint(
+ Main *bmain,
+ Paint *paint,
+ BrushCompatFn brush_compat_fn, BrushToolFn brush_tool_fn)
+{
+ for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) {
+ if (brush_compat_fn(brush)) {
+ uint slot_index = brush_tool_fn(brush);
+ BKE_paint_toolslots_len_ensure(paint, slot_index + 1);
+ if (paint->tool_slots[slot_index].brush == NULL) {
+ paint->tool_slots[slot_index].brush = brush;
+ id_us_plus(&brush->id);
+ }
+ }
+ }
+}
+
+/* Image paint. */
+static bool brush_compat_from_imagepaint(const Brush *brush) { return brush->ob_mode & OB_MODE_TEXTURE_PAINT; }
+static char brush_tool_from_imagepaint(const Brush *brush) { return brush->imagepaint_tool; }
+/* Sculpt. */
+static bool brush_compat_from_sculpt(const Brush *brush) { return brush->ob_mode & OB_MODE_SCULPT; }
+static char brush_tool_from_sculpt(const Brush *brush) { return brush->sculpt_tool; }
+/* Vertex Paint. */
+static bool brush_compat_from_vertexpaint(const Brush *brush) { return brush->ob_mode & OB_MODE_VERTEX_PAINT; }
+static char brush_tool_from_vertexpaint(const Brush *brush) { return brush->vertexpaint_tool; }
+/* Weight Paint. */
+static bool brush_compat_from_weightpaint(const Brush *brush) { return brush->ob_mode & OB_MODE_WEIGHT_PAINT; }
+static char brush_tool_from_weightpaint(const Brush *brush) { return brush->vertexpaint_tool; }
+/* Grease Pencil. */
+static bool brush_compat_from_gpencil(const Brush *brush) { return brush->ob_mode & OB_MODE_GPENCIL_PAINT; }
+static char brush_tool_from_gpencil(const Brush *brush) { return brush->gpencil_tool; }
+
+void BKE_paint_toolslots_init_from_main(struct Main *bmain)
+{
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ ToolSettings *ts = scene->toolsettings;
+ paint_toolslots_init_paint(bmain, &ts->imapaint.paint, brush_compat_from_imagepaint, brush_tool_from_imagepaint);
+ paint_toolslots_init_paint(bmain, &ts->sculpt->paint, brush_compat_from_sculpt, brush_tool_from_sculpt);
+ paint_toolslots_init_paint(bmain, &ts->vpaint->paint, brush_compat_from_vertexpaint, brush_tool_from_vertexpaint);
+ paint_toolslots_init_paint(bmain, &ts->wpaint->paint, brush_compat_from_weightpaint, brush_tool_from_weightpaint);
+ paint_toolslots_init_paint(bmain, &ts->gp_paint->paint, brush_compat_from_gpencil, brush_tool_from_gpencil);
+ }
+}
+
+
+void BKE_paint_toolslots_brush_update_ex(Scene *scene, Paint *paint, Brush *brush)
+{
+ ToolSettings *ts = scene->toolsettings;
+ int slot_index;
+ if (paint == &ts->imapaint.paint) {
+ slot_index = brush->imagepaint_tool;
+ }
+ else if (paint == &ts->sculpt->paint) {
+ slot_index = brush->sculpt_tool;
+ }
+ else if (paint == &ts->vpaint->paint) {
+ slot_index = brush->vertexpaint_tool;
+ }
+ else if (paint == &ts->wpaint->paint) {
+ slot_index = brush->vertexpaint_tool;
+ }
+ else if (paint == &ts->gp_paint->paint) {
+ slot_index = brush->gpencil_tool;
+ }
+ BKE_paint_toolslots_len_ensure(paint, slot_index + 1);
+ PaintToolSlot *tslot = &paint->tool_slots[slot_index];
+ id_us_plus(&brush->id);
+ id_us_min(&tslot->brush->id);
+ tslot->brush = brush;
+}
+
+void BKE_paint_toolslots_brush_update(Scene *scene, Paint *paint)
+{
+ if (paint->brush == NULL) {
+ return;
+ }
+ BKE_paint_toolslots_brush_update_ex(scene, paint, paint->brush);
+}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index ddda9eb610e..6b5b5c59706 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5910,6 +5910,11 @@ static void link_paint(FileData *fd, Scene *sce, Paint *p)
{
if (p) {
p->brush = newlibadr_us(fd, sce->id.lib, p->brush);
+ for (int i = 0; i < p->tool_slots_len; i++) {
+ if (p->tool_slots[i].brush != NULL) {
+ p->tool_slots[i].brush = newlibadr_us(fd, sce->id.lib, p->tool_slots[i].brush);
+ }
+ }
p->palette = newlibadr_us(fd, sce->id.lib, p->palette);
p->paint_cursor = NULL;
}
@@ -6205,6 +6210,8 @@ static void direct_link_paint(FileData *fd, Paint *p)
direct_link_curvemapping(fd, p->cavity_curve);
else
BKE_paint_cavity_curve_preset(p, CURVE_PRESET_LINE);
+
+ p->tool_slots = newdataadr(fd, p->tool_slots);
}
static void direct_link_paint_helper(FileData *fd, Paint **paint)
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 98bebd70d14..1384a4f28e2 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -909,6 +909,15 @@ void do_versions_after_linking_280(Main *bmain)
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 30)) {
+ for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) {
+ if (brush->gpencil_settings != NULL) {
+ brush->gpencil_tool = brush->gpencil_settings->brush_type;
+ }
+ }
+ BKE_paint_toolslots_init_from_main(bmain);
+ }
}
/* NOTE: this version patch is intended for versions < 2.52.2, but was initially introduced in 2.27 already.
@@ -2030,7 +2039,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) {
if (brush->gpencil_settings != NULL) {
BrushGpencilSettings *gp = brush->gpencil_settings;
- if (gp->brush_type == GP_BRUSH_TYPE_ERASE) {
+ if (gp->brush_type == GPAINT_TOOL_ERASE) {
gp->era_strength_f = 100.0f;
gp->era_thickness_f = 10.0f;
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 16bc845a3e9..c3693de4866 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2434,6 +2434,7 @@ static void write_paint(WriteData *wd, Paint *p)
if (p->cavity_curve) {
write_curvemapping(wd, p->cavity_curve);
}
+ writedata(wd, DATA, sizeof(PaintToolSlot) * p->tool_slots_len, p->tool_slots);
}
static void write_layer_collections(WriteData *wd, ListBase *lb)
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index ed3eab7b642..d9a233b78d8 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -134,7 +134,7 @@ static bool gp_stroke_paintmode_draw_poll(bContext *C)
Brush *brush = BKE_brush_getactive_gpencil(ts);
return ((gpd) && (gpd->flag & GP_DATA_STROKE_PAINTMODE) &&
(brush && brush->gpencil_settings) &&
- (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_DRAW));
+ (brush->gpencil_tool == GPAINT_TOOL_DRAW));
}
/* Poll callback for stroke painting (erase brush) */
@@ -146,7 +146,7 @@ static bool gp_stroke_paintmode_erase_poll(bContext *C)
Brush *brush = BKE_brush_getactive_gpencil(ts);
return ((gpd) && (gpd->flag & GP_DATA_STROKE_PAINTMODE) &&
(brush && brush->gpencil_settings) &&
- (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE));
+ (brush->gpencil_tool == GPAINT_TOOL_ERASE));
}
/* Poll callback for stroke painting (fill) */
@@ -158,7 +158,7 @@ static bool gp_stroke_paintmode_fill_poll(bContext *C)
Brush *brush = BKE_brush_getactive_gpencil(ts);
return ((gpd) && (gpd->flag & GP_DATA_STROKE_PAINTMODE) &&
(brush && brush->gpencil_settings) &&
- (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_FILL));
+ (brush->gpencil_tool == GPAINT_TOOL_FILL));
}
/* Poll callback for stroke sculpting mode */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index e734542eb43..afd91d50e1f 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1546,10 +1546,10 @@ static void gp_stroke_doeraser(tGPsdata *p)
float press = 1.0f;
/* detect if use pressure in eraser */
- if (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE) {
+ if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
use_pressure = (bool)(brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE);
}
- else if ((eraser != NULL) & (eraser->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) {
+ else if ((eraser != NULL) & (eraser->gpencil_tool == GPAINT_TOOL_ERASE)) {
use_pressure = (bool)(eraser->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE);
}
if (use_pressure) {
@@ -1645,7 +1645,7 @@ static Brush *gp_get_default_eraser(Main *bmain, ToolSettings *ts)
Brush *brush_old = paint->brush;
for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) {
if ((brush->ob_mode == OB_MODE_GPENCIL_PAINT) &&
- (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE))
+ (brush->gpencil_tool == GPAINT_TOOL_ERASE))
{
/* save first eraser to use later if no default */
if (brush_dft == NULL) {
@@ -1668,7 +1668,7 @@ static Brush *gp_get_default_eraser(Main *bmain, ToolSettings *ts)
brush_dft->size = 30.0f;
brush_dft->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
brush_dft->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
- brush_dft->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
+ brush_dft->gpencil_tool = GPAINT_TOOL_ERASE;
brush_dft->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
/* reset current brush */
@@ -1704,7 +1704,7 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p)
/* assign to temp tGPsdata */
p->brush = brush;
- if (brush->gpencil_settings->brush_type != GP_BRUSH_TYPE_ERASE) {
+ if (brush->gpencil_tool != GPAINT_TOOL_ERASE) {
p->eraser = gp_get_default_eraser(p->bmain, ts);
}
else {
@@ -2317,7 +2317,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
/* if mode is draw and the brush is eraser, cancel */
if (paintmode != GP_PAINTMODE_ERASER) {
- if ((brush) && (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) {
+ if ((brush) && (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
return 0;
}
}
@@ -2358,7 +2358,7 @@ static void gpencil_draw_cursor_set(tGPsdata *p)
{
Brush *brush = p->brush;
if ((p->paintmode == GP_PAINTMODE_ERASER) ||
- (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE))
+ (brush->gpencil_tool == GPAINT_TOOL_ERASE))
{
WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index fd7ce2d4139..5b8c11ac38c 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -1554,7 +1554,7 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *customdata)
}
/* eraser has special shape and use a different shader program */
- if (paintbrush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE) {
+ if (paintbrush->gpencil_tool == GPAINT_TOOL_ERASE) {
ED_gpencil_brush_draw_eraser(paintbrush, x, y);
return;
}
@@ -1576,7 +1576,7 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *customdata)
if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
- (paintbrush->gpencil_settings->brush_type == GP_BRUSH_TYPE_DRAW))
+ (paintbrush->gpencil_tool == GPAINT_TOOL_DRAW))
{
radius = 2.0f;
copy_v3_v3(color, gp_style->stroke_rgba);
@@ -1621,7 +1621,7 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *customdata)
if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
- (paintbrush->gpencil_settings->brush_type == GP_BRUSH_TYPE_DRAW))
+ (paintbrush->gpencil_tool == GPAINT_TOOL_DRAW))
{
imm_draw_circle_fill_2d(pos, x, y, radius, 40);
}
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 4801aee3c60..9cf23f30287 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -80,8 +80,7 @@ typedef struct BrushGpencilSettings {
int input_samples; /* maximum distance before generate new point for very fast mouse movements */
float uv_random; /* random factor for UV rotation */
-
- int brush_type; /* type of brush (draw, fill, erase, etc..) */
+ int brush_type DNA_DEPRECATED; /* moved to 'Brush.gpencil_tool' */
int eraser_mode; /* soft, hard or stroke */
float active_smooth; /* smooth while drawing factor */
float era_strength_f; /* factor to apply to strength for soft eraser */
@@ -133,13 +132,6 @@ typedef enum eGP_FillDrawModes {
GP_FILL_DMODE_CONTROL = 2,
} eGP_FillDrawModes;
-/* BrushGpencilSettings->brush type */
-typedef enum eGP_BrushType {
- GP_BRUSH_TYPE_DRAW = 0,
- GP_BRUSH_TYPE_FILL = 1,
- GP_BRUSH_TYPE_ERASE = 2,
-} eGP_BrushType;
-
/* BrushGpencilSettings->gp_eraser_mode */
typedef enum eGP_BrushEraserMode {
GP_BRUSH_ERASER_SOFT = 0,
@@ -216,6 +208,8 @@ typedef struct Brush {
char vertexpaint_tool; /* active vertex/weight paint blend mode (poorly named) */
char imagepaint_tool; /* active image paint tool */
char mask_tool; /* enum eBrushMaskTool, only used if sculpt_tool is SCULPT_TOOL_MASK */
+ char gpencil_tool; /* Active grease pencil tool. */
+ char _pad0[7];
float autosmooth_factor;
@@ -416,6 +410,15 @@ typedef enum eBrushImagePaintTool {
PAINT_TOOL_MASK = 5
} eBrushImagePaintTool;
+
+/* BrushGpencilSettings->brush type */
+typedef enum eBrushGPaintTool {
+ GPAINT_TOOL_DRAW = 0,
+ GPAINT_TOOL_FILL = 1,
+ GPAINT_TOOL_ERASE = 2,
+} eBrushGPaintTool;
+
+
/* direction that the brush displaces along */
enum {
SCULPT_DISP_DIR_AREA = 0,
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 7d71f1250e3..31627760aa3 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -797,9 +797,21 @@ typedef struct TimeMarker {
#define PAINT_MAX_INPUT_SAMPLES 64
+/* We might want to store other things here. */
+typedef struct PaintToolSlot {
+ struct Brush *brush;
+} PaintToolSlot;
+
/* Paint Tool Base */
typedef struct Paint {
struct Brush *brush;
+
+ /* Each tool has it's own active brush,
+ * The currently active tool is defined by the current 'brush'. */
+ struct PaintToolSlot *tool_slots;
+ int tool_slots_len;
+ char _pad1[4];
+
struct Palette *palette;
struct CurveMapping *cavity_curve; /* cavity curve */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index ad193eecbe8..2c0d647332c 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -469,6 +469,7 @@ extern StructRNA RNA_OutflowFluidSettings;
extern StructRNA RNA_PackedFile;
extern StructRNA RNA_Paint;
extern StructRNA RNA_PaintCurve;
+extern StructRNA RNA_PaintToolSlot;
extern StructRNA RNA_Palette;
extern StructRNA RNA_PaletteColor;
extern StructRNA RNA_Panel;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 2366c5186e3..0bcb29fe860 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -126,10 +126,10 @@ const EnumPropertyItem rna_enum_brush_image_tool_items[] = {
#ifndef RNA_RUNTIME
static EnumPropertyItem rna_enum_gpencil_brush_types_items[] = {
- { GP_BRUSH_TYPE_DRAW, "DRAW", ICON_GP_STROKE, "Draw", "The brush is of type used for drawing strokes" },
- { GP_BRUSH_TYPE_FILL, "FILL", ICON_COLOR, "Fill", "The brush is of type used for filling areas" },
- { GP_BRUSH_TYPE_ERASE, "ERASE", ICON_PANEL_CLOSE, "Erase", "The brush is used for erasing strokes" },
- { 0, NULL, 0, NULL, NULL }
+ {GPAINT_TOOL_DRAW, "DRAW", ICON_GP_STROKE, "Draw", "The brush is of type used for drawing strokes"},
+ {GPAINT_TOOL_FILL, "FILL", ICON_COLOR, "Fill", "The brush is of type used for filling areas"},
+ {GPAINT_TOOL_ERASE, "ERASE", ICON_PANEL_CLOSE, "Erase", "The brush is used for erasing strokes"},
+ {0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem rna_enum_gpencil_brush_eraser_modes_items[] = {
@@ -508,33 +508,6 @@ static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
-static const EnumPropertyItem *rna_DynamicGpencil_type_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
-{
- Main *bmain = CTX_data_main(C);
- EnumPropertyItem *item = NULL, item_tmp = { 0 };
- int totitem = 0;
- int i = 0;
-
- Brush *brush;
- for (brush = bmain->brush.first; brush; brush = brush->id.next, i++) {
- if (brush->gpencil_settings == NULL)
- continue;
-
- item_tmp.identifier = brush->id.name + 2;
- item_tmp.name = brush->id.name + 2;
- item_tmp.value = i;
- item_tmp.icon = brush->gpencil_settings->icon_id;
-
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
-}
-
static void rna_TextureSlot_brush_angle_update(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
@@ -725,7 +698,7 @@ static void rna_BrushGpencilSettings_default_eraser_update(Main *bmain, Scene *s
for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) {
if ((brush != brush_cur) &&
(brush->ob_mode == OB_MODE_GPENCIL_PAINT) &&
- (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE))
+ (brush->gpencil_tool == GPAINT_TOOL_ERASE))
{
brush->gpencil_settings->flag &= ~GP_BRUSH_DEFAULT_ERASER;
}
@@ -739,7 +712,7 @@ static void rna_BrushGpencilSettings_eraser_mode_update(Main *UNUSED(bmain), Sce
Brush *brush = paint->brush;
/* set eraser icon */
- if ((brush) && (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) {
+ if ((brush) && (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
switch (brush->gpencil_settings->eraser_mode) {
case GP_BRUSH_ERASER_SOFT:
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
@@ -964,27 +937,11 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- /* Grease Pencil Drawing - generated dynamically */
- static const EnumPropertyItem prop_dynamic_gpencil_type[] = {
- {1, "DRAW", 0, "Draw", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
srna = RNA_def_struct(brna, "BrushGpencilSettings", NULL);
RNA_def_struct_sdna(srna, "BrushGpencilSettings");
RNA_def_struct_path_func(srna, "rna_BrushGpencilSettings_path");
RNA_def_struct_ui_text(srna, "Grease Pencil Brush Settings", "Settings for grease pencil brush");
- /* grease pencil drawing brushes */
- prop = RNA_def_property(srna, "grease_pencil_tool", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "brush_type");
- RNA_def_property_enum_items(prop, prop_dynamic_gpencil_type);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DynamicGpencil_type_itemf");
- RNA_def_property_ui_text(prop, "Grease Pencil Tool", "");
- /* TODO: GPXX review update */
- RNA_def_property_update(prop, 0, NULL);
- //RNA_def_property_update(prop, 0, "rna_Brush_gpencil_tool_update");
-
/* Sensitivity factor for new strokes */
prop = RNA_def_property(srna, "pen_sensitivity_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "draw_sensitivity");
@@ -1230,12 +1187,6 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Enable Cursor", "Enable cursor on screen");
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
- prop = RNA_def_property(srna, "tool", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "brush_type");
- RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_types_items);
- RNA_def_property_ui_text(prop, "Type", "Category of the brush");
- RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
-
prop = RNA_def_property(srna, "eraser_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "eraser_mode");
RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_eraser_modes_items);
@@ -1407,6 +1358,12 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Image Paint Tool", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_Brush_imagepaint_tool_update");
+ prop = RNA_def_property(srna, "gpencil_tool", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "gpencil_tool");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_types_items);
+ RNA_def_property_ui_text(prop, "Type", "Category of the brush");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
prop = RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_direction_items);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 9efb4fb4d97..dcddf77b963 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -273,23 +273,102 @@ static char *rna_ParticleEdit_path(PointerRNA *UNUSED(ptr))
static bool rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value)
{
Scene *scene = (Scene *)ptr->id.data;
+ const Paint *paint = ptr->data;
ToolSettings *ts = scene->toolsettings;
Brush *brush = value.id.data;
int mode = 0;
+ uint brush_tool_offset = 0;
/* check the origin of the Paint struct to see which paint
* mode to select from */
- if (ptr->data == &ts->imapaint)
+ if (paint == &ts->imapaint.paint) {
mode = OB_MODE_TEXTURE_PAINT;
- else if (ptr->data == ts->sculpt)
+ brush_tool_offset = offsetof(Brush, imagepaint_tool);
+ }
+ else if (paint == &ts->sculpt->paint) {
mode = OB_MODE_SCULPT;
- else if (ptr->data == ts->vpaint)
+ brush_tool_offset = offsetof(Brush, sculpt_tool);
+ }
+ else if (paint == &ts->vpaint->paint) {
mode = OB_MODE_VERTEX_PAINT;
- else if (ptr->data == ts->wpaint)
+ brush_tool_offset = offsetof(Brush, vertexpaint_tool);
+ }
+ else if (paint == &ts->wpaint->paint) {
mode = OB_MODE_WEIGHT_PAINT;
- else if (ptr->data == ts->gp_paint)
+ brush_tool_offset = offsetof(Brush, vertexpaint_tool);
+ }
+ else if (paint == &ts->gp_paint->paint) {
mode = OB_MODE_GPENCIL_PAINT;
+ brush_tool_offset = offsetof(Brush, gpencil_tool);
+ }
+
+ if (brush->ob_mode & mode) {
+ if (paint->brush) {
+ const char *tool_a = (const char *)POINTER_OFFSET(paint->brush, brush_tool_offset);
+ const char *tool_b = (const char *)POINTER_OFFSET(brush, brush_tool_offset);
+ if (*tool_a == *tool_b) {
+ return true;
+ }
+ }
+ else {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool paint_contains_brush_slot(const Paint *paint, const PaintToolSlot *tslot, int *r_index)
+{
+ if ((tslot >= paint->tool_slots) &&
+ (tslot < (paint->tool_slots + paint->tool_slots_len)))
+ {
+ *r_index = (int)(tslot - paint->tool_slots);
+ return true;
+ }
+ return false;
+}
+
+static bool rna_Brush_mode_with_tool_poll(PointerRNA *ptr, PointerRNA value)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ const PaintToolSlot *tslot = ptr->data;
+ ToolSettings *ts = scene->toolsettings;
+ Brush *brush = value.id.data;
+ int mode = 0;
+ int slot_index = 0;
+
+ if (paint_contains_brush_slot(&ts->imapaint.paint, tslot, &slot_index)) {
+ if (slot_index != brush->imagepaint_tool) {
+ return false;
+ }
+ mode = OB_MODE_TEXTURE_PAINT;
+ }
+ else if (paint_contains_brush_slot(&ts->sculpt->paint, tslot, &slot_index)) {
+ if (slot_index != brush->sculpt_tool) {
+ return false;
+ }
+ mode = OB_MODE_SCULPT;
+ }
+ else if (paint_contains_brush_slot(&ts->vpaint->paint, tslot, &slot_index)) {
+ if (slot_index != brush->vertexpaint_tool) {
+ return false;
+ }
+ mode = OB_MODE_VERTEX_PAINT;
+ }
+ else if (paint_contains_brush_slot(&ts->wpaint->paint, tslot, &slot_index)) {
+ if (slot_index != brush->vertexpaint_tool) {
+ return false;
+ }
+ mode = OB_MODE_WEIGHT_PAINT;
+ }
+ else if (paint_contains_brush_slot(&ts->gp_paint->paint, tslot, &slot_index)) {
+ if (slot_index != brush->gpencil_tool) {
+ return false;
+ }
+ mode = OB_MODE_GPENCIL_PAINT;
+ }
return brush->ob_mode & mode;
}
@@ -383,9 +462,11 @@ static char *rna_ParticleBrush_path(PointerRNA *UNUSED(ptr))
static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *)ptr->id.data;
Paint *paint = ptr->data;
Brush *br = paint->brush;
BKE_paint_invalidate_overlay_all();
+ BKE_paint_toolslots_brush_update(scene, paint);
WM_main_add_notifier(NC_BRUSH | NA_SELECTED, br);
}
@@ -498,6 +579,19 @@ static void rna_def_paint_curve(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_CURVE_BEZCURVE);
}
+static void rna_def_paint_tool_slot(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "PaintToolSlot", NULL);
+ RNA_def_struct_ui_text(srna, "Paint Tool Slot", "");
+
+ prop = RNA_def_property(srna, "brush", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Brush_mode_with_tool_poll");
+ RNA_def_property_ui_text(prop, "Brush", "");
+}
static void rna_def_paint(BlenderRNA *brna)
{
@@ -514,6 +608,14 @@ static void rna_def_paint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Brush", "Active Brush");
RNA_def_property_update(prop, 0, "rna_Paint_brush_update");
+ /* paint_tool_slots */
+ prop = RNA_def_property(srna, "tool_slots", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "tool_slots", "tool_slots_len");
+ RNA_def_property_struct_type(prop, "PaintToolSlot");
+ /* don't dereference pointer! */
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_iterator_array_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Paint Tool Slots", "");
+
prop = RNA_def_property(srna, "palette", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, NULL);
@@ -1276,6 +1378,7 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
rna_def_paint_curve(brna);
+ rna_def_paint_tool_slot(brna);
rna_def_paint(brna);
rna_def_sculpt(brna);
rna_def_uv_sculpt(brna);