Change to the way brush/tool selection works, as discussed a while ago

Now, there are preset brushes made for each tool type (eg. for sculpt mode, Grab, 
Draw, Inflate, etc), and the recommended method for changing sculpt tools is to 
change between Brushes. The shortcut keys for changing between tools have 
now been changed to change between named brushes - the G key in sculpt 
mode now changes to any brush named 'Grab'.

The advantages of this are:
* Changing between brushes remembers the strength/size/texture etc settings for 
each brush. This means that for example, you can draw with a strong textured 
Clay brush, but then switch quickly to a weaker, untextured Smooth brush, 
without having to re-do your settings each time.
* You can now add your own custom shortcut keys to your own custom brushes - 
just add a keymap entry similar to the existing ones, that references your own 
custom brush names.

To bring over these new default brushes to an existing B.blend setup, just 
append them in from the new B.blend in svn.
This commit is contained in:
Matt Ebb 2009-12-28 01:27:05 +00:00
parent be55097353
commit 78aa924206
7 changed files with 10425 additions and 9831 deletions

@ -498,7 +498,15 @@ class VIEW3D_PT_tools_brush(PaintPanel):
if not context.particle_edit_object: if not context.particle_edit_object:
col = layout.split().column() col = layout.split().column()
row = col.row() row = col.row()
row.template_list(settings, "brushes", settings, "active_brush_index", rows=2)
if context.sculpt_object and brush:
defaulttools = 8
elif context.texture_paint_object and brush:
defaulttools = 4
else:
defaulttools = 2
row.template_list(settings, "brushes", settings, "active_brush_index", rows=2, maxrows=defaulttools)
col.template_ID(settings, "brush", new="brush.add") col.template_ID(settings, "brush", new="brush.add")
@ -531,9 +539,7 @@ class VIEW3D_PT_tools_brush(PaintPanel):
elif context.sculpt_object and brush: elif context.sculpt_object and brush:
col = layout.column() col = layout.column()
col.separator() col.separator()
col.prop(brush, "sculpt_tool", expand=True)
col.separator()
row = col.row(align=True) row = col.row(align=True)
row.prop(brush, "size", slider=True) row.prop(brush, "size", slider=True)
row.prop(brush, "use_size_pressure", toggle=True, text="") row.prop(brush, "use_size_pressure", toggle=True, text="")
@ -563,12 +569,6 @@ class VIEW3D_PT_tools_brush(PaintPanel):
# Texture Paint Mode # # Texture Paint Mode #
elif context.texture_paint_object and brush: elif context.texture_paint_object and brush:
col = layout.column(align=True)
col.prop_enum(settings, "tool", 'DRAW')
col.prop_enum(settings, "tool", 'SOFTEN')
col.prop_enum(settings, "tool", 'CLONE')
col.prop_enum(settings, "tool", 'SMEAR')
col = layout.column() col = layout.column()
col.prop(brush, "color", text="") col.prop(brush, "color", text="")
@ -624,6 +624,33 @@ class VIEW3D_PT_tools_brush(PaintPanel):
#row.prop(brush, "jitter", slider=True) #row.prop(brush, "jitter", slider=True)
#row.prop(brush, "use_jitter_pressure", toggle=True, text="") #row.prop(brush, "use_jitter_pressure", toggle=True, text="")
class VIEW3D_PT_tools_brush_tool(PaintPanel):
bl_label = "Tool"
bl_default_closed = True
def poll(self, context):
settings = self.paint_settings(context)
return (settings and settings.brush and (context.sculpt_object or
context.texture_paint_object))
def draw(self, context):
layout = self.layout
settings = self.paint_settings(context)
brush = settings.brush
texture_paint = context.texture_paint_object
sculpt = context.sculpt_object
col = layout.column(align=True)
if context.sculpt_object:
col.prop(brush, "sculpt_tool", expand=True)
elif context.texture_paint_object:
col.prop_enum(settings, "tool", 'DRAW')
col.prop_enum(settings, "tool", 'SOFTEN')
col.prop_enum(settings, "tool", 'CLONE')
col.prop_enum(settings, "tool", 'SMEAR')
class VIEW3D_PT_tools_brush_stroke(PaintPanel): class VIEW3D_PT_tools_brush_stroke(PaintPanel):
bl_label = "Stroke" bl_label = "Stroke"
@ -948,6 +975,7 @@ bpy.types.register(VIEW3D_PT_tools_latticeedit)
bpy.types.register(VIEW3D_PT_tools_posemode) bpy.types.register(VIEW3D_PT_tools_posemode)
bpy.types.register(VIEW3D_PT_tools_posemode_options) bpy.types.register(VIEW3D_PT_tools_posemode_options)
bpy.types.register(VIEW3D_PT_tools_brush) bpy.types.register(VIEW3D_PT_tools_brush)
bpy.types.register(VIEW3D_PT_tools_brush_tool)
bpy.types.register(VIEW3D_PT_tools_brush_stroke) bpy.types.register(VIEW3D_PT_tools_brush_stroke)
bpy.types.register(VIEW3D_PT_tools_brush_curve) bpy.types.register(VIEW3D_PT_tools_brush_curve)
bpy.types.register(VIEW3D_PT_sculpt_options) bpy.types.register(VIEW3D_PT_sculpt_options)

