Tool System: use tool type enum to access brushes
authorCampbell Barton <ideasman42@gmail.com>
Tue, 6 Nov 2018 01:08:39 +0000 (12:08 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 6 Nov 2018 01:39:51 +0000 (12:39 +1100)
Previously the brush names were used which had the limit that:

- Brush names that were deleted wouldn't show up in the toolbar.
- Naming collisions between user defined brushes and existing tools
  broke tool selection.

Now brushes are created as needed when tools are selected.

Note, vertex/weight paint combine tool and blend modes,
this should be split out into a separate enum.

release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
source/blender/blenkernel/BKE_paint.h
source/blender/blenkernel/intern/paint.c
source/blender/blenkernel/intern/paint_toolslots.c
source/blender/makesrna/RNA_enum_types.h
source/blender/makesrna/intern/rna_brush.c
source/blender/makesrna/intern/rna_workspace_api.c
source/blender/windowmanager/intern/wm_toolsystem.c

index c494aae03cd9e7dc199b50e7b618dd0acdde989b..bd64e7e3834a6c0cdbc0c33a29643a1350069d78 100644 (file)
@@ -39,64 +39,12 @@ from .properties_grease_pencil_common import (
 )
 
 
-def generate_from_brushes_tool_slots_ex(
-        context, paint, *,
-        icon_prefix,
-        brush_category_attr,
-        brush_category_layout,
-        # Optional
-        tooldef_keywords={},
-):
-    # Categories
-    brush_categories = {}
-    for paint_slot in paint.tool_slots:
-        brush = paint_slot.brush
-        if brush is None:
-            continue
-        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,
-                    **tooldef_keywords,
-                )
-            )
-        )
-
-    def tools_from_brush_group(groups):
-        assert(type(groups) is tuple)
-        if len(groups) == 1:
-            tool_defs = tuple(brush_categories.pop(groups[0], ()))
-        else:
-            tool_defs = tuple(item for g in groups for item in brush_categories.pop(g, ()))
-
-        if len(tool_defs) > 1:
-            return (tool_defs,)
-        else:
-            return tool_defs
-
-    # Each item below is a single toolbar entry:
-    # Grouped for multiple or none if no brushes are found.
-    tool_defs = tuple(
-        tool_def
-        for category in brush_category_layout
-        for tool_def in tools_from_brush_group(category)
-    )
-    # Ensure we use all types.
-    if brush_categories:
-        print(brush_categories)
-    assert(len(brush_categories) == 0)
-    return tool_defs
-
-
 def generate_from_enum_ex(
         context, *,
         icon_prefix,
         type,
         attr,
+        tooldef_keywords={},
 ):
     tool_defs = []
     for enum in type.bl_rna.properties[attr].enum_items_static:
@@ -108,6 +56,7 @@ def generate_from_enum_ex(
                     text=name,
                     icon=icon_prefix + identifier.lower(),
                     data_block=identifier,
+                    **tooldef_keywords,
                 )
             )
         )
@@ -1015,26 +964,11 @@ class _defs_sculpt:
 
     @staticmethod
     def generate_from_brushes(context):
