diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-11-02 01:10:23 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-11-02 11:40:39 +0300 |
commit | ac8d7873278c47e8e282b7f83888108e2720a451 (patch) | |
tree | 902a404882e4ab22b8d7a153fbfc2e306747b083 | |
parent | 5bd3f3e64b7eba34e6c1676b82eec5b3c7d49d97 (diff) |
Tool System: brushes are now categorized by tool
The toolbar now shows brush types, the brush selector now
only shows brushes matching the current tool type.
Details:
- Add's Paint.tool_slots (used by the toolbar).
- Removed custom grease pencil brush tool code.
- Bumped subversion.
See T57526 for details.
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); |