File diff suppressed because it is too large Load Diff

@ -660,7 +660,7 @@ void uiTemplateOperatorSearch(uiLayout *layout);
void uiTemplateHeader3D(uiLayout *layout, struct bContext *C); void uiTemplateHeader3D(uiLayout *layout, struct bContext *C);
void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex); void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex);
void uiTemplateList(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *activeptr, char *activeprop, int rows, int type); void uiTemplateList(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *activeptr, char *activeprop, int rows, int maxrows, int type);
/* items */ /* items */
void uiItemO(uiLayout *layout, char *name, int icon, char *opname); void uiItemO(uiLayout *layout, char *name, int icon, char *opname);

@ -2138,7 +2138,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe
MEM_freeN(namebuf); MEM_freeN(namebuf);
} }
void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int listtype) void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int maxrows, int listtype)
{ {
//Scene *scene= CTX_data_scene(C); //Scene *scene= CTX_data_scene(C);
PropertyRNA *prop= NULL, *activeprop; PropertyRNA *prop= NULL, *activeprop;
@ -2261,6 +2261,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propna
/* default rows */ /* default rows */
if(rows == 0) if(rows == 0)
rows= 5; rows= 5;
if (maxrows == 0)
maxrows = 5;
if(pa->list_grip_size != 0) if(pa->list_grip_size != 0)
rows= pa->list_grip_size; rows= pa->list_grip_size;
@ -2274,7 +2276,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propna
if(prop) if(prop)
len= RNA_property_collection_length(ptr, prop); len= RNA_property_collection_length(ptr, prop);
items= CLAMPIS(len, rows, MAX2(rows, 5)); items= CLAMPIS(len, rows, MAX2(rows, maxrows));
/* if list length changes and active is out of view, scroll to it */ /* if list length changes and active is out of view, scroll to it */
if(pa->list_last_len != len) if(pa->list_last_len != len)

@ -193,8 +193,6 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
ed_keymap_paint_brush_switch(keymap, "tool_settings.sculpt.active_brush_index");
for(i=0; i<=5; i++) for(i=0; i<=5; i++)
RNA_int_set(WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", ZEROKEY+i, KM_PRESS, KM_CTRL, 0)->ptr, "level", i); RNA_int_set(WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", ZEROKEY+i, KM_PRESS, KM_CTRL, 0)->ptr, "level", i);
@ -208,6 +206,8 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "relative", 1); RNA_boolean_set(kmi->ptr, "relative", 1);
/* toggles */ /* toggles */
ed_keymap_paint_brush_switch(keymap, "tool_settings.sculpt.active_brush_index");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", AKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", AKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.brush.use_anchor"); RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.brush.use_anchor");
@ -222,29 +222,29 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
/* brush switching */ /* brush switching */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", DKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", DKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.brush.sculpt_tool"); RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.active_brush_name");
RNA_string_set(kmi->ptr, "value", "DRAW"); RNA_string_set(kmi->ptr, "value", "Draw");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", SKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", SKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.brush.sculpt_tool"); RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.active_brush_name");
RNA_string_set(kmi->ptr, "value", "SMOOTH"); RNA_string_set(kmi->ptr, "value", "Smooth");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.brush.sculpt_tool"); RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.active_brush_name");
RNA_string_set(kmi->ptr, "value", "PINCH"); RNA_string_set(kmi->ptr, "value", "Pinch");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", GKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", GKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.brush.sculpt_tool"); RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.active_brush_name");
RNA_string_set(kmi->ptr, "value", "GRAB"); RNA_string_set(kmi->ptr, "value", "Grab");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", LKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", LKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.brush.sculpt_tool"); RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.active_brush_name");
RNA_string_set(kmi->ptr, "value", "LAYER"); RNA_string_set(kmi->ptr, "value", "Layer");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", TKEY, KM_PRESS, KM_SHIFT, 0); /* was just T in 2.4x */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", TKEY, KM_PRESS, KM_SHIFT, 0); // was just T in 2.4x
RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.brush.sculpt_tool"); RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.active_brush_name");
RNA_string_set(kmi->ptr, "value", "FLATTEN"); RNA_string_set(kmi->ptr, "value", "Flatten");
/* Vertex Paint mode */ /* Vertex Paint mode */
keymap= WM_keymap_find(keyconf, "Vertex Paint", 0, 0); keymap= WM_keymap_find(keyconf, "Vertex Paint", 0, 0);

