Tool System: use tool type enum to access brushes
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.
This commit is contained in:
@@ -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",
|
||||
),
|
||||
|
||||
@@ -33,10 +33,12 @@
|
||||
*/
|
||||
|
||||
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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user