-        return generate_from_brushes_tool_slots_ex(
-            context, context.tool_settings.sculpt,
+        return generate_from_enum_ex(
+            context,
             icon_prefix="brush.sculpt.",
-            brush_category_attr="sculpt_tool",
-            brush_category_layout=(
-                ('DRAW',),
-                ('GRAB', 'THUMB'),
-                ('SNAKE_HOOK',),
-                ('BLOB', 'INFLATE'),
-                ('SMOOTH',),
-                ('SCRAPE',),
-                ('FLATTEN',),
-                ('CREASE', 'PINCH'),
-                ('CLAY', 'CLAY_STRIPS'),
-                ('LAYER',),
-                ('NUDGE', 'ROTATE'),
-                ('FILL',),
-                ('SIMPLIFY',),
-                ('MASK',),
-            ),
+            type=bpy.types.Brush,
+            attr="sculpt_tool",
         )
 
     @ToolDef.from_fn
@@ -1072,40 +1006,22 @@ class _defs_vertex_paint:
 
     @staticmethod
     def generate_from_brushes(context):
-        return generate_from_brushes_tool_slots_ex(
-            context, context.tool_settings.vertex_paint,
+        return generate_from_enum_ex(
+            context,
             icon_prefix="brush.paint_vertex.",
-            brush_category_attr="vertex_tool",
-            brush_category_layout=(
-                ('MIX',),
-                ('BLUR', 'AVERAGE'),
-                ('SMEAR',),
-                (
-                    'ADD', 'SUB', 'MUL', 'LIGHTEN', 'DARKEN',
-                    'COLORDODGE', 'DIFFERENCE', 'SCREEN', 'HARDLIGHT',
-                    'OVERLAY', 'SOFTLIGHT', 'EXCLUSION', 'LUMINOCITY',
-                    'SATURATION', 'HUE', 'ERASE_ALPHA', 'ADD_ALPHA',
-                ),
-            ),
+            type=bpy.types.Brush,
+            attr="vertex_tool",
         )
 
-
 class _defs_texture_paint:
 
     @staticmethod
     def generate_from_brushes(context):
-        return generate_from_brushes_tool_slots_ex(
-            context, context.tool_settings.image_paint,
+        return generate_from_enum_ex(
+            context,
             icon_prefix="brush.paint_texture.",
-            brush_category_attr="image_tool",
-            brush_category_layout=(
-                ('DRAW',),
-                ('SOFTEN',),
-                ('SMEAR',),
-                ('CLONE',),
-                ('FILL',),
-                ('MASK',),
-            ),
+            type=bpy.types.Brush,
+            attr="image_tool",
         )
 
 
@@ -1120,21 +1036,11 @@ class _defs_weight_paint:
 
     @staticmethod
     def generate_from_brushes(context):
-        return generate_from_brushes_tool_slots_ex(
-            context, context.tool_settings.weight_paint,
+        return generate_from_enum_ex(
+            context,
             icon_prefix="brush.paint_weight.",
-            brush_category_attr="vertex_tool",
-            brush_category_layout=(
-                ('MIX',),
-                ('BLUR', 'AVERAGE'),
-                ('SMEAR',),
-                (
-                    'ADD', 'SUB', 'MUL', 'LIGHTEN', 'DARKEN',
-                    'COLORDODGE', 'DIFFERENCE', 'SCREEN', 'HARDLIGHT',
-                    'OVERLAY', 'SOFTLIGHT', 'EXCLUSION', 'LUMINOCITY',
-                    'SATURATION', 'HUE',
-                ),
-            ),
+            type=bpy.types.Brush,
+            attr="vertex_tool",
         )
 
     @ToolDef.from_fn
@@ -1299,16 +1205,11 @@ class _defs_gpencil_paint:
 
     @staticmethod
     def generate_from_brushes(context):
-
-        return generate_from_brushes_tool_slots_ex(
-            context, context.tool_settings.gpencil_paint,
+        return generate_from_enum_ex(
+            context,
             icon_prefix="brush.gpencil_draw.",
-            brush_category_attr="gpencil_tool",
-            brush_category_layout=(
-                ('DRAW',),
-                ('FILL',),
-                ('ERASE',),
-            ),
+            type=bpy.types.Brush,
+            attr="gpencil_tool",
             tooldef_keywords=dict(
                 operator="gpencil.draw",
             ),
index 6dcd3a7c446db769f7b7a73adff3a0ad3f8ba7d0..dc05642fb695a456bdd9edfa8a75075ea60a7aca 100644 (file)
  */
 
 struct bContext;
+struct bToolRef;
 struct BMesh;
 struct BMFace;
 struct Brush;
 struct CurveMapping;
+struct EnumPropertyItem;
 struct MeshElemMap;
 struct GridPaintMask;
 struct Main;
@@ -136,9 +138,11 @@ void BKE_paint_cavity_curve_preset(struct Paint *p, int preset);
 
 eObjectMode BKE_paint_object_mode_from_paint_mode(ePaintMode mode);
 struct Paint *BKE_paint_get_active_from_paintmode(struct Scene *sce, ePaintMode mode);
+const struct EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode);
 struct Paint *BKE_paint_get_active(struct Scene *sce, struct ViewLayer *view_layer);
 struct Paint *BKE_paint_get_active_from_context(const struct bContext *C);
 ePaintMode BKE_paintmode_get_active_from_context(const struct bContext *C);
+ePaintMode BKE_paintmode_get_from_tool(const struct bToolRef *tref);
 struct Brush *BKE_paint_brush(struct Paint *paint);
 void BKE_paint_brush_set(struct Paint *paint, struct Brush *br);
 struct Palette *BKE_paint_palette(struct Paint *paint);
@@ -179,6 +183,7 @@ void BKE_paint_toolslots_len_ensure(struct Paint *paint, int len);
 void BKE_paint_toolslots_brush_update_ex(struct Paint *paint, struct Brush *brush);
 void BKE_paint_toolslots_brush_update(struct Paint *paint);
 void BKE_paint_toolslots_brush_validate(struct Main *bmain, struct Paint *paint);
+struct Brush *BKE_paint_toolslots_brush_get(struct Paint *paint, int slot_index);
 
 /* Used for both vertex color and weight paint */
 struct SculptVertexPaintGeomMap {
index f12e33344dc6e7a90749c22fc6fb3aceb1991103..6bc86f75d719260380250e32e020838521152df6 100644 (file)
@@ -79,6 +79,8 @@
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_query.h"
 
+#include "RNA_enum_types.h"
+
 #include "bmesh.h"
 
 const char PAINT_CURSOR_SCULPT[3] = {255, 100, 100};
@@ -172,6 +174,28 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode)
        return NULL;
 }
 
+const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode)
+{
+       switch (mode) {
+               case ePaintSculpt:
+                       return rna_enum_brush_sculpt_tool_items;
+               case ePaintVertex:
+                       return rna_enum_brush_vertex_tool_items;
+               case ePaintWeight:
+                       return rna_enum_brush_vertex_tool_items;
+               case ePaintTextureProjective:
+               case ePaintTexture2D:
+                       return rna_enum_brush_image_tool_items;
+               case ePaintSculptUV:
+                       return NULL;
+               case ePaintGpencil:
+                       return rna_enum_brush_gpencil_types_items;
+               case ePaintInvalid:
+                       break;
+       }
+       return NULL;
+}
+
 Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
 {
        if (sce && view_layer) {
@@ -288,6 +312,32 @@ ePaintMode BKE_paintmode_get_active_from_context(const bContext *C)
        return ePaintInvalid;
 }
 
+ePaintMode BKE_paintmode_get_from_tool(const struct bToolRef *tref)
+{
+       if (tref->space_type == SPACE_VIEW3D) {
+               switch (tref->mode) {
+                       case CTX_MODE_SCULPT:
+                               return ePaintSculpt;
+                       case CTX_MODE_PAINT_VERTEX:
+                               return ePaintVertex;
+                       case CTX_MODE_PAINT_WEIGHT:
+                               return ePaintWeight;
+                       case CTX_MODE_GPENCIL_PAINT:
+                               return ePaintGpencil;
+                       case CTX_MODE_PAINT_TEXTURE:
+                               return ePaintTextureProjective;
+               }
+       }
+       else if (tref->space_type == SPACE_IMAGE) {
+               switch (tref->mode) {
+                       case SI_MODE_PAINT:
+                               return ePaintTexture2D;
+               }
+       }
+
+       return ePaintInvalid;
+}
+
 Brush *BKE_paint_brush(Paint *p)
 {
        return p ? p->brush : NULL;
index 61e0f03ce9ee981eb3703b5b793a87a440cc0443..c0f26c1c9c15c8dfad824a88a25e7f9faa51482c 100644 (file)
@@ -22,6 +22,8 @@
  *  \ingroup bke
  */
 
+#include <limits.h>
+
 #include "MEM_guardedalloc.h"
 
 #include "DNA_modifier_types.h"
@@ -36,6 +38,8 @@
 
 void BKE_paint_toolslots_len_ensure(Paint *paint, int len)
 {
+       /* Tool slots are 'uchar'. */
+       BLI_assert(len <= UCHAR_MAX);
        if (paint->tool_slots_len < len) {
                paint->tool_slots = MEM_recallocN(paint->tool_slots, sizeof(*paint->tool_slots) * len);
                paint->tool_slots_len = len;
@@ -122,3 +126,12 @@ void BKE_paint_toolslots_brush_validate(Main *bmain, Paint *paint)
        /* Fill slots from brushes. */
        paint_toolslots_init(bmain, paint);
 }
+
+Brush *BKE_paint_toolslots_brush_get(Paint *paint, int slot_index)
+{
+       if (slot_index < paint->tool_slots_len) {
+               PaintToolSlot *tslot = &paint->tool_slots[slot_index];
+               return tslot->brush;
+       }
+       return NULL;
+}
index 935af5c8bbd358dacf32e967433142d08f3503ea..8376bdefbc46f8434328bb54853de6481d2fff82 100644 (file)
@@ -120,6 +120,7 @@ extern const EnumPropertyItem rna_enum_operator_property_tags[];
 
 extern const EnumPropertyItem rna_enum_brush_sculpt_tool_items[];
 extern const EnumPropertyItem rna_enum_brush_vertex_tool_items[];
+extern const EnumPropertyItem rna_enum_brush_gpencil_types_items[];
 extern const EnumPropertyItem rna_enum_brush_image_tool_items[];
 
 extern const EnumPropertyItem rna_enum_particle_edit_hair_brush_items[];
index 0bcb29fe860858549b2a1b3235114bbc862ceff2..ac41666a79fd2f5d46f4bbf765cc79ee54b780ec 100644 (file)
@@ -124,14 +124,14 @@ const EnumPropertyItem rna_enum_brush_image_tool_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
-#ifndef RNA_RUNTIME
-static EnumPropertyItem rna_enum_gpencil_brush_types_items[] = {
+const EnumPropertyItem rna_enum_brush_gpencil_types_items[] = {
        {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}
 };
 
+#ifndef RNA_RUNTIME
 static EnumPropertyItem rna_enum_gpencil_brush_eraser_modes_items[] = {
        { GP_BRUSH_ERASER_SOFT, "SOFT", 0, "Soft", "Use soft eraser" },
        { GP_BRUSH_ERASER_HARD, "HARD", 0, "Hard", "Use hard eraser" },
@@ -1360,7 +1360,7 @@ static void rna_def_brush(BlenderRNA *brna)
 
        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_enum_items(prop, rna_enum_brush_gpencil_types_items);
        RNA_def_property_ui_text(prop, "Type", "Category of the brush");
        RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
 
index 83ee5195fd811a6318aafa3954104d3ab206e81a..4cb74ac147956334a7bbd9b20420568696072cae 100644 (file)
@@ -116,13 +116,20 @@ static void rna_WorkspaceTool_refresh_from_context(
                                }
                        }
                        else {
-                               Paint *paint = BKE_paint_get_active(scene, view_layer);
-                               if (paint) {
+                               const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref);
+                               Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
+                               const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
+                               if (paint && paint->brush && items) {
                                        const ID *brush = (ID *)paint->brush;
-                                       if (brush) {
-                                               if (!STREQ(tref_rt->data_block, brush->name + 2)) {
-                                                       STRNCPY(tref_rt->data_block, brush->name + 2);
-                                                       STRNCPY(tref->idname, brush->name + 2);
+                                       const char tool_type = *(char *)POINTER_OFFSET(brush, paint->runtime.tool_offset);
+                                       const int i = RNA_enum_from_value(items, tool_type);
+                                       /* Possible when loading files from the future. */
+                                       if (i != -1) {
+                                               const char *name = items[i].name;
+                                               const char *identifier = items[i].identifier;
+                                               if (!STREQ(tref_rt->data_block, identifier)) {
+                                                       STRNCPY(tref_rt->data_block, identifier);
+                                                       STRNCPY(tref->idname, name);
                                                }
                                        }
                                }
index 565fade50bbad061a97167f36be60ba88d910407..04a3da5f01f2a69995f4928a1a714b7f5eee5d94 100644 (file)
@@ -41,6 +41,7 @@
 #include "DNA_workspace_types.h"
 #include "DNA_object_types.h"
 
+#include "BKE_brush.h"
 #include "BKE_context.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
@@ -242,19 +243,28 @@ static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tre
                        }
                }
                else {
-                       struct Brush *brush = (struct Brush *)BKE_libblock_find_name(bmain, ID_BR, tref_rt->data_block);
-                       if (brush) {
+                       const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref);
+                       BLI_assert(paint_mode != ePaintInvalid);
+                       const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
+                       BLI_assert(items != NULL);
+
+                       const int i = items ? RNA_enum_from_identifier(items, tref_rt->data_block) : -1;
+                       if (i != -1) {
+                               const int slot_index = items[i].value;
                                wmWindowManager *wm = bmain->wm.first;
                                for (wmWindow *win = wm->windows.first; win; win = win->next) {
                                        if (workspace == WM_window_get_active_workspace(win)) {
                                                Scene *scene = WM_window_get_active_scene(win);
-                                               ViewLayer *view_layer = WM_window_get_active_view_layer(win);
-                                               Paint *paint = BKE_paint_get_active(scene, view_layer);
-                                               if (paint) {
-                                                       if (brush) {
-                                                               BKE_paint_brush_set(paint, brush);
-                                                       }
+                                               Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
+                                               struct Brush *brush = BKE_paint_toolslots_brush_get(paint, slot_index);
+                                               if (brush == NULL) {
+                                                       /* Could make into a function. */
+                                                       brush = BKE_brush_add(bmain, items[i].name, paint->runtime.ob_mode);
+                                                       char *tool_type = (char *)POINTER_OFFSET(brush, paint->runtime.tool_offset);
+                                                       *tool_type = slot_index;
+                                                       BKE_paint_brush_set(paint, brush);
                                                }
+                                               BKE_paint_brush_set(paint, brush);
                                        }
                                }
                        }