@ -29,6 +29,7 @@
#include "rna_internal.h" #include "rna_internal.h"
#include "DNA_ID.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "BKE_paint.h" #include "BKE_paint.h"
@ -159,6 +160,38 @@ static void rna_Paint_active_brush_index_range(PointerRNA *ptr, int *min, int *m
*max= MAX2(p->brush_count-1, 0); *max= MAX2(p->brush_count-1, 0);
} }
static void rna_Paint_active_brush_name_get(PointerRNA *ptr, char *value)
{
Paint *p= ptr->data;
Brush *br = paint_brush(p);
BLI_strncpy(value, br->id.name+2, sizeof(br->id.name-2));
}
static int rna_Paint_active_brush_name_length(PointerRNA *ptr)
{
Paint *p= ptr->data;
Brush *br = paint_brush(p);
return strlen(br->id.name+2);
}
static void rna_Paint_active_brush_name_set(PointerRNA *ptr, const char *value)
{
Paint *p= ptr->data;
Brush *br;
int i;
for(i = 0; i < p->brush_count; ++i) {
br = p->brushes[i];
if (strcmp(br->id.name+2, value)==0) {
paint_brush_set(p, br);
return;
}
}
}
#else #else
static void rna_def_paint(BlenderRNA *brna) static void rna_def_paint(BlenderRNA *brna)
@ -182,6 +215,12 @@ static void rna_def_paint(BlenderRNA *brna)
RNA_def_property_int_funcs(prop, NULL, "rna_Paint_active_brush_index_set", "rna_Paint_active_brush_index_range"); RNA_def_property_int_funcs(prop, NULL, "rna_Paint_active_brush_index_set", "rna_Paint_active_brush_index_range");
RNA_def_property_range(prop, 0, INT_MAX); RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_update(prop, NC_BRUSH|NA_EDITED, NULL); RNA_def_property_update(prop, NC_BRUSH|NA_EDITED, NULL);
prop= RNA_def_property(srna, "active_brush_name", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_Paint_active_brush_name_get", "rna_Paint_active_brush_name_length", "rna_Paint_active_brush_name_set");
RNA_def_property_string_maxlength(prop, sizeof(((ID*)NULL)->name)-2);
RNA_def_property_ui_text(prop, "Active Brush Name", "");
RNA_def_property_update(prop, NC_BRUSH|NA_EDITED, NULL);
/* Fake property to get active brush directly, rather than integer index */ /* Fake property to get active brush directly, rather than integer index */
prop= RNA_def_property(srna, "brush", PROP_POINTER, PROP_NONE); prop= RNA_def_property(srna, "brush", PROP_POINTER, PROP_NONE);

@ -353,6 +353,7 @@ void RNA_api_ui_layout(StructRNA *srna)
parm= RNA_def_string(func, "active_property", "", 0, "", "Identifier of property in data, for the active element."); parm= RNA_def_string(func, "active_property", "", 0, "", "Identifier of property in data, for the active element.");
RNA_def_property_flag(parm, PROP_REQUIRED); RNA_def_property_flag(parm, PROP_REQUIRED);
parm= RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display.", 0, INT_MAX); parm= RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display.", 0, INT_MAX);
parm= RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Maximum number of rows to display.", 0, INT_MAX);
parm= RNA_def_enum(func, "type", list_type_items, 0, "Type", "Type of list to use."); parm= RNA_def_enum(func, "type", list_type_items, 0, "Type", "Type of list to use.");
func= RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs"); func= RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs");