GPv3: Implementation of sculpt mode tools
This implements all the sculpt tools in Grease Pencil 3. UI changes in the 3D view header and keymap entries for sculpt mode are still minimal, more entries should be added once the relevant operators are supported. A set of utility functions and a shared base class `GreasePencilStrokeOperationCommon` for sculpt operations has been added to make individual operations less verbose. The `GreasePencilStrokeParams` struct bundles common arguments to reduce the amount of boilerplate code. The `foreach_editable_drawing` utility function takes care of setting up the parameters and finding the right drawings, so the tool only has to modify the data. Common features like tracking mouse movement and inverting brush influence are handled by the common base class. Most operations are then relatively simple, with the exception of the Grab and Clone operations. - __Grab__ stores a stroke mask and weights on initialization of the stroke, rather than working with the usual selection mask. - __Clone__ needs access to the clipboard, which requires exposing the clipboard in the editor API. Pull Request: https://projects.blender.org/blender/blender/pulls/120508
This commit is contained in:
@@ -4693,6 +4693,12 @@ def km_grease_pencil_sculpt_mode(params):
|
||||
{"properties": [("scalar", 0.9)]}),
|
||||
("brush.scale_size", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 1.0 / 0.9)]}),
|
||||
# Invoke sculpt operator
|
||||
("grease_pencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
|
||||
("grease_pencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS',
|
||||
"ctrl": True}, {"properties": [("mode", 'INVERT')]}),
|
||||
("grease_pencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS',
|
||||
"shift": True}, {"properties": [("mode", 'SMOOTH')]}),
|
||||
*_template_paint_radial_control("gpencil_sculpt_paint"),
|
||||
])
|
||||
|
||||
|
||||
@@ -474,9 +474,14 @@ class _draw_tool_settings_context_mode:
|
||||
)
|
||||
|
||||
# direction
|
||||
if not capabilities.has_direction:
|
||||
if brush.gpencil_sculpt_tool in {'THICKNESS', 'STRENGTH', 'PINCH', 'TWIST'}:
|
||||
layout.row().prop(brush, "direction", expand=True, text="")
|
||||
|
||||
# Brush falloff
|
||||
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
||||
|
||||
# Active layer only switch
|
||||
layout.prop(brush.gpencil_settings, "use_active_layer_only")
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
@@ -894,11 +899,11 @@ class VIEW3D_HT_header(Header):
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE')
|
||||
|
||||
if object_mode in {'PAINT_GPENCIL', 'EDIT', 'WEIGHT_GPENCIL'}:
|
||||
if object_mode in {'PAINT_GPENCIL', 'EDIT', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_grease_pencil_multi_frame_editing", text="")
|
||||
|
||||
if object_mode in {'EDIT', 'WEIGHT_GPENCIL'}:
|
||||
if object_mode in {'EDIT', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
|
||||
sub = row.row(align=True)
|
||||
sub.enabled = tool_settings.use_grease_pencil_multi_frame_editing
|
||||
sub.popover(
|
||||
@@ -975,6 +980,35 @@ class VIEW3D_HT_header(Header):
|
||||
text="Multiframe",
|
||||
)
|
||||
|
||||
# Grease Pencil
|
||||
if obj and obj.type == 'GREASEPENCIL':
|
||||
if object_mode == 'PAINT_GREASE_PENCIL':
|
||||
row = layout.row()
|
||||
sub = row.row(align=True)
|
||||
sub.prop(tool_settings, "use_gpencil_draw_onback", text="", icon='MOD_OPACITY')
|
||||
sub.separator(factor=0.4)
|
||||
sub.prop(tool_settings, "use_gpencil_automerge_strokes", text="")
|
||||
sub.separator(factor=0.4)
|
||||
sub.prop(tool_settings, "use_gpencil_weight_data_add", text="", icon='WPAINT_HLT')
|
||||
sub.separator(factor=0.4)
|
||||
sub.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE')
|
||||
|
||||
# Select mode for Editing
|
||||
if object_mode == 'EDIT':
|
||||
row = layout.row(align=True)
|
||||
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='POINT')
|
||||
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='STROKE')
|
||||
|
||||
subrow = row.row(align=True)
|
||||
subrow.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='SEGMENT')
|
||||
|
||||
# Select mode for Sculpt
|
||||
if object_mode == 'SCULPT_GPENCIL':
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_gpencil_select_mask_point", text="")
|
||||
row.prop(tool_settings, "use_gpencil_select_mask_stroke", text="")
|
||||
row.prop(tool_settings, "use_gpencil_select_mask_segment", text="")
|
||||
|
||||
overlay = view.overlay
|
||||
|
||||
VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
|
||||
@@ -1188,7 +1222,12 @@ class VIEW3D_MT_editor_menus(Menu):
|
||||
mode_string = context.mode
|
||||
edit_object = context.edit_object
|
||||
gp_edit = obj and obj.type == 'GPENCIL' and obj.mode in {
|
||||
'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL', 'VERTEX_GPENCIL',
|
||||
'EDIT_GPENCIL',
|
||||
'PAINT_GPENCIL',
|
||||
'SCULPT_GPENCIL',
|
||||
'SCULPT_GREASE_PENCIL',
|
||||
'WEIGHT_GPENCIL',
|
||||
'VERTEX_GPENCIL',
|
||||
}
|
||||
tool_settings = context.tool_settings
|
||||
|
||||
@@ -1196,18 +1235,16 @@ class VIEW3D_MT_editor_menus(Menu):
|
||||
|
||||
# Select Menu
|
||||
if gp_edit:
|
||||
if mode_string not in {'PAINT_GPENCIL', 'WEIGHT_GPENCIL'}:
|
||||
if (
|
||||
mode_string == 'SCULPT_GPENCIL' and
|
||||
(tool_settings.use_gpencil_select_mask_point or
|
||||
tool_settings.use_gpencil_select_mask_stroke or
|
||||
tool_settings.use_gpencil_select_mask_segment)
|
||||
):
|
||||
layout.menu("VIEW3D_MT_select_edit_gpencil")
|
||||
elif mode_string == 'EDIT_GPENCIL':
|
||||
layout.menu("VIEW3D_MT_select_edit_gpencil")
|
||||
elif mode_string == 'VERTEX_GPENCIL':
|
||||
layout.menu("VIEW3D_MT_select_edit_gpencil")
|
||||
use_gpencil_masking = (tool_settings.use_gpencil_select_mask_point or
|
||||
tool_settings.use_gpencil_select_mask_stroke or
|
||||
tool_settings.use_gpencil_select_mask_segment)
|
||||
if mode_string in {
|
||||
'EDIT_GPENCIL',
|
||||
'VERTEX_GPENCIL'} or (
|
||||
mode_string in {
|
||||
'SCULPT_GPENCIL',
|
||||
'SCULPT_GREASE_PENCIL'} and use_gpencil_masking):
|
||||
layout.menu("VIEW3D_MT_select_edit_gpencil")
|
||||
elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
|
||||
mesh = obj.data
|
||||
if mesh.use_paint_mask:
|
||||
|
||||
Reference in New Issue
Block a user