UI: Brush Settings overhaul
This makes a number of changes to the tool settings brush UI: - All brush-related controls are now grouped together, so you can see which items are brush settings are which are not. Previously it was all jumbled together. - The brush picker is in a separate panel, so that you can switch brushes without worrying about the settings, or vice versa. - Custom Icon settings moved from the Display settings(now known as Cursor) to the Brushes panel. - UnifiedPaintSettings panels are removed and the contained options are now next to their relevant setting with a globe icon toggle. This is not displayed in the header. - 2D Falloff and Absolute Jitter toggles were changed into enums, to make it clearer what happens when they are on or off. - Adjust Strength for Spacing option was in the Options panel in some modes, but in the Stroke panel in others. It is now always under Stroke. - Display (now Cursor) panel was reorganized, settings renamed. - 2-option enums are annoying as a drop-down menu, so they are now drawn with expand=True. - Smooth Stroke and Stabilizer options in grease pencil and other paint modes are now both called "Stabilize Stroke", for consistency and clarity. - De-duplicated some drawing code between various painting modes' brush options. I tried to keep de-duplication reasonable and easy to follow. - A few more tweaks - see D5928 for the extensive list. Most of the patch is written by Demeter Dzadik, with some additions by myself Differential Revision: https://developer.blender.org/D5928 Reviewers: Pablo Dobarro, Bastien Montagne, Matias Mendiola
This commit is contained in:
@@ -131,122 +131,6 @@ class AnnotationDrawingToolsPanel:
|
||||
gpencil_stroke_placement_settings(context, col)
|
||||
|
||||
|
||||
class GreasePencilStrokeEditPanel:
|
||||
# subclass must set
|
||||
# bl_space_type = 'IMAGE_EDITOR'
|
||||
bl_label = "Edit Strokes"
|
||||
bl_category = "Tools"
|
||||
bl_region_type = 'TOOLS'
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.gpencil_data is None:
|
||||
return False
|
||||
|
||||
gpd = context.gpencil_data
|
||||
return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
is_3d_view = context.space_data.type == 'VIEW_3D'
|
||||
|
||||
if not is_3d_view:
|
||||
layout.label(text="Select:")
|
||||
col = layout.column(align=True)
|
||||
col.operator("gpencil.select_all", text="Select All")
|
||||
col.operator("gpencil.select_box")
|
||||
col.operator("gpencil.select_circle")
|
||||
|
||||
layout.separator()
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.operator("gpencil.select_linked")
|
||||
col.operator("gpencil.select_more")
|
||||
col.operator("gpencil.select_less")
|
||||
col.operator("gpencil.select_alternate")
|
||||
|
||||
layout.label(text="Edit:")
|
||||
row = layout.row(align=True)
|
||||
row.operator("gpencil.copy", text="Copy")
|
||||
row.operator("gpencil.paste", text="Paste").type = 'ACTIVE'
|
||||
row.operator("gpencil.paste", text="Paste by Layer").type = 'LAYER'
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.operator("gpencil.delete")
|
||||
col.operator("gpencil.duplicate_move", text="Duplicate")
|
||||
if is_3d_view:
|
||||
col.operator("gpencil.stroke_cyclical_set", text="Toggle Cyclic").type = 'TOGGLE'
|
||||
col.operator_menu_enum("gpencil.stroke_caps_set", text="Toggle Caps...", property="type")
|
||||
|
||||
layout.separator()
|
||||
|
||||
if not is_3d_view:
|
||||
col = layout.column(align=True)
|
||||
col.operator("transform.translate") # icon='MAN_TRANS'
|
||||
col.operator("transform.rotate") # icon='MAN_ROT'
|
||||
col.operator("transform.resize", text="Scale") # icon='MAN_SCALE'
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.separator()
|
||||
col = layout.column(align=True)
|
||||
col.operator_menu_enum("gpencil.stroke_arrange", text="Arrange Strokes...", property="direction")
|
||||
col.operator("gpencil.stroke_change_color", text="Assign Material")
|
||||
|
||||
layout.separator()
|
||||
col = layout.column(align=True)
|
||||
col.operator("gpencil.stroke_subdivide", text="Subdivide")
|
||||
row = col.row(align=True)
|
||||
row.operator("gpencil.stroke_simplify_fixed", text="Simplify")
|
||||
row.operator("gpencil.stroke_simplify", text="Adaptive")
|
||||
row.operator("gpencil.stroke_trim", text="Trim")
|
||||
|
||||
col.separator()
|
||||
|
||||
row = col.row(align=True)
|
||||
row.operator("gpencil.stroke_merge", text="Merge")
|
||||
row.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
|
||||
row.operator("gpencil.stroke_join", text="& Copy").type = 'JOINCOPY'
|
||||
|
||||
col.operator("gpencil.stroke_flip", text="Flip Direction")
|
||||
|
||||
if is_3d_view:
|
||||
layout.separator()
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.operator_menu_enum("gpencil.stroke_separate", text="Separate...", property="mode")
|
||||
col.operator("gpencil.stroke_split", text="Split")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Cleanup:")
|
||||
col.operator_menu_enum("gpencil.reproject", text="Reproject Strokes...", property="type")
|
||||
col.operator_menu_enum("gpencil.frame_clean_fill", text="Clean Boundary Strokes...", property="mode")
|
||||
|
||||
|
||||
class GreasePencilStrokeSculptPanel:
|
||||
# subclass must set
|
||||
# bl_space_type = 'IMAGE_EDITOR'
|
||||
bl_label = "Sculpt Strokes"
|
||||
bl_category = "Tools"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
|
||||
layout.template_icon_view(settings, "sculpt_tool", show_labels=True)
|
||||
|
||||
if not self.is_popover:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_sculpt_settings,
|
||||
)
|
||||
brush_basic_gpencil_sculpt_settings(layout, context, brush)
|
||||
|
||||
|
||||
class GreasePencilSculptOptionsPanel:
|
||||
bl_label = "Sculpt Strokes"
|
||||
|
||||
@@ -276,16 +160,35 @@ class GreasePencilSculptOptionsPanel:
|
||||
|
||||
layout.prop(settings, "use_edit_uv", text="Affect UV")
|
||||
|
||||
|
||||
# GP Object Tool Settings
|
||||
class GreasePencilAppearancePanel:
|
||||
bl_label = "Brush Appearance"
|
||||
class GreasePencilDisplayPanel:
|
||||
bl_label = "Brush Tip"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.active_object
|
||||
return ob and ob.type == 'GPENCIL'
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
if ob and ob.type == 'GPENCIL' and brush:
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
return brush.gpencil_tool != 'ERASE'
|
||||
else:
|
||||
# GP Sculpt and Weight Paint always have Brush Tip panel.
|
||||
return True
|
||||
|
||||
def draw_header(self, context):
|
||||
if self.is_popover: return
|
||||
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
self.layout.prop(gp_settings, "use_cursor", text="")
|
||||
elif context.mode in ('SCULPT_GPENCIL', 'WEIGHT_GPENCIL'):
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
|
||||
self.layout.prop(brush, "use_cursor", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -299,42 +202,44 @@ class GreasePencilAppearancePanel:
|
||||
brush = tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
sub = layout.column(align=True)
|
||||
sub.enabled = not brush.use_custom_icon
|
||||
sub.prop(gp_settings, "gp_icon", text="Icon")
|
||||
if self.is_popover:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "use_cursor", text="")
|
||||
row.label(text="Display Cursor")
|
||||
|
||||
layout.prop(brush, "use_custom_icon")
|
||||
sub = layout.column()
|
||||
sub.active = brush.use_custom_icon
|
||||
sub.prop(brush, "icon_filepath", text="")
|
||||
|
||||
layout.prop(gp_settings, "use_cursor", text="Show Brush")
|
||||
col = layout.column(align=True)
|
||||
col.active = gp_settings.use_cursor
|
||||
|
||||
if brush.gpencil_tool == 'DRAW':
|
||||
layout.prop(gp_settings, "show_lasso", text="Show Fill Color While Drawing")
|
||||
col.prop(gp_settings, "show_lasso", text="Show Fill Color While Drawing")
|
||||
|
||||
if brush.gpencil_tool == 'FILL':
|
||||
layout.prop(brush, "cursor_color_add", text="Color")
|
||||
col.prop(brush, "cursor_color_add", text="Cursor Color")
|
||||
|
||||
elif ob.mode in {'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
|
||||
settings = tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
tool = settings.sculpt_tool
|
||||
|
||||
if self.is_popover:
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "use_cursor", text="")
|
||||
row.label(text="Display Cursor")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(brush, "use_cursor", text="Show Brush")
|
||||
col.active = brush.use_cursor
|
||||
|
||||
if tool in {'THICKNESS', 'STRENGTH'}:
|
||||
col.prop(brush, "cursor_color_add", text="Add")
|
||||
col.prop(brush, "cursor_color_sub", text="Subtract")
|
||||
col.prop(brush, "cursor_color_add", text="Add Cursor Color")
|
||||
col.prop(brush, "cursor_color_sub", text="Subtract Cursor Color")
|
||||
elif tool == 'PINCH':
|
||||
col.prop(brush, "cursor_color_add", text="Pinch")
|
||||
col.prop(brush, "cursor_color_sub", text="Inflate")
|
||||
col.prop(brush, "cursor_color_add", text="Pinch Cursor Color")
|
||||
col.prop(brush, "cursor_color_sub", text="Inflate Cursor Color")
|
||||
elif tool == 'TWIST':
|
||||
col.prop(brush, "cursor_color_add", text="CCW")
|
||||
col.prop(brush, "cursor_color_sub", text="CW")
|
||||
col.prop(brush, "cursor_color_add", text="CCW Cursor Color")
|
||||
col.prop(brush, "cursor_color_sub", text="CW Cursor Color")
|
||||
else:
|
||||
col.prop(brush, "cursor_color_add", text="")
|
||||
col.prop(brush, "cursor_color_add", text="Cursor Color")
|
||||
|
||||
|
||||
class GPENCIL_MT_pie_tool_palette(Menu):
|
||||
|
||||
@@ -25,75 +25,462 @@ class UnifiedPaintPanel:
|
||||
# bl_space_type = 'IMAGE_EDITOR'
|
||||
# bl_region_type = 'UI'
|
||||
|
||||
@staticmethod
|
||||
def get_brush_mode(context):
|
||||
"""Get the correct mode for this context. For any context where this returns None, no brush options should be displayed."""
|
||||
|
||||
if context.mode == 'PARTICLE':
|
||||
# Particle brush settings currently completely do their own thing.
|
||||
return None
|
||||
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
|
||||
if not tool:
|
||||
# If there is no active tool, then there can't be an active brush.
|
||||
return None
|
||||
|
||||
if not tool.has_datablock:
|
||||
# tool.has_datablock is always true for tools that use brushes.
|
||||
return None
|
||||
|
||||
space_data = context.space_data
|
||||
tool_settings = context.tool_settings
|
||||
|
||||
if space_data:
|
||||
space_type = space_data.type
|
||||
if space_type == 'IMAGE_EDITOR':
|
||||
if space_data.show_uvedit:
|
||||
return 'UV_SCULPT'
|
||||
return 'PAINT_2D'
|
||||
|
||||
if space_type in ('VIEW_3D', 'PROPERTIES'):
|
||||
if context.mode == 'PAINT_TEXTURE':
|
||||
if tool_settings.image_paint and tool_settings.image_paint.detect_data():
|
||||
return context.mode
|
||||
else:
|
||||
return None
|
||||
return context.mode
|
||||
|
||||
@staticmethod
|
||||
def paint_settings(context):
|
||||
tool_settings = context.tool_settings
|
||||
|
||||
if context.sculpt_object:
|
||||
mode = UnifiedPaintPanel.get_brush_mode(context)
|
||||
|
||||
# 3D paint settings
|
||||
if mode == 'SCULPT':
|
||||
return tool_settings.sculpt
|
||||
elif context.vertex_paint_object:
|
||||
elif mode == 'PAINT_VERTEX':
|
||||
return tool_settings.vertex_paint
|
||||
elif context.weight_paint_object:
|
||||
elif mode == 'PAINT_WEIGHT':
|
||||
return tool_settings.weight_paint
|
||||
elif context.image_paint_object:
|
||||
if (tool_settings.image_paint and tool_settings.image_paint.detect_data()):
|
||||
return tool_settings.image_paint
|
||||
|
||||
return None
|
||||
elif context.particle_edit_object:
|
||||
elif mode == 'PAINT_TEXTURE':
|
||||
return tool_settings.image_paint
|
||||
elif mode == 'PARTICLE':
|
||||
return tool_settings.particle_edit
|
||||
|
||||
return None
|
||||
# 2D paint settings
|
||||
elif mode == 'PAINT_2D':
|
||||
return tool_settings.image_paint
|
||||
elif mode == 'UV_SCULPT':
|
||||
return tool_settings.uv_sculpt
|
||||
# Grease Pencil settings
|
||||
elif mode == 'PAINT_GPENCIL':
|
||||
return tool_settings.gpencil_paint
|
||||
elif mode in ('SCULPT_GPENCIL', 'WEIGHT_GPENCIL'):
|
||||
return tool_settings.gpencil_sculpt
|
||||
|
||||
@staticmethod
|
||||
def unified_paint_settings(parent, context):
|
||||
def prop_unified(layout, context, brush, prop_name, unified_name=None, pressure_name=None, icon='NONE', text=None, slider=False, display_unified_toggle=True):
|
||||
""" Generalized way of adding brush options to the UI, along with their pen pressure setting and global toggle, if they exist """
|
||||
row = layout.row(align=True)
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
prop_owner = brush
|
||||
if(unified_name and getattr(ups, unified_name) and display_unified_toggle):
|
||||
prop_owner = ups
|
||||
|
||||
flow = parent.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
row.prop(prop_owner, prop_name, icon=icon, text=text, slider=slider)
|
||||
|
||||
col = flow.column()
|
||||
col.prop(ups, "use_unified_size", text="Size")
|
||||
col = flow.column()
|
||||
col.prop(ups, "use_unified_strength", text="Strength")
|
||||
if context.weight_paint_object:
|
||||
col = flow.column()
|
||||
col.prop(ups, "use_unified_weight", text="Weight")
|
||||
elif context.vertex_paint_object or context.image_paint_object:
|
||||
col = flow.column()
|
||||
col.prop(ups, "use_unified_color", text="Color")
|
||||
else:
|
||||
col = flow.column()
|
||||
col.prop(ups, "use_unified_color", text="Color")
|
||||
if(pressure_name):
|
||||
row.prop(brush, pressure_name, text="")
|
||||
|
||||
@staticmethod
|
||||
def prop_unified_size(parent, context, brush, prop_name, *, icon='NONE', text=None, slider=False):
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
ptr = ups if ups.use_unified_size else brush
|
||||
parent.prop(ptr, prop_name, icon=icon, text=text, slider=slider)
|
||||
if(unified_name and display_unified_toggle):
|
||||
row.prop(ups, unified_name, text="", icon="WORLD")
|
||||
|
||||
@staticmethod
|
||||
def prop_unified_strength(parent, context, brush, prop_name, *, icon='NONE', text=None, slider=False):
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
ptr = ups if ups.use_unified_strength else brush
|
||||
parent.prop(ptr, prop_name, icon=icon, text=text, slider=slider)
|
||||
|
||||
@staticmethod
|
||||
def prop_unified_weight(parent, context, brush, prop_name, *, icon='NONE', text=None, slider=False):
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
ptr = ups if ups.use_unified_weight else brush
|
||||
parent.prop(ptr, prop_name, icon=icon, text=text, slider=slider)
|
||||
return row
|
||||
|
||||
@staticmethod
|
||||
def prop_unified_color(parent, context, brush, prop_name, *, text=None):
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
ptr = ups if ups.use_unified_color else brush
|
||||
parent.prop(ptr, prop_name, text=text)
|
||||
prop_owner = ups if ups.use_unified_color else brush
|
||||
parent.prop(prop_owner, prop_name, text=text)
|
||||
|
||||
@staticmethod
|
||||
def prop_unified_color_picker(parent, context, brush, prop_name, value_slider=True):
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
ptr = ups if ups.use_unified_color else brush
|
||||
parent.template_color_picker(ptr, prop_name, value_slider=value_slider)
|
||||
prop_owner = ups if ups.use_unified_color else brush
|
||||
parent.template_color_picker(prop_owner, prop_name, value_slider=value_slider)
|
||||
|
||||
|
||||
### Classes to let various paint modes' panels share code, by sub-classing these classes. ###
|
||||
class BrushPanel(UnifiedPaintPanel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return cls.get_brush_mode(context) is not None
|
||||
|
||||
|
||||
class BrushSelectPanel(BrushPanel):
|
||||
bl_label = "Brushes"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
row = layout.row()
|
||||
large_preview=True
|
||||
if large_preview:
|
||||
row.column().template_ID_preview(settings, "brush", new="brush.add", rows=3, cols=8, hide_buttons=False)
|
||||
else:
|
||||
row.column().template_ID(settings, "brush", new="brush.add")
|
||||
col = row.column()
|
||||
col.menu("VIEW3D_MT_brush_context_menu", icon='DOWNARROW_HLT', text="")
|
||||
col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
|
||||
|
||||
if brush.use_custom_icon:
|
||||
layout.prop(brush, "icon_filepath", text="")
|
||||
|
||||
|
||||
class ColorPalettePanel(BrushPanel):
|
||||
bl_label = "Color Palette"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not super().poll(context):
|
||||
return False
|
||||
|
||||
settings = cls.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
if context.space_data.type == 'IMAGE_EDITOR' or context.image_paint_object:
|
||||
capabilities = brush.image_paint_capabilities
|
||||
return capabilities.has_color
|
||||
|
||||
elif context.vertex_paint_object:
|
||||
capabilities = brush.vertex_paint_capabilities
|
||||
return capabilities.has_color
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = self.paint_settings(context)
|
||||
|
||||
layout.template_ID(settings, "palette", new="palette.new")
|
||||
if settings.palette:
|
||||
layout.template_palette(settings, "palette", color=True)
|
||||
|
||||
|
||||
class ClonePanel(BrushPanel):
|
||||
bl_label = "Clone"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not super().poll(context):
|
||||
return False
|
||||
|
||||
settings = cls.paint_settings(context)
|
||||
|
||||
mode = cls.get_brush_mode(context)
|
||||
if mode in ('PAINT_TEXTURE', 'PAINT_2D'):
|
||||
brush = settings.brush
|
||||
return brush.image_tool == 'CLONE'
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = self.paint_settings(context)
|
||||
self.layout.prop(settings, "use_clone_layer", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
layout.active = settings.use_clone_layer
|
||||
|
||||
ob = context.active_object
|
||||
col = layout.column()
|
||||
|
||||
if settings.mode == 'MATERIAL':
|
||||
if len(ob.material_slots) > 1:
|
||||
col.label(text="Materials")
|
||||
col.template_list("MATERIAL_UL_matslots", "",
|
||||
ob, "material_slots",
|
||||
ob, "active_material_index", rows=2)
|
||||
|
||||
mat = ob.active_material
|
||||
if mat:
|
||||
col.label(text="Source Clone Slot")
|
||||
col.template_list("TEXTURE_UL_texpaintslots", "",
|
||||
mat, "texture_paint_images",
|
||||
mat, "paint_clone_slot", rows=2)
|
||||
|
||||
elif settings.mode == 'IMAGE':
|
||||
mesh = ob.data
|
||||
|
||||
clone_text = mesh.uv_layer_clone.name if mesh.uv_layer_clone else ""
|
||||
col.label(text="Source Clone Image")
|
||||
col.template_ID(settings, "clone_image")
|
||||
col.label(text="Source Clone UV Map")
|
||||
col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
|
||||
|
||||
|
||||
class TextureMaskPanel(BrushPanel):
|
||||
bl_label = "Texture Mask"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
brush = context.tool_settings.image_paint.brush
|
||||
|
||||
col = layout.column()
|
||||
col.template_ID_preview(brush, "mask_texture", new="texture.new", rows=3, cols=8)
|
||||
|
||||
mask_tex_slot = brush.mask_texture_slot
|
||||
|
||||
# map_mode
|
||||
layout.row().prop(mask_tex_slot, "mask_map_mode", text="Mask Mapping")
|
||||
|
||||
if mask_tex_slot.map_mode == 'STENCIL':
|
||||
if brush.mask_texture and brush.mask_texture.type == 'IMAGE':
|
||||
layout.operator("brush.stencil_fit_image_aspect").mask = True
|
||||
layout.operator("brush.stencil_reset_transform").mask = True
|
||||
|
||||
col = layout.column()
|
||||
col.prop(brush, "use_pressure_masking", text="Pressure Masking")
|
||||
# angle and texture_angle_source
|
||||
if mask_tex_slot.has_texture_angle:
|
||||
col = layout.column()
|
||||
col.prop(mask_tex_slot, "angle", text="Angle")
|
||||
if mask_tex_slot.has_texture_angle_source:
|
||||
col.prop(mask_tex_slot, "use_rake", text="Rake")
|
||||
|
||||
if brush.brush_capabilities.has_random_texture_angle and mask_tex_slot.has_random_texture_angle:
|
||||
col.prop(mask_tex_slot, "use_random", text="Random")
|
||||
if mask_tex_slot.use_random:
|
||||
col.prop(mask_tex_slot, "random_angle", text="Random Angle")
|
||||
|
||||
# scale and offset
|
||||
col.prop(mask_tex_slot, "offset")
|
||||
col.prop(mask_tex_slot, "scale")
|
||||
|
||||
|
||||
class StrokePanel(BrushPanel):
|
||||
bl_label = "Stroke"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
mode = self.get_brush_mode(context)
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
|
||||
col.prop(brush, "stroke_method")
|
||||
|
||||
if brush.use_anchor:
|
||||
col.prop(brush, "use_edge_to_edge", text="Edge To Edge")
|
||||
|
||||
if brush.use_airbrush:
|
||||
col.prop(brush, "rate", text="Rate", slider=True)
|
||||
|
||||
if brush.use_space:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "spacing", text="Spacing")
|
||||
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
|
||||
col.separator()
|
||||
col.prop(brush, "dash_ratio", text="Dash Ratio")
|
||||
col.prop(brush, "dash_samples", text="Dash Length")
|
||||
|
||||
if brush.use_line or brush.use_curve:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "spacing", text="Spacing")
|
||||
|
||||
if brush.use_curve:
|
||||
col.template_ID(brush, "paint_curve", new="paintcurve.new")
|
||||
col.operator("paintcurve.draw")
|
||||
|
||||
if mode in ('PAINT_TEXTURE', "PAINT_2D"):
|
||||
if brush.image_paint_capabilities.has_space_attenuation:
|
||||
col.prop(brush, "use_space_attenuation")
|
||||
|
||||
if mode == 'SCULPT':
|
||||
col.row().prop(brush, "use_scene_spacing", text="Spacing Distance", expand=True)
|
||||
|
||||
if brush.sculpt_capabilities.has_space_attenuation:
|
||||
col.prop(brush, "use_space_attenuation")
|
||||
|
||||
col.separator()
|
||||
|
||||
|
||||
if (mode == 'SCULPT' and brush.sculpt_capabilities.has_jitter) or mode != 'SCULPT':
|
||||
row = col.row(align=True)
|
||||
if brush.jitter_unit == 'BRUSH':
|
||||
row.prop(brush, "jitter", slider=True)
|
||||
else:
|
||||
row.prop(brush, "jitter_absolute")
|
||||
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
|
||||
col.row().prop(brush, "jitter_unit", expand=True)
|
||||
col.separator()
|
||||
|
||||
col.prop(settings, "input_samples")
|
||||
|
||||
|
||||
class SmoothStrokePanel(BrushPanel):
|
||||
bl_label = "Stabilize Stroke"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not super().poll(context):
|
||||
return False
|
||||
settings = cls.paint_settings(context)
|
||||
brush = settings.brush
|
||||
if brush.brush_capabilities.has_smooth_stroke:
|
||||
return True
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
self.layout.prop(brush, "use_smooth_stroke", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.active = brush.use_smooth_stroke
|
||||
col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
|
||||
col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
|
||||
|
||||
|
||||
class FalloffPanel(BrushPanel):
|
||||
bl_label = "Falloff"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not super().poll(context):
|
||||
return False
|
||||
settings = cls.paint_settings(context)
|
||||
return (settings and settings.brush and settings.brush.curve)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = self.paint_settings(context)
|
||||
mode = self.get_brush_mode(context)
|
||||
brush = settings.brush
|
||||
|
||||
if brush is None:
|
||||
return
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "curve_preset", text="")
|
||||
|
||||
if brush.curve_preset == 'CUSTOM':
|
||||
layout.template_curve_mapping(brush, "curve", brush=True)
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
|
||||
row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
|
||||
row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
|
||||
row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
|
||||
row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
|
||||
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
|
||||
|
||||
if mode in {'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT'}:
|
||||
col.separator()
|
||||
row = col.row(align=True)
|
||||
row.use_property_split = True
|
||||
row.use_property_decorate = False
|
||||
row.prop(brush, "falloff_shape", expand=True)
|
||||
|
||||
|
||||
class DisplayPanel(BrushPanel):
|
||||
bl_label = "Brush Cursor"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = self.paint_settings(context)
|
||||
if settings and not self.is_popover:
|
||||
self.layout.prop(settings, "show_brush", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
mode = self.get_brush_mode(context)
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
tex_slot = brush.texture_slot
|
||||
tex_slot_mask = brush.mask_texture_slot
|
||||
|
||||
if self.is_popover:
|
||||
row = layout.row(align=True)
|
||||
row.prop(settings, "show_brush", text="")
|
||||
row.label(text="Display Cursor")
|
||||
|
||||
col = layout.column()
|
||||
col.active = brush.brush_capabilities.has_overlay and settings.show_brush
|
||||
|
||||
col.prop(brush, "cursor_color_add", text="Cursor Color")
|
||||
if mode == 'SCULPT' and brush.sculpt_capabilities.has_secondary_color:
|
||||
col.prop(brush, "cursor_color_subtract", text="Inverse Cursor Color")
|
||||
|
||||
col.separator()
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "cursor_overlay_alpha", text="Falloff Opacity")
|
||||
row.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
|
||||
row.prop(
|
||||
brush, "use_cursor_overlay", text="", toggle=True,
|
||||
icon='HIDE_OFF' if brush.use_cursor_overlay else 'HIDE_ON',
|
||||
)
|
||||
|
||||
if mode in ['PAINT_2D', 'PAINT_TEXTURE', 'PAINT_VERTEX', 'SCULPT']:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "texture_overlay_alpha", text="Texture Opacity")
|
||||
row.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
|
||||
if tex_slot.map_mode != 'STENCIL':
|
||||
row.prop(
|
||||
brush, "use_primary_overlay", text="", toggle=True,
|
||||
icon='HIDE_OFF' if brush.use_primary_overlay else 'HIDE_ON',
|
||||
)
|
||||
|
||||
if mode in ['PAINT_TEXTURE', 'PAINT_2D']:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "mask_overlay_alpha", text="Mask Texture Opacity")
|
||||
row.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
|
||||
if tex_slot_mask.map_mode != 'STENCIL':
|
||||
row.prop(
|
||||
brush, "use_secondary_overlay", text="", toggle=True,
|
||||
icon='HIDE_OFF' if brush.use_secondary_overlay else 'HIDE_ON',
|
||||
)
|
||||
|
||||
|
||||
class VIEW3D_MT_tools_projectpaint_clone(Menu):
|
||||
@@ -108,99 +495,315 @@ class VIEW3D_MT_tools_projectpaint_clone(Menu):
|
||||
props.value = i
|
||||
|
||||
|
||||
def brush_texpaint_common(panel, context, layout, brush, _settings, *, projpaint=False):
|
||||
col = layout.column()
|
||||
def brush_settings(layout, context, brush, popover=False):
|
||||
""" Draw simple brush settings for Sculpt, Texture/Vertex/Weight Paint modes, or skip certain settings for the popover """
|
||||
|
||||
if brush.image_tool == 'FILL' and not projpaint:
|
||||
col.prop(brush, "fill_threshold", text="Gradient Type", slider=True)
|
||||
mode = UnifiedPaintPanel.get_brush_mode(context)
|
||||
|
||||
elif brush.image_tool == 'SOFTEN':
|
||||
col.row().prop(brush, "direction", expand=True)
|
||||
col.prop(brush, "sharp_threshold")
|
||||
if not projpaint:
|
||||
col.prop(brush, "blur_kernel_radius")
|
||||
col.prop(brush, "blur_mode")
|
||||
elif brush.image_tool == 'MASK':
|
||||
col.prop(brush, "weight", text="Mask Value", slider=True)
|
||||
### Draw simple settings unique to each paint mode. ###
|
||||
brush_shared_settings(layout, context, brush, popover)
|
||||
|
||||
elif brush.image_tool == 'CLONE':
|
||||
if not projpaint:
|
||||
col.prop(brush, "clone_image", text="Image")
|
||||
col.prop(brush, "clone_alpha", text="Alpha")
|
||||
# Sculpt Mode #
|
||||
if mode == 'SCULPT':
|
||||
capabilities = brush.sculpt_capabilities
|
||||
|
||||
if not panel.is_popover:
|
||||
brush_basic_texpaint_settings(col, context, brush)
|
||||
# normal_radius_factor
|
||||
layout.prop(brush, "normal_radius_factor", slider=True)
|
||||
|
||||
# auto_smooth_factor and use_inverse_smooth_pressure
|
||||
if capabilities.has_auto_smooth:
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "auto_smooth_factor", pressure_name="use_inverse_smooth_pressure", slider=True)
|
||||
|
||||
# topology_rake_factor
|
||||
if (
|
||||
capabilities.has_topology_rake and
|
||||
context.sculpt_object.use_dynamic_topology_sculpting
|
||||
):
|
||||
layout.prop(brush, "topology_rake_factor", slider=True)
|
||||
|
||||
# normal_weight
|
||||
if capabilities.has_normal_weight:
|
||||
layout.prop(brush, "normal_weight", slider=True)
|
||||
|
||||
# crease_pinch_factor
|
||||
if capabilities.has_pinch_factor:
|
||||
text = "Pinch"
|
||||
if brush.sculpt_tool in ('BLOB', 'SNAKE_HOOK'):
|
||||
text = "Magnify"
|
||||
layout.prop(brush, "crease_pinch_factor", slider=True, text=text)
|
||||
|
||||
# rake_factor
|
||||
if capabilities.has_rake_factor:
|
||||
layout.prop(brush, "rake_factor", slider=True)
|
||||
|
||||
# plane_offset, use_offset_pressure, use_plane_trim, plane_trim
|
||||
if capabilities.has_plane_offset:
|
||||
layout.separator()
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "plane_offset", pressure_name="use_offset_pressure", slider=True)
|
||||
|
||||
layout.prop(brush, "use_plane_trim", text="Plane Trim")
|
||||
row = layout.row()
|
||||
row.active = brush.use_plane_trim
|
||||
row.prop(brush, "plane_trim", slider=True, text="Distance")
|
||||
layout.separator()
|
||||
|
||||
# height
|
||||
if capabilities.has_height:
|
||||
layout.prop(brush, "height", slider=True, text="Height")
|
||||
|
||||
# use_persistent, set_persistent_base
|
||||
if capabilities.has_persistence:
|
||||
ob = context.sculpt_object
|
||||
do_persistent = True
|
||||
|
||||
# not supported yet for this case
|
||||
for md in ob.modifiers:
|
||||
if md.type == 'MULTIRES':
|
||||
do_persistent = False
|
||||
break
|
||||
|
||||
if do_persistent:
|
||||
layout.separator()
|
||||
layout.prop(brush, "use_persistent")
|
||||
layout.operator("sculpt.set_persistent_base")
|
||||
layout.separator()
|
||||
|
||||
if brush.sculpt_tool == 'ELASTIC_DEFORM':
|
||||
layout.separator()
|
||||
layout.prop(brush, "elastic_deform_type")
|
||||
layout.prop(brush, "elastic_deform_volume_preservation", slider=True)
|
||||
layout.separator()
|
||||
|
||||
if brush.sculpt_tool == 'POSE':
|
||||
row = layout.row()
|
||||
row.prop(brush, "pose_offset")
|
||||
|
||||
if brush.sculpt_tool == 'SCRAPE':
|
||||
row = layout.row()
|
||||
row.prop(brush, "invert_to_scrape_fill", text = "Invert to Fill")
|
||||
|
||||
if brush.sculpt_tool == 'FILL':
|
||||
row = layout.row()
|
||||
row.prop(brush, "invert_to_scrape_fill", text = "Invert to Scrape")
|
||||
|
||||
if brush.sculpt_tool == 'GRAB':
|
||||
layout.prop(brush, "use_grab_active_vertex")
|
||||
|
||||
if brush.sculpt_tool == 'MULTIPLANE_SCRAPE':
|
||||
col = layout.column()
|
||||
col.prop(brush, "multiplane_scrape_angle")
|
||||
col.prop(brush, "use_multiplane_scrape_dynamic")
|
||||
col.prop(brush, "show_multiplane_scrape_planes_preview")
|
||||
|
||||
if brush.sculpt_tool == 'MASK':
|
||||
layout.row().prop(brush, "mask_tool", expand=True)
|
||||
|
||||
# 3D and 2D Texture Paint Mode #
|
||||
elif mode in ('PAINT_TEXTURE', 'PAINT_2D'):
|
||||
capabilities = brush.image_paint_capabilities
|
||||
|
||||
if brush.image_tool == 'FILL':
|
||||
if(brush.color_type == 'COLOR' and mode=='PAINT_2D'): # For some reason fill threshold only appears to be implemented in 2D paint.
|
||||
layout.prop(brush, "fill_threshold", text="Fill Threshold", slider=True)
|
||||
if(brush.color_type == 'GRADIENT'):
|
||||
layout.row().prop(brush, "gradient_fill_mode", expand=True)
|
||||
|
||||
|
||||
def brush_texpaint_common_clone(_panel, context, layout, _brush, settings, *, projpaint=False):
|
||||
ob = context.active_object
|
||||
col = layout.column()
|
||||
def brush_shared_settings(layout, context, brush, popover=False):
|
||||
""" Draw simple brush settings that are shared between different paint modes. """
|
||||
|
||||
if settings.mode == 'MATERIAL':
|
||||
if len(ob.material_slots) > 1:
|
||||
col.label(text="Materials")
|
||||
col.template_list("MATERIAL_UL_matslots", "",
|
||||
ob, "material_slots",
|
||||
ob, "active_material_index", rows=2)
|
||||
mode = UnifiedPaintPanel.get_brush_mode(context)
|
||||
|
||||
mat = ob.active_material
|
||||
if mat:
|
||||
col.label(text="Source Clone Slot")
|
||||
col.template_list("TEXTURE_UL_texpaintslots", "",
|
||||
mat, "texture_paint_images",
|
||||
mat, "paint_clone_slot", rows=2)
|
||||
### Determine which settings to draw. ###
|
||||
blend_mode = False
|
||||
size = False
|
||||
size_mode = False
|
||||
strength = False
|
||||
strength_pressure = False
|
||||
weight = False
|
||||
direction = False
|
||||
|
||||
elif settings.mode == 'IMAGE':
|
||||
mesh = ob.data
|
||||
# 3D and 2D Texture Paint #
|
||||
if mode in ('PAINT_TEXTURE', 'PAINT_2D'):
|
||||
if not popover:
|
||||
blend_mode = brush.image_paint_capabilities.has_color
|
||||
size = brush.image_paint_capabilities.has_radius
|
||||
strength = strength_pressure = True
|
||||
|
||||
clone_text = mesh.uv_layer_clone.name if mesh.uv_layer_clone else ""
|
||||
col.label(text="Source Clone Image")
|
||||
col.template_ID(settings, "clone_image")
|
||||
col.label(text="Source Clone UV Map")
|
||||
col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
|
||||
# Sculpt #
|
||||
if mode == 'SCULPT':
|
||||
size_mode = True
|
||||
if not popover:
|
||||
size = True
|
||||
strength = True
|
||||
strength_pressure = brush.sculpt_capabilities.has_strength_pressure
|
||||
direction = not brush.sculpt_capabilities.has_direction
|
||||
|
||||
# Vertex Paint #
|
||||
if mode == 'PAINT_VERTEX':
|
||||
if not popover:
|
||||
blend_mode = True
|
||||
size = True
|
||||
strength = True
|
||||
strength_pressure = True
|
||||
|
||||
# Weight Paint #
|
||||
if mode == 'PAINT_WEIGHT':
|
||||
if not popover:
|
||||
size = True
|
||||
weight = brush.weight_paint_capabilities.has_weight
|
||||
strength = strength_pressure = True
|
||||
if(brush.weight_tool=='DRAW'): # Only draw blend mode for the Draw tool, because for other tools it is pointless. D5928#137944
|
||||
blend_mode = True
|
||||
|
||||
# UV Sculpt #
|
||||
if mode == 'UV_SCULPT':
|
||||
size = True
|
||||
strength = True
|
||||
|
||||
### Draw settings. ###
|
||||
ups = context.scene.tool_settings.unified_paint_settings
|
||||
|
||||
if blend_mode:
|
||||
layout.prop(brush, "blend", text="Blend")
|
||||
layout.separator()
|
||||
|
||||
if weight:
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "weight", unified_name="use_unified_weight", slider=True)
|
||||
|
||||
size_owner = ups if ups.use_unified_size else brush
|
||||
size_prop = "size"
|
||||
if size_mode and (size_owner.use_locked_size == 'SCENE'):
|
||||
size_prop = "unprojected_radius"
|
||||
if size or size_mode:
|
||||
if size:
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, size_prop, unified_name="use_unified_size", pressure_name="use_pressure_size", text="Radius", slider=True)
|
||||
if size_mode:
|
||||
layout.row().prop(size_owner, "use_locked_size", expand=True)
|
||||
layout.separator()
|
||||
|
||||
if strength:
|
||||
pressure_name = "use_pressure_strength" if strength_pressure else None
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "strength", unified_name="use_unified_strength", pressure_name=pressure_name, slider=True)
|
||||
layout.separator()
|
||||
|
||||
if direction:
|
||||
layout.row().prop(brush, "direction", expand=True)
|
||||
|
||||
|
||||
def brush_texpaint_common_color(_panel, context, layout, brush, _settings, *, projpaint=False):
|
||||
UnifiedPaintPanel.prop_unified_color_picker(layout, context, brush, "color", value_slider=True)
|
||||
def brush_settings_advanced(layout, context, brush, popover=False):
|
||||
"""Draw advanced brush settings for Sculpt, Texture/Vertex/Weight Paint modes."""
|
||||
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_color(row, context, brush, "color", text="")
|
||||
UnifiedPaintPanel.prop_unified_color(row, context, brush, "secondary_color", text="")
|
||||
row.separator()
|
||||
row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="", emboss=False)
|
||||
mode = UnifiedPaintPanel.get_brush_mode(context)
|
||||
|
||||
# In the popover we want to combine advanced brush settings with non-advanced brush settings.
|
||||
if popover:
|
||||
brush_settings(layout, context, brush, popover=True)
|
||||
layout.separator()
|
||||
layout.label(text="Advanced:")
|
||||
|
||||
# These options are shared across many modes.
|
||||
use_accumulate = False
|
||||
use_frontface = False
|
||||
|
||||
if mode == 'SCULPT':
|
||||
capabilities = brush.sculpt_capabilities
|
||||
use_accumulate = capabilities.has_accumulate
|
||||
use_frontface = True
|
||||
|
||||
# topology automasking
|
||||
layout.prop(brush, "use_automasking_topology")
|
||||
|
||||
# sculpt plane settings
|
||||
if capabilities.has_sculpt_plane:
|
||||
layout.prop(brush, "sculpt_plane")
|
||||
layout.prop(brush, "use_original_normal")
|
||||
layout.prop(brush, "use_original_plane")
|
||||
layout.separator()
|
||||
|
||||
# 3D and 2D Texture Paint #
|
||||
elif mode in ('PAINT_TEXTURE', 'PAINT_2D'):
|
||||
capabilities = brush.image_paint_capabilities
|
||||
use_accumulate = capabilities.has_accumulate
|
||||
|
||||
if mode == 'PAINT_2D':
|
||||
layout.prop(brush, "use_paint_antialiasing")
|
||||
else:
|
||||
layout.prop(brush, "use_alpha")
|
||||
|
||||
# Tool specific settings
|
||||
if brush.image_tool == 'SOFTEN':
|
||||
layout.separator()
|
||||
layout.row().prop(brush, "direction", expand=True)
|
||||
layout.prop(brush, "sharp_threshold")
|
||||
if mode == 'PAINT_2D':
|
||||
layout.prop(brush, "blur_kernel_radius")
|
||||
layout.prop(brush, "blur_mode")
|
||||
|
||||
elif brush.image_tool == 'MASK':
|
||||
layout.prop(brush, "weight", text="Mask Value", slider=True)
|
||||
|
||||
elif brush.image_tool == 'CLONE':
|
||||
if mode == 'PAINT_2D':
|
||||
layout.prop(brush, "clone_image", text="Image")
|
||||
layout.prop(brush, "clone_alpha", text="Alpha")
|
||||
|
||||
# Vertex Paint #
|
||||
elif mode == 'PAINT_VERTEX':
|
||||
layout.prop(brush, "use_alpha")
|
||||
if brush.vertex_tool != 'SMEAR':
|
||||
use_accumulate = True
|
||||
use_frontface = True
|
||||
|
||||
# Weight Paint
|
||||
elif mode == 'PAINT_WEIGHT':
|
||||
if brush.weight_tool != 'SMEAR':
|
||||
use_accumulate = True
|
||||
use_frontface = True
|
||||
|
||||
### Draw shared settings. ###
|
||||
ups = context.scene.tool_settings.unified_paint_settings
|
||||
|
||||
if use_accumulate:
|
||||
layout.prop(brush, "use_accumulate")
|
||||
|
||||
if use_frontface:
|
||||
layout.prop(brush, "use_frontface", text="Front Faces Only")
|
||||
|
||||
|
||||
def brush_texpaint_common_gradient(_panel, context, layout, brush, _settings, *, projpaint=False):
|
||||
layout.template_color_ramp(brush, "gradient", expand=True)
|
||||
def draw_color_settings(context, layout, brush, color_type=False):
|
||||
"""Draw color wheel and gradient settings."""
|
||||
ups = context.scene.tool_settings.unified_paint_settings
|
||||
|
||||
layout.use_property_split = True
|
||||
if color_type:
|
||||
row = layout.row()
|
||||
row.use_property_split = False
|
||||
row.prop(brush, "color_type", expand=True)
|
||||
|
||||
col = layout.column()
|
||||
# Color wheel
|
||||
if brush.color_type == 'COLOR':
|
||||
UnifiedPaintPanel.prop_unified_color_picker(layout, context, brush, "color", value_slider=True)
|
||||
|
||||
if brush.image_tool == 'DRAW':
|
||||
UnifiedPaintPanel.prop_unified_color(col, context, brush, "secondary_color", text="Background Color")
|
||||
col.prop(brush, "gradient_stroke_mode", text="Gradient Mapping")
|
||||
if brush.gradient_stroke_mode in {'SPACING_REPEAT', 'SPACING_CLAMP'}:
|
||||
col.prop(brush, "grad_spacing")
|
||||
else: # if brush.image_tool == 'FILL':
|
||||
col.prop(brush, "gradient_fill_mode")
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_color(row, context, brush, "color", text="")
|
||||
UnifiedPaintPanel.prop_unified_color(row, context, brush, "secondary_color", text="")
|
||||
row.separator()
|
||||
row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="", emboss=False)
|
||||
row.prop(ups, "use_unified_color", text="", icon='WORLD')
|
||||
# Gradient
|
||||
elif brush.color_type == 'GRADIENT':
|
||||
layout.template_color_ramp(brush, "gradient", expand=True)
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
def brush_texpaint_common_options(_panel, _context, layout, brush, _settings, *, projpaint=False):
|
||||
capabilities = brush.image_paint_capabilities
|
||||
col = layout.column()
|
||||
|
||||
col = layout.column()
|
||||
if brush.image_tool == 'DRAW':
|
||||
UnifiedPaintPanel.prop_unified(col, context, brush, "secondary_color", unified_name="use_unified_color", text="Background Color", display_unified_toggle=False)
|
||||
|
||||
if capabilities.has_accumulate:
|
||||
col.prop(brush, "use_accumulate")
|
||||
|
||||
if capabilities.has_space_attenuation:
|
||||
col.prop(brush, "use_space_attenuation")
|
||||
|
||||
if projpaint:
|
||||
col.prop(brush, "use_alpha")
|
||||
else:
|
||||
col.prop(brush, "use_paint_antialiasing")
|
||||
col.prop(brush, "gradient_stroke_mode", text="Gradient Mapping")
|
||||
if brush.gradient_stroke_mode in {'SPACING_REPEAT', 'SPACING_CLAMP'}:
|
||||
col.prop(brush, "grad_spacing")
|
||||
|
||||
|
||||
# Used in both the View3D toolbar and texture properties
|
||||
@@ -281,94 +884,23 @@ def brush_mask_texture_settings(layout, brush):
|
||||
# scale and offset
|
||||
col.prop(mask_tex_slot, "offset")
|
||||
col.prop(mask_tex_slot, "scale")
|
||||
|
||||
# Basic Brush Options
|
||||
#
|
||||
# Share between topbar and brush panel.
|
||||
|
||||
|
||||
def brush_basic_wpaint_settings(layout, context, brush, *, compact=False):
|
||||
capabilities = brush.weight_paint_capabilities
|
||||
|
||||
if capabilities.has_weight:
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_weight(row, context, brush, "weight", slider=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True)
|
||||
row.prop(brush, "use_pressure_size", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength")
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
|
||||
layout.prop(brush, "blend", text="" if compact else "Blend")
|
||||
|
||||
|
||||
def brush_basic_vpaint_settings(layout, context, brush, *, compact=False):
|
||||
capabilities = brush.vertex_paint_capabilities
|
||||
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True)
|
||||
row.prop(brush, "use_pressure_size", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength")
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
|
||||
if capabilities.has_color:
|
||||
layout.prop(brush, "blend", text="" if compact else "Blend")
|
||||
|
||||
|
||||
def brush_basic_texpaint_settings(layout, context, brush, *, compact=False):
|
||||
"""Draw Tool Settings header for Vertex Paint and 2D and 3D Texture Paint modes."""
|
||||
# NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281
|
||||
capabilities = brush.image_paint_capabilities
|
||||
|
||||
if capabilities.has_radius:
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True)
|
||||
row.prop(brush, "use_pressure_size", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
|
||||
UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength")
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
|
||||
if capabilities.has_color:
|
||||
UnifiedPaintPanel.prop_unified_color(layout, context, brush, "color", text="")
|
||||
layout.prop(brush, "blend", text="" if compact else "Blend")
|
||||
|
||||
|
||||
def brush_basic_sculpt_settings(layout, context, brush, *, compact=False):
|
||||
tool_settings = context.tool_settings
|
||||
capabilities = brush.sculpt_capabilities
|
||||
|
||||
row = layout.row(align=True)
|
||||
|
||||
ups = tool_settings.unified_paint_settings
|
||||
if (
|
||||
(ups.use_unified_size and ups.use_locked_size == 'SCENE') or
|
||||
((not ups.use_unified_size) and brush.use_locked_size == 'SCENE')
|
||||
):
|
||||
UnifiedPaintPanel.prop_unified_size(row, context, brush, "unprojected_radius", slider=True, text="Radius")
|
||||
else:
|
||||
UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True)
|
||||
|
||||
row.prop(brush, "use_pressure_size", text="")
|
||||
|
||||
# strength, use_strength_pressure, and use_strength_attenuation
|
||||
row = layout.row(align=True)
|
||||
|
||||
UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength")
|
||||
|
||||
if capabilities.has_strength_pressure:
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
|
||||
# direction
|
||||
if not capabilities.has_direction:
|
||||
layout.row().prop(brush, "direction", expand=True, **({"text": ""} if compact else {}))
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "size", pressure_name="use_pressure_size", slider=True, text="Radius")
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "strength", pressure_name="use_pressure_strength")
|
||||
|
||||
|
||||
def brush_basic_gpencil_paint_settings(layout, context, brush, tool, *, compact=True, is_toolbar=False):
|
||||
def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False):
|
||||
gp_settings = brush.gpencil_settings
|
||||
tool = context.workspace.tools.from_space_view3d_mode(context.mode, create=False)
|
||||
|
||||
# Brush details
|
||||
if brush.gpencil_tool == 'ERASE':
|
||||
@@ -377,6 +909,8 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, tool, *, compact=
|
||||
row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
row.prop(gp_settings, "use_occlude_eraser", text="", icon='XRAY')
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "eraser_mode", expand=True)
|
||||
if gp_settings.eraser_mode == 'SOFT':
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "pen_strength", slider=True)
|
||||
@@ -385,6 +919,11 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, tool, *, compact=
|
||||
row.prop(gp_settings, "eraser_strength_factor")
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "eraser_thickness_factor")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "use_cursor", text="Show Brush")
|
||||
|
||||
# FIXME: tools must use their own UI drawing!
|
||||
elif brush.gpencil_tool == 'FILL':
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "fill_leak", text="Leak Size")
|
||||
@@ -395,23 +934,7 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, tool, *, compact=
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "fill_draw_mode", text="Boundary")
|
||||
row.prop(gp_settings, "show_fill_boundary", text="", icon='GRID')
|
||||
# Fill options
|
||||
if is_toolbar:
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
row = layout.row(align=True)
|
||||
sub = row.row(align=True)
|
||||
sub.popover(
|
||||
panel="TOPBAR_PT_gpencil_fill",
|
||||
text="Fill Options",
|
||||
)
|
||||
else:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "fill_factor", text="Resolution")
|
||||
if gp_settings.fill_draw_mode != 'STROKE':
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes")
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "fill_threshold", text="Threshold")
|
||||
|
||||
else: # brush.gpencil_tool == 'DRAW':
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "size", text="Radius")
|
||||
@@ -427,10 +950,10 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, tool, *, compact=
|
||||
"builtin.line",
|
||||
"builtin.box",
|
||||
"builtin.circle",
|
||||
"builtin.polyline",
|
||||
"builtin.polyline"
|
||||
}:
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
if is_toolbar:
|
||||
if compact:
|
||||
row = layout.row(align=True)
|
||||
row.prop(settings, "use_thickness_curve", text="", icon='CURVE_DATA')
|
||||
sub = row.row(align=True)
|
||||
@@ -491,10 +1014,8 @@ def brush_basic_gpencil_weight_settings(layout, _context, brush, *, compact=Fals
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "strength", slider=True)
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
|
||||
layout.prop(brush, "use_falloff")
|
||||
|
||||
layout.prop(brush, "weight", slider=True)
|
||||
layout.prop(brush, "use_falloff")
|
||||
|
||||
|
||||
classes = (
|
||||
|
||||
@@ -27,12 +27,18 @@ from bpy.types import (
|
||||
from bl_ui.properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
brush_texture_settings,
|
||||
brush_texpaint_common,
|
||||
brush_texpaint_common_color,
|
||||
brush_texpaint_common_gradient,
|
||||
brush_texpaint_common_clone,
|
||||
brush_texpaint_common_options,
|
||||
brush_mask_texture_settings,
|
||||
brush_basic_texpaint_settings,
|
||||
brush_settings,
|
||||
brush_settings_advanced,
|
||||
draw_color_settings,
|
||||
ClonePanel,
|
||||
BrushSelectPanel,
|
||||
TextureMaskPanel,
|
||||
ColorPalettePanel,
|
||||
StrokePanel,
|
||||
SmoothStrokePanel,
|
||||
FalloffPanel,
|
||||
DisplayPanel,
|
||||
)
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
AnnotationDataPanel,
|
||||
@@ -44,7 +50,7 @@ from bl_ui.space_toolsystem_common import (
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
|
||||
|
||||
class ImagePaintPanel(UnifiedPaintPanel):
|
||||
class ImagePaintPanel:
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
|
||||
@@ -59,7 +65,7 @@ class BrushButtonsPanel(UnifiedPaintPanel):
|
||||
return tool_settings.brush
|
||||
|
||||
|
||||
class IMAGE_PT_active_tool(ToolActivePanelHelper, Panel):
|
||||
class IMAGE_PT_active_tool(Panel, ToolActivePanelHelper):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Tool"
|
||||
@@ -181,25 +187,6 @@ class IMAGE_MT_select(Menu):
|
||||
layout.operator("uv.select_overlap")
|
||||
|
||||
|
||||
class IMAGE_MT_brush(Menu):
|
||||
bl_label = "Brush"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
layout.prop(ups, "use_unified_size", text="Unified Size")
|
||||
layout.prop(ups, "use_unified_strength", text="Unified Strength")
|
||||
layout.prop(ups, "use_unified_color", text="Unified Color")
|
||||
layout.separator()
|
||||
|
||||
# Brush tool.
|
||||
layout.prop_menu_enum(brush, "image_tool")
|
||||
|
||||
|
||||
class IMAGE_MT_image(Menu):
|
||||
bl_label = "Image"
|
||||
|
||||
@@ -569,15 +556,16 @@ class IMAGE_HT_tool_header(Header):
|
||||
|
||||
if tool_mode == 'PAINT':
|
||||
if (tool is not None) and tool.has_datablock:
|
||||
layout.popover_group(
|
||||
space_type='IMAGE_EDITOR',
|
||||
region_type='UI',
|
||||
context=".paint_common_2d",
|
||||
category="",
|
||||
)
|
||||
layout.popover("IMAGE_PT_paint_settings_advanced")
|
||||
layout.popover("IMAGE_PT_paint_stroke")
|
||||
layout.popover("IMAGE_PT_paint_curve")
|
||||
layout.popover("IMAGE_PT_tools_brush_display")
|
||||
layout.popover("IMAGE_PT_tools_brush_texture")
|
||||
layout.popover("IMAGE_PT_tools_mask_texture")
|
||||
elif tool_mode == 'UV':
|
||||
if (tool is not None) and tool.has_datablock:
|
||||
layout.popover_group(space_type='IMAGE_EDITOR', region_type='UI', context=".uv_sculpt", category="")
|
||||
layout.popover("IMAGE_PT_uv_sculpt_curve")
|
||||
layout.popover("IMAGE_PT_uv_sculpt_options")
|
||||
|
||||
def draw_mode_settings(self, context):
|
||||
layout = self.layout
|
||||
@@ -601,15 +589,9 @@ class _draw_tool_settings_context_mode:
|
||||
uv_sculpt = tool_settings.uv_sculpt
|
||||
brush = uv_sculpt.brush
|
||||
if brush:
|
||||
from bl_ui.properties_paint_common import UnifiedPaintPanel
|
||||
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True)
|
||||
row.prop(brush, "use_pressure_size", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength", slider=True)
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
# NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "size", pressure_name="use_pressure_size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "strength", pressure_name="use_pressure_strength", slider=True)
|
||||
|
||||
@staticmethod
|
||||
def PAINT(context, layout, tool):
|
||||
@@ -623,13 +605,6 @@ class _draw_tool_settings_context_mode:
|
||||
if brush is None:
|
||||
return
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
brush_basic_texpaint_settings,
|
||||
)
|
||||
capabilities = brush.image_paint_capabilities
|
||||
if capabilities.has_color:
|
||||
UnifiedPaintPanel.prop_unified_color(layout, context, brush, "color", text="")
|
||||
brush_basic_texpaint_settings(layout, context, brush, compact=True)
|
||||
|
||||
|
||||
@@ -771,8 +746,6 @@ class MASK_MT_editor_menus(Menu):
|
||||
layout.menu("IMAGE_MT_select")
|
||||
if show_maskedit:
|
||||
layout.menu("MASK_MT_select")
|
||||
if show_paint:
|
||||
layout.menu("IMAGE_MT_brush")
|
||||
|
||||
if ima and ima.is_dirty:
|
||||
layout.menu("IMAGE_MT_image", text="Image*")
|
||||
@@ -1101,11 +1074,16 @@ class IMAGE_PT_udim_tiles(Panel):
|
||||
col.operator("image.tile_fill")
|
||||
|
||||
|
||||
class IMAGE_PT_paint(Panel, ImagePaintPanel):
|
||||
bl_label = "Brush"
|
||||
class IMAGE_PT_paint_select(Panel, ImagePaintPanel, BrushSelectPanel):
|
||||
bl_label = "Brushes"
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_category = "Tool"
|
||||
|
||||
class IMAGE_PT_paint_settings(Panel, ImagePaintPanel):
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_category = "Tool"
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
@@ -1115,17 +1093,31 @@ class IMAGE_PT_paint(Panel, ImagePaintPanel):
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.template_ID_preview(settings, "brush", new="brush.add", rows=2, cols=6)
|
||||
|
||||
if brush:
|
||||
brush_texpaint_common(self, context, layout, brush, settings)
|
||||
brush_settings(layout.column(), context, brush, popover=self.is_popover)
|
||||
|
||||
|
||||
class IMAGE_PT_paint_settings_advanced(Panel, ImagePaintPanel):
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||
bl_label = "Advanced"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
brush_settings_advanced(layout.column(), context, brush, self.is_popover)
|
||||
|
||||
|
||||
class IMAGE_PT_paint_color(Panel, ImagePaintPanel):
|
||||
bl_category = "Tool"
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_parent_id = "IMAGE_PT_paint"
|
||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||
bl_category = "Tool"
|
||||
bl_label = "Color Picker"
|
||||
|
||||
@classmethod
|
||||
@@ -1141,210 +1133,36 @@ class IMAGE_PT_paint_color(Panel, ImagePaintPanel):
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
layout.prop(brush, "color_type", expand=True)
|
||||
|
||||
if brush.color_type == 'COLOR':
|
||||
brush_texpaint_common_color(self, context, layout, brush, settings)
|
||||
elif brush.color_type == 'GRADIENT':
|
||||
brush_texpaint_common_gradient(self, context, layout, brush, settings)
|
||||
draw_color_settings(context, layout, brush, color_type=True)
|
||||
|
||||
|
||||
class IMAGE_PT_paint_swatches(Panel, ImagePaintPanel):
|
||||
class IMAGE_PT_paint_swatches(Panel, ImagePaintPanel, ColorPalettePanel):
|
||||
bl_category = "Tool"
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_parent_id = "IMAGE_PT_paint"
|
||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||
bl_label = "Color Palette"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
capabilities = brush.image_paint_capabilities
|
||||
|
||||
return capabilities.has_color
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = context.tool_settings.image_paint
|
||||
|
||||
layout.template_ID(settings, "palette", new="palette.new")
|
||||
if settings.palette:
|
||||
layout.template_palette(settings, "palette", color=True)
|
||||
|
||||
|
||||
class IMAGE_PT_paint_clone(Panel, ImagePaintPanel):
|
||||
class IMAGE_PT_paint_clone(Panel, ImagePaintPanel, ClonePanel):
|
||||
bl_category = "Tool"
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_parent_id = "IMAGE_PT_paint"
|
||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||
bl_label = "Clone from Image/UV Map"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
return brush.image_tool == 'CLONE'
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = context.tool_settings.image_paint
|
||||
self.layout.prop(settings, "use_clone_layer", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
layout.active = settings.use_clone_layer
|
||||
|
||||
brush_texpaint_common_clone(self, context, layout, brush, settings)
|
||||
|
||||
|
||||
class IMAGE_PT_paint_options(Panel, ImagePaintPanel):
|
||||
bl_category = "Tool"
|
||||
class IMAGE_PT_tools_brush_display(Panel, BrushButtonsPanel, DisplayPanel):
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_parent_id = "IMAGE_PT_paint"
|
||||
bl_label = "Options"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
capabilities = brush.image_paint_capabilities
|
||||
|
||||
return capabilities.has_color
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
brush_texpaint_common_options(self, context, layout, brush, settings)
|
||||
|
||||
|
||||
class IMAGE_PT_tools_brush_display(BrushButtonsPanel, Panel):
|
||||
bl_label = "Display"
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_category = "Tool"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.tool_settings.image_paint
|
||||
brush = tool_settings.brush
|
||||
tex_slot = brush.texture_slot
|
||||
tex_slot_mask = brush.mask_texture_slot
|
||||
|
||||
col = layout.column()
|
||||
|
||||
row = col.row(align=True)
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.prop(brush, "cursor_overlay_alpha", text="Curve Alpha")
|
||||
sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
|
||||
row.prop(
|
||||
brush, "use_cursor_overlay", text="", toggle=True,
|
||||
icon='HIDE_OFF' if brush.use_cursor_overlay else 'HIDE_ON',
|
||||
)
|
||||
|
||||
col.active = brush.brush_capabilities.has_overlay
|
||||
|
||||
row = col.row(align=True)
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.prop(brush, "texture_overlay_alpha", text="Texture Alpha")
|
||||
sub.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
|
||||
if tex_slot.map_mode != 'STENCIL':
|
||||
row.prop(
|
||||
brush, "use_primary_overlay", text="", toggle=True,
|
||||
icon='HIDE_OFF' if brush.use_primary_overlay else 'HIDE_ON',
|
||||
)
|
||||
|
||||
row = col.row(align=True)
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.prop(brush, "mask_overlay_alpha", text="Mask Texture Alpha")
|
||||
sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
|
||||
if tex_slot_mask.map_mode != 'STENCIL':
|
||||
row.prop(
|
||||
brush, "use_secondary_overlay", text="", toggle=True,
|
||||
icon='HIDE_OFF' if brush.use_secondary_overlay else 'HIDE_ON',
|
||||
)
|
||||
|
||||
|
||||
class IMAGE_PT_tools_brush_display_show_brush(BrushButtonsPanel, Panel):
|
||||
bl_context = ".paint_common_2d" # dot on purpose (access from topbar)
|
||||
bl_label = "Show Brush"
|
||||
bl_parent_id = "IMAGE_PT_tools_brush_display"
|
||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||
bl_category = "Tool"
|
||||
bl_label = "Brush Tip"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = context.tool_settings.image_paint
|
||||
|
||||
self.layout.prop(settings, "show_brush", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.active = settings.show_brush
|
||||
|
||||
if context.sculpt_object and context.tool_settings.sculpt:
|
||||
if brush.sculpt_capabilities.has_secondary_color:
|
||||
col.prop(brush, "cursor_color_add", text="Add")
|
||||
col.prop(brush, "cursor_color_subtract", text="Subtract")
|
||||
else:
|
||||
col.prop(brush, "cursor_color_add", text="Color")
|
||||
else:
|
||||
col.prop(brush, "cursor_color_add", text="Color")
|
||||
|
||||
|
||||
class IMAGE_PT_tools_brush_display_custom_icon(BrushButtonsPanel, Panel):
|
||||
bl_context = ".paint_common_2d" # dot on purpose (access from topbar)
|
||||
bl_label = "Custom Icon"
|
||||
bl_parent_id = "IMAGE_PT_tools_brush_display"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
self.layout.prop(brush, "use_custom_icon", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.active = brush.use_custom_icon
|
||||
col.prop(brush, "icon_filepath", text="")
|
||||
|
||||
|
||||
class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
|
||||
bl_label = "Texture"
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@@ -1360,135 +1178,36 @@ class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
|
||||
brush_texture_settings(col, brush, 0)
|
||||
|
||||
|
||||
class IMAGE_PT_tools_mask_texture(BrushButtonsPanel, Panel):
|
||||
bl_label = "Texture Mask"
|
||||
class IMAGE_PT_tools_mask_texture(Panel, BrushButtonsPanel, TextureMaskPanel):
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
brush = context.tool_settings.image_paint.brush
|
||||
|
||||
col = layout.column()
|
||||
|
||||
col.template_ID_preview(brush, "mask_texture", new="texture.new", rows=3, cols=8)
|
||||
|
||||
brush_mask_texture_settings(col, brush)
|
||||
bl_label = "Texture Mask"
|
||||
|
||||
|
||||
class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
|
||||
class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel, StrokePanel):
|
||||
bl_label = "Stroke"
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
tool_settings = context.tool_settings.image_paint
|
||||
brush = tool_settings.brush
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
col = layout.column()
|
||||
|
||||
col.prop(brush, "stroke_method")
|
||||
|
||||
if brush.use_anchor:
|
||||
col.prop(brush, "use_edge_to_edge", text="Edge To Edge")
|
||||
|
||||
if brush.use_airbrush:
|
||||
col.prop(brush, "rate", text="Rate", slider=True)
|
||||
|
||||
if brush.use_space:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "spacing", text="Spacing")
|
||||
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
|
||||
|
||||
if brush.use_line or brush.use_curve:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "spacing", text="Spacing")
|
||||
|
||||
if brush.use_curve:
|
||||
col.template_ID(brush, "paint_curve", new="paintcurve.new")
|
||||
col.operator("paintcurve.draw")
|
||||
|
||||
row = col.row(align=True)
|
||||
if brush.use_relative_jitter:
|
||||
row.prop(brush, "jitter", slider=True)
|
||||
else:
|
||||
row.prop(brush, "jitter_absolute")
|
||||
row.prop(brush, "use_relative_jitter", icon_only=True)
|
||||
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
|
||||
|
||||
col.prop(tool_settings, "input_samples")
|
||||
|
||||
|
||||
class IMAGE_PT_paint_stroke_smooth_stroke(BrushButtonsPanel, Panel):
|
||||
bl_context = ".paint_common_2d" # dot on purpose (access from topbar)
|
||||
bl_label = "Smooth Stroke"
|
||||
class IMAGE_PT_paint_stroke_smooth_stroke(Panel, BrushButtonsPanel, SmoothStrokePanel):
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_label = "Stabilize Stroke"
|
||||
bl_parent_id = "IMAGE_PT_paint_stroke"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
if brush.brush_capabilities.has_smooth_stroke:
|
||||
return True
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
self.layout.prop(brush, "use_smooth_stroke", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.image_paint
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.active = brush.use_smooth_stroke
|
||||
col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
|
||||
col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
|
||||
|
||||
|
||||
class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
|
||||
class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel, FalloffPanel):
|
||||
bl_label = "Falloff"
|
||||
bl_context = ".paint_common_2d"
|
||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
tool_settings = context.tool_settings.image_paint
|
||||
brush = tool_settings.brush
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "curve_preset", text="")
|
||||
|
||||
if brush.curve_preset == 'CUSTOM':
|
||||
layout.template_curve_mapping(brush, "curve")
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
|
||||
row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
|
||||
row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
|
||||
row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
|
||||
row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
|
||||
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
|
||||
|
||||
|
||||
class IMAGE_PT_tools_imagepaint_symmetry(BrushButtonsPanel, Panel):
|
||||
bl_context = ".imagepaint_2d"
|
||||
@@ -1507,91 +1226,61 @@ class IMAGE_PT_tools_imagepaint_symmetry(BrushButtonsPanel, Panel):
|
||||
row.prop(ipaint, "tile_x", text="X", toggle=True)
|
||||
row.prop(ipaint, "tile_y", text="Y", toggle=True)
|
||||
|
||||
|
||||
class IMAGE_PT_uv_sculpt_brush(Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_context = ".uv_sculpt" # dot on purpose (access from topbar)
|
||||
bl_category = "Tool"
|
||||
bl_label = "Brush"
|
||||
|
||||
class UVSculptPanel(UnifiedPaintPanel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
sima = context.space_data
|
||||
# TODO(campbell): nicer way to check if we're in uv sculpt mode.
|
||||
if sima and sima.show_uvedit:
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
if tool.has_datablock:
|
||||
return True
|
||||
return False
|
||||
return cls.get_brush_mode(context) == 'UV_SCULPT'
|
||||
|
||||
|
||||
class IMAGE_PT_uv_sculpt_brush_select(Panel, BrushSelectPanel, ImagePaintPanel, UVSculptPanel):
|
||||
bl_context = ".uv_sculpt"
|
||||
bl_category = "Tool"
|
||||
bl_label = "Brushes"
|
||||
|
||||
|
||||
class IMAGE_PT_uv_sculpt_brush_settings(Panel, ImagePaintPanel, UVSculptPanel):
|
||||
bl_context = ".uv_sculpt"
|
||||
bl_category = "Tool"
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
def draw(self, context):
|
||||
from bl_ui.properties_paint_common import UnifiedPaintPanel
|
||||
layout = self.layout
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
uvsculpt = tool_settings.uv_sculpt
|
||||
|
||||
layout.template_ID(uvsculpt, "brush")
|
||||
|
||||
brush = uvsculpt.brush
|
||||
|
||||
if not self.is_popover:
|
||||
if brush:
|
||||
col = layout.column()
|
||||
|
||||
row = col.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="")
|
||||
|
||||
row = col.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength", slider=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(tool_settings, "uv_sculpt_lock_borders")
|
||||
col.prop(tool_settings, "uv_sculpt_all_islands")
|
||||
brush_settings(layout.column(), context, brush)
|
||||
|
||||
if brush:
|
||||
if brush.uv_sculpt_tool == 'RELAX':
|
||||
col.prop(tool_settings, "uv_relax_method")
|
||||
|
||||
col.prop(uvsculpt, "show_brush")
|
||||
# Although this settings is stored in the scene, it is only used by a single tool, so it doesn't make sense from a user perspective to move it to the Options panel.
|
||||
layout.prop(tool_settings, "uv_relax_method")
|
||||
|
||||
|
||||
class IMAGE_PT_uv_sculpt_curve(Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
class IMAGE_PT_uv_sculpt_curve(Panel, FalloffPanel, ImagePaintPanel, UVSculptPanel):
|
||||
bl_context = ".uv_sculpt" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "IMAGE_PT_uv_sculpt_brush_settings"
|
||||
bl_category = "Tool"
|
||||
bl_label = "Falloff"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
poll = IMAGE_PT_uv_sculpt_brush.poll
|
||||
class IMAGE_PT_uv_sculpt_options(Panel, ImagePaintPanel, UVSculptPanel):
|
||||
bl_context = ".uv_sculpt" # dot on purpose (access from topbar)
|
||||
bl_category = "Tool"
|
||||
bl_label = "Options"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
uvsculpt = tool_settings.uv_sculpt
|
||||
brush = uvsculpt.brush
|
||||
|
||||
if brush is not None:
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "curve_preset", text="")
|
||||
|
||||
if brush.curve_preset == 'CUSTOM':
|
||||
layout.template_curve_mapping(brush, "curve")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
|
||||
row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
|
||||
row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
|
||||
row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
|
||||
row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
|
||||
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
|
||||
col = layout.column()
|
||||
col.prop(tool_settings, "uv_sculpt_lock_borders")
|
||||
col.prop(tool_settings, "uv_sculpt_all_islands")
|
||||
col.prop(uvsculpt, "show_brush", text="Display Cursor")
|
||||
|
||||
|
||||
class ImageScopesPanel:
|
||||
@@ -1765,7 +1454,6 @@ classes = (
|
||||
IMAGE_MT_view,
|
||||
IMAGE_MT_view_zoom,
|
||||
IMAGE_MT_select,
|
||||
IMAGE_MT_brush,
|
||||
IMAGE_MT_image,
|
||||
IMAGE_MT_image_invert,
|
||||
IMAGE_MT_uvs,
|
||||
@@ -1797,21 +1485,22 @@ classes = (
|
||||
IMAGE_PT_view_display,
|
||||
IMAGE_PT_view_display_uv_edit_overlays,
|
||||
IMAGE_PT_view_display_uv_edit_overlays_stretch,
|
||||
IMAGE_PT_paint,
|
||||
IMAGE_PT_paint_select,
|
||||
IMAGE_PT_paint_settings,
|
||||
IMAGE_PT_paint_color,
|
||||
IMAGE_PT_paint_swatches,
|
||||
IMAGE_PT_paint_settings_advanced,
|
||||
IMAGE_PT_paint_clone,
|
||||
IMAGE_PT_paint_options,
|
||||
IMAGE_PT_tools_brush_texture,
|
||||
IMAGE_PT_tools_mask_texture,
|
||||
IMAGE_PT_paint_stroke,
|
||||
IMAGE_PT_paint_stroke_smooth_stroke,
|
||||
IMAGE_PT_paint_curve,
|
||||
IMAGE_PT_tools_brush_display,
|
||||
IMAGE_PT_tools_brush_display_show_brush,
|
||||
IMAGE_PT_tools_brush_display_custom_icon,
|
||||
IMAGE_PT_tools_imagepaint_symmetry,
|
||||
IMAGE_PT_uv_sculpt_brush,
|
||||
IMAGE_PT_uv_sculpt_brush_select,
|
||||
IMAGE_PT_uv_sculpt_brush_settings,
|
||||
IMAGE_PT_uv_sculpt_options,
|
||||
IMAGE_PT_uv_sculpt_curve,
|
||||
IMAGE_PT_view_histogram,
|
||||
IMAGE_PT_view_waveform,
|
||||
|
||||
@@ -378,7 +378,7 @@ class ToolSelectPanelHelper:
|
||||
|
||||
@staticmethod
|
||||
def _tool_active_from_context(context, space_type, mode=None, create=False):
|
||||
if space_type == 'VIEW_3D':
|
||||
if space_type in ('VIEW_3D', 'PROPERTIES'):
|
||||
if mode is None:
|
||||
mode = context.mode
|
||||
tool = context.workspace.tools.from_space_view3d_mode(mode, create=create)
|
||||
|
||||
@@ -1135,11 +1135,10 @@ class _defs_weight_paint:
|
||||
def draw_settings(context, layout, tool):
|
||||
brush = context.tool_settings.weight_paint.brush
|
||||
if brush is not None:
|
||||
from bl_ui.properties_paint_common import UnifiedPaintPanel
|
||||
UnifiedPaintPanel.prop_unified_weight(layout, context, brush, "weight", slider=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength", slider=True)
|
||||
layout.prop(brush, "weight", slider=True)
|
||||
layout.prop(brush, "strength", slider=True)
|
||||
props = tool.operator_properties("paint.weight_gradient")
|
||||
layout.prop(props, "type")
|
||||
layout.prop(props, "type", expand=True)
|
||||
|
||||
return dict(
|
||||
idname="builtin.gradient",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
import bpy
|
||||
from bpy.types import Header, Menu, Panel
|
||||
|
||||
|
||||
class TOPBAR_HT_upper_bar(Header):
|
||||
bl_space_type = 'TOPBAR'
|
||||
|
||||
@@ -67,7 +68,8 @@ class TOPBAR_HT_upper_bar(Header):
|
||||
layout.template_running_jobs()
|
||||
|
||||
# Active workspace view-layer is retrieved through window, not through workspace.
|
||||
layout.template_ID(window, "scene", new="scene.new", unlink="scene.delete")
|
||||
layout.template_ID(window, "scene", new="scene.new",
|
||||
unlink="scene.delete")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.template_search(
|
||||
@@ -91,9 +93,11 @@ class TOPBAR_PT_tool_settings_extra(Panel):
|
||||
layout = self.layout
|
||||
|
||||
# Get the active tool
|
||||
space_type, mode = ToolSelectPanelHelper._tool_key_from_context(context)
|
||||
space_type, mode = ToolSelectPanelHelper._tool_key_from_context(
|
||||
context)
|
||||
cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
|
||||
item, tool, _ = cls._tool_get_active(context, space_type, mode, with_icon=True)
|
||||
item, tool, _ = cls._tool_get_active(
|
||||
context, space_type, mode, with_icon=True)
|
||||
if item is None:
|
||||
return
|
||||
|
||||
@@ -115,7 +119,8 @@ class TOPBAR_PT_tool_fallback(Panel):
|
||||
ToolSelectPanelHelper.draw_fallback_tool_items(layout, context)
|
||||
if tool_settings.workspace_tool_type == 'FALLBACK':
|
||||
tool = context.tool
|
||||
ToolSelectPanelHelper.draw_active_tool_fallback(context, layout, tool)
|
||||
ToolSelectPanelHelper.draw_active_tool_fallback(
|
||||
context, layout, tool)
|
||||
|
||||
|
||||
class TOPBAR_PT_gpencil_layers(Panel):
|
||||
@@ -174,20 +179,25 @@ class TOPBAR_PT_gpencil_layers(Panel):
|
||||
|
||||
gpl = context.active_gpencil_layer
|
||||
if gpl:
|
||||
sub.menu("GPENCIL_MT_layer_context_menu", icon='DOWNARROW_HLT', text="")
|
||||
sub.menu("GPENCIL_MT_layer_context_menu",
|
||||
icon='DOWNARROW_HLT', text="")
|
||||
|
||||
if len(gpd.layers) > 1:
|
||||
col.separator()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
|
||||
sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
|
||||
sub.operator("gpencil.layer_move",
|
||||
icon='TRIA_UP', text="").type = 'UP'
|
||||
sub.operator("gpencil.layer_move",
|
||||
icon='TRIA_DOWN', text="").type = 'DOWN'
|
||||
|
||||
col.separator()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.layer_isolate", icon='HIDE_OFF', text="").affect_visibility = True
|
||||
sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
sub.operator("gpencil.layer_isolate", icon='HIDE_OFF',
|
||||
text="").affect_visibility = True
|
||||
sub.operator("gpencil.layer_isolate", icon='LOCKED',
|
||||
text="").affect_visibility = False
|
||||
|
||||
|
||||
class TOPBAR_MT_editor_menus(Menu):
|
||||
@@ -229,7 +239,8 @@ class TOPBAR_MT_app(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("preferences.app_template_install", text="Install Application Template...")
|
||||
layout.operator("preferences.app_template_install",
|
||||
text="Install Application Template...")
|
||||
|
||||
|
||||
class TOPBAR_MT_file(Menu):
|
||||
@@ -325,7 +336,8 @@ class TOPBAR_MT_file_new(Menu):
|
||||
|
||||
# Draw application templates.
|
||||
if not use_more:
|
||||
props = layout.operator("wm.read_homefile", text="General", icon=icon)
|
||||
props = layout.operator(
|
||||
"wm.read_homefile", text="General", icon=icon)
|
||||
props.app_template = ""
|
||||
|
||||
for d in paths:
|
||||
@@ -370,7 +382,8 @@ class TOPBAR_MT_file_defaults(Menu):
|
||||
app_template = None
|
||||
|
||||
if app_template:
|
||||
layout.label(text=bpy.path.display_name(app_template, has_ext=False))
|
||||
layout.label(text=bpy.path.display_name(
|
||||
app_template, has_ext=False))
|
||||
|
||||
layout.operator("wm.save_homefile")
|
||||
props = layout.operator("wm.read_factory_settings")
|
||||
@@ -384,12 +397,15 @@ class TOPBAR_MT_app_about(Menu):
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("wm.url_open_preset", text="Release Notes", icon='URL').type = 'RELEASE_NOTES'
|
||||
layout.operator("wm.url_open_preset", text="Release Notes",
|
||||
icon='URL').type = 'RELEASE_NOTES'
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("wm.url_open_preset", text="Blender Website", icon='URL').type = 'BLENDER'
|
||||
layout.operator("wm.url_open_preset", text="Credits", icon='URL').type = 'CREDITS'
|
||||
layout.operator("wm.url_open_preset",
|
||||
text="Blender Website", icon='URL').type = 'BLENDER'
|
||||
layout.operator("wm.url_open_preset", text="Credits",
|
||||
icon='URL').type = 'CREDITS'
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -404,7 +420,8 @@ class TOPBAR_MT_app_support(Menu):
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("wm.url_open_preset", text="Development Fund", icon='FUND').type = 'FUND'
|
||||
layout.operator("wm.url_open_preset",
|
||||
text="Development Fund", icon='FUND').type = 'FUND'
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -417,7 +434,8 @@ class TOPBAR_MT_templates_more(Menu):
|
||||
bl_label = "Templates"
|
||||
|
||||
def draw(self, context):
|
||||
bpy.types.TOPBAR_MT_file_new.draw_ex(self.layout, context, use_more=True)
|
||||
bpy.types.TOPBAR_MT_file_new.draw_ex(
|
||||
self.layout, context, use_more=True)
|
||||
|
||||
|
||||
class TOPBAR_MT_file_import(Menu):
|
||||
@@ -426,7 +444,8 @@ class TOPBAR_MT_file_import(Menu):
|
||||
|
||||
def draw(self, _context):
|
||||
if bpy.app.build_options.collada:
|
||||
self.layout.operator("wm.collada_import", text="Collada (Default) (.dae)")
|
||||
self.layout.operator("wm.collada_import",
|
||||
text="Collada (Default) (.dae)")
|
||||
if bpy.app.build_options.alembic:
|
||||
self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
|
||||
|
||||
@@ -437,11 +456,13 @@ class TOPBAR_MT_file_export(Menu):
|
||||
|
||||
def draw(self, context):
|
||||
if bpy.app.build_options.collada:
|
||||
self.layout.operator("wm.collada_export", text="Collada (Default) (.dae)")
|
||||
self.layout.operator("wm.collada_export",
|
||||
text="Collada (Default) (.dae)")
|
||||
if bpy.app.build_options.alembic:
|
||||
self.layout.operator("wm.alembic_export", text="Alembic (.abc)")
|
||||
if bpy.app.build_options.usd and context.preferences.experimental.use_usd_exporter:
|
||||
self.layout.operator("wm.usd_export", text="Universal Scene Description (.usd, .usdc, .usda)")
|
||||
self.layout.operator(
|
||||
"wm.usd_export", text="Universal Scene Description (.usd, .usdc, .usda)")
|
||||
|
||||
|
||||
class TOPBAR_MT_file_external_data(Menu):
|
||||
@@ -494,8 +515,10 @@ class TOPBAR_MT_render(Menu):
|
||||
|
||||
rd = context.scene.render
|
||||
|
||||
layout.operator("render.render", text="Render Image", icon='RENDER_STILL').use_viewport = True
|
||||
props = layout.operator("render.render", text="Render Animation", icon='RENDER_ANIMATION')
|
||||
layout.operator("render.render", text="Render Image",
|
||||
icon='RENDER_STILL').use_viewport = True
|
||||
props = layout.operator(
|
||||
"render.render", text="Render Animation", icon='RENDER_ANIMATION')
|
||||
props.animation = True
|
||||
props.use_viewport = True
|
||||
|
||||
@@ -537,7 +560,8 @@ class TOPBAR_MT_edit(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("wm.search_menu", text="Operator Search...", icon='VIEWZOOM')
|
||||
layout.operator("wm.search_menu",
|
||||
text="Operator Search...", icon='VIEWZOOM')
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -556,7 +580,8 @@ class TOPBAR_MT_edit(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.userpref_show", text="Preferences...", icon='PREFERENCES')
|
||||
layout.operator("screen.userpref_show",
|
||||
text="Preferences...", icon='PREFERENCES')
|
||||
|
||||
|
||||
class TOPBAR_MT_window(Menu):
|
||||
@@ -576,8 +601,10 @@ class TOPBAR_MT_window(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.workspace_cycle", text="Next Workspace").direction = 'NEXT'
|
||||
layout.operator("screen.workspace_cycle", text="Previous Workspace").direction = 'PREV'
|
||||
layout.operator("screen.workspace_cycle",
|
||||
text="Next Workspace").direction = 'NEXT'
|
||||
layout.operator("screen.workspace_cycle",
|
||||
text="Previous Workspace").direction = 'PREV'
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -604,7 +631,8 @@ class TOPBAR_MT_help(Menu):
|
||||
|
||||
show_developer = context.preferences.view.show_developer_ui
|
||||
|
||||
layout.operator("wm.url_open_preset", text="Manual", icon='HELP').type = 'MANUAL'
|
||||
layout.operator("wm.url_open_preset", text="Manual",
|
||||
icon='HELP').type = 'MANUAL'
|
||||
|
||||
layout.operator(
|
||||
"wm.url_open", text="Tutorials", icon='URL',
|
||||
@@ -637,7 +665,8 @@ class TOPBAR_MT_help(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("wm.url_open_preset", text="Report a Bug", icon='URL').type = 'BUG'
|
||||
layout.operator("wm.url_open_preset",
|
||||
text="Report a Bug", icon='URL').type = 'BUG'
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -666,7 +695,8 @@ class TOPBAR_MT_file_context_menu(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.userpref_show", text="Preferences...", icon='PREFERENCES')
|
||||
layout.operator("screen.userpref_show",
|
||||
text="Preferences...", icon='PREFERENCES')
|
||||
|
||||
|
||||
class TOPBAR_MT_workspace_menu(Menu):
|
||||
@@ -675,21 +705,26 @@ class TOPBAR_MT_workspace_menu(Menu):
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("workspace.duplicate", text="Duplicate", icon='DUPLICATE')
|
||||
layout.operator("workspace.duplicate",
|
||||
text="Duplicate", icon='DUPLICATE')
|
||||
if len(bpy.data.workspaces) > 1:
|
||||
layout.operator("workspace.delete", text="Delete", icon='REMOVE')
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("workspace.reorder_to_front", text="Reorder to Front", icon='TRIA_LEFT_BAR')
|
||||
layout.operator("workspace.reorder_to_back", text="Reorder to Back", icon='TRIA_RIGHT_BAR')
|
||||
layout.operator("workspace.reorder_to_front",
|
||||
text="Reorder to Front", icon='TRIA_LEFT_BAR')
|
||||
layout.operator("workspace.reorder_to_back",
|
||||
text="Reorder to Back", icon='TRIA_RIGHT_BAR')
|
||||
|
||||
layout.separator()
|
||||
|
||||
# For key binding discoverability.
|
||||
props = layout.operator("screen.workspace_cycle", text="Previous Workspace")
|
||||
props = layout.operator("screen.workspace_cycle",
|
||||
text="Previous Workspace")
|
||||
props.direction = 'PREV'
|
||||
props = layout.operator("screen.workspace_cycle", text="Next Workspace")
|
||||
props = layout.operator(
|
||||
"screen.workspace_cycle", text="Next Workspace")
|
||||
props.direction = 'NEXT'
|
||||
|
||||
|
||||
@@ -704,29 +739,8 @@ class TOPBAR_PT_gpencil_primitive(Panel):
|
||||
|
||||
layout = self.layout
|
||||
# Curve
|
||||
layout.template_curve_mapping(settings, "thickness_primitive_curve", brush=True)
|
||||
|
||||
|
||||
# Grease Pencil Fill
|
||||
class TOPBAR_PT_gpencil_fill(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'HEADER'
|
||||
bl_label = "Advanced"
|
||||
|
||||
def draw(self, context):
|
||||
paint = context.tool_settings.gpencil_paint
|
||||
brush = paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
layout = self.layout
|
||||
# Fill
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "fill_factor", text="Resolution")
|
||||
if gp_settings.fill_draw_mode != 'STROKE':
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes")
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "fill_threshold", text="Threshold")
|
||||
layout.template_curve_mapping(
|
||||
settings, "thickness_primitive_curve", brush=True)
|
||||
|
||||
|
||||
# Only a popover
|
||||
@@ -818,7 +832,6 @@ classes = (
|
||||
TOPBAR_PT_tool_settings_extra,
|
||||
TOPBAR_PT_gpencil_layers,
|
||||
TOPBAR_PT_gpencil_primitive,
|
||||
TOPBAR_PT_gpencil_fill,
|
||||
TOPBAR_PT_name,
|
||||
)
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ from bpy.types import (
|
||||
)
|
||||
from bl_ui.properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
brush_basic_texpaint_settings,
|
||||
)
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
AnnotationDataPanel,
|
||||
@@ -67,7 +68,6 @@ class VIEW3D_HT_tool_header(Header):
|
||||
context, layout,
|
||||
tool_key=('VIEW_3D', tool_mode),
|
||||
)
|
||||
|
||||
# Object Mode Options
|
||||
# -------------------
|
||||
|
||||
@@ -79,21 +79,29 @@ class VIEW3D_HT_tool_header(Header):
|
||||
if draw_fn is not None:
|
||||
draw_fn(context, layout, tool)
|
||||
|
||||
popover_kw = {"space_type": 'VIEW_3D', "region_type": 'UI', "category": "Tool"}
|
||||
def draw_3d_brush_settings(layout, tool_mode):
|
||||
layout.popover("VIEW3D_PT_tools_brush_settings_advanced", text="Brush")
|
||||
if tool_mode != 'PAINT_WEIGHT':
|
||||
layout.popover("VIEW3D_PT_tools_brush_texture")
|
||||
if tool_mode == 'PAINT_TEXTURE':
|
||||
layout.popover("VIEW3D_PT_tools_mask_texture")
|
||||
layout.popover("VIEW3D_PT_tools_brush_stroke")
|
||||
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
||||
layout.popover("VIEW3D_PT_tools_brush_display")
|
||||
|
||||
# Note: general mode options should be added to 'draw_mode_settings'.
|
||||
if tool_mode == 'SCULPT':
|
||||
if (tool is not None) and tool.has_datablock:
|
||||
layout.popover_group(context=".paint_common", **popover_kw)
|
||||
draw_3d_brush_settings(layout, tool_mode)
|
||||
elif tool_mode == 'PAINT_VERTEX':
|
||||
if (tool is not None) and tool.has_datablock:
|
||||
layout.popover_group(context=".paint_common", **popover_kw)
|
||||
draw_3d_brush_settings(layout, tool_mode)
|
||||
elif tool_mode == 'PAINT_WEIGHT':
|
||||
if (tool is not None) and tool.has_datablock:
|
||||
layout.popover_group(context=".paint_common", **popover_kw)
|
||||
draw_3d_brush_settings(layout, tool_mode)
|
||||
elif tool_mode == 'PAINT_TEXTURE':
|
||||
if (tool is not None) and tool.has_datablock:
|
||||
layout.popover_group(context=".paint_common", **popover_kw)
|
||||
draw_3d_brush_settings(layout, tool_mode)
|
||||
elif tool_mode == 'EDIT_ARMATURE':
|
||||
pass
|
||||
elif tool_mode == 'EDIT_CURVE':
|
||||
@@ -109,11 +117,24 @@ class VIEW3D_HT_tool_header(Header):
|
||||
pass
|
||||
elif tool_mode == 'PAINT_GPENCIL':
|
||||
if (tool is not None) and tool.has_datablock:
|
||||
layout.popover_group(context=".greasepencil_paint", **popover_kw)
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
if brush.gpencil_tool != 'ERASE':
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_advanced")
|
||||
|
||||
if brush.gpencil_tool != 'FILL':
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_stabilizer")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_random")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_brushcurves")
|
||||
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_paint_appearance")
|
||||
elif tool_mode == 'SCULPT_GPENCIL':
|
||||
layout.popover_group(context=".greasepencil_sculpt", **popover_kw)
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
tool = settings.sculpt_tool
|
||||
if tool in ('SMOOTH', 'RANDOMIZE', 'SMOOTH'):
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_options")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
|
||||
elif tool_mode == 'WEIGHT_GPENCIL':
|
||||
layout.popover_group(context=".greasepencil_weight", **popover_kw)
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_weight_appearance")
|
||||
|
||||
def draw_mode_settings(self, context):
|
||||
layout = self.layout
|
||||
@@ -230,10 +251,26 @@ class _draw_tool_settings_context_mode:
|
||||
if brush is None:
|
||||
return
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_sculpt_settings,
|
||||
)
|
||||
brush_basic_sculpt_settings(layout, context, brush, compact=True)
|
||||
tool_settings = context.tool_settings
|
||||
capabilities = brush.sculpt_capabilities
|
||||
|
||||
ups = tool_settings.unified_paint_settings
|
||||
|
||||
size = "size"
|
||||
size_owner = ups if ups.use_unified_size else brush
|
||||
if size_owner.use_locked_size == 'SCENE':
|
||||
size = "unprojected_radius"
|
||||
|
||||
# NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, size, pressure_name="use_pressure_size", text="Radius", slider=True)
|
||||
|
||||
# strength, use_strength_pressure
|
||||
pressure_name = "use_pressure_strength" if capabilities.has_strength_pressure else None
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "strength", pressure_name=pressure_name, text="Strength")
|
||||
|
||||
# direction
|
||||
if not capabilities.has_direction:
|
||||
layout.row().prop(brush, "direction", expand=True, text="")
|
||||
|
||||
@staticmethod
|
||||
def PAINT_TEXTURE(context, layout, tool):
|
||||
@@ -247,13 +284,6 @@ class _draw_tool_settings_context_mode:
|
||||
if brush is None:
|
||||
return
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
brush_basic_texpaint_settings,
|
||||
)
|
||||
capabilities = brush.image_paint_capabilities
|
||||
if capabilities.has_color:
|
||||
UnifiedPaintPanel.prop_unified_color(layout, context, brush, "color", text="")
|
||||
brush_basic_texpaint_settings(layout, context, brush, compact=True)
|
||||
|
||||
@staticmethod
|
||||
@@ -268,14 +298,7 @@ class _draw_tool_settings_context_mode:
|
||||
if brush is None:
|
||||
return
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
brush_basic_vpaint_settings,
|
||||
)
|
||||
capabilities = brush.vertex_paint_capabilities
|
||||
if capabilities.has_color:
|
||||
UnifiedPaintPanel.prop_unified_color(layout, context, brush, "color", text="")
|
||||
brush_basic_vpaint_settings(layout, context, brush, compact=True)
|
||||
brush_basic_texpaint_settings(layout, context, brush, compact=True)
|
||||
|
||||
@staticmethod
|
||||
def PAINT_WEIGHT(context, layout, tool):
|
||||
@@ -288,8 +311,13 @@ class _draw_tool_settings_context_mode:
|
||||
if brush is None:
|
||||
return
|
||||
|
||||
from bl_ui.properties_paint_common import brush_basic_wpaint_settings
|
||||
brush_basic_wpaint_settings(layout, context, brush, compact=True)
|
||||
# NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281
|
||||
capabilities = brush.weight_paint_capabilities
|
||||
if capabilities.has_weight:
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "weight", slider=True)
|
||||
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "size", pressure_name="use_pressure_size", slider=True, text="Radius")
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "strength", pressure_name="use_pressure_strength")
|
||||
|
||||
@staticmethod
|
||||
def PAINT_GPENCIL(context, layout, tool):
|
||||
@@ -358,7 +386,7 @@ class _draw_tool_settings_context_mode:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_paint_settings,
|
||||
)
|
||||
brush_basic_gpencil_paint_settings(layout, context, brush, tool, compact=True, is_toolbar=True)
|
||||
brush_basic_gpencil_paint_settings(layout, context, brush, compact=True)
|
||||
|
||||
@staticmethod
|
||||
def SCULPT_GPENCIL(context, layout, tool):
|
||||
@@ -467,12 +495,11 @@ class VIEW3D_HT_header(Header):
|
||||
show_snap = True
|
||||
else:
|
||||
|
||||
from bl_ui.properties_paint_common import UnifiedPaintPanel
|
||||
paint_settings = UnifiedPaintPanel.paint_settings(context)
|
||||
|
||||
if paint_settings:
|
||||
brush = paint_settings.brush
|
||||
if brush and brush.stroke_method == 'CURVE':
|
||||
if brush and hasattr(brush, "stroke_method") and brush.stroke_method == 'CURVE':
|
||||
show_snap = True
|
||||
|
||||
if show_snap:
|
||||
@@ -6653,6 +6680,7 @@ class VIEW3D_PT_paint_vertex_context_menu(Panel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
brush = context.tool_settings.vertex_paint.brush
|
||||
capabilities = brush.vertex_paint_capabilities
|
||||
|
||||
@@ -6662,9 +6690,8 @@ class VIEW3D_PT_paint_vertex_context_menu(Panel):
|
||||
UnifiedPaintPanel.prop_unified_color_picker(split, context, brush, "color", value_slider=True)
|
||||
layout.prop(brush, "blend", text="")
|
||||
|
||||
UnifiedPaintPanel.prop_unified_size(layout, context, brush, "size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength")
|
||||
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "size", unified_name="use_unified_size", pressure_name="use_pressure_size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "strength", unified_name="use_unified_strength", pressure_name="use_pressure_strength", slider=True)
|
||||
|
||||
class VIEW3D_PT_paint_texture_context_menu(Panel):
|
||||
# Only for popover, these are dummy values.
|
||||
@@ -6674,6 +6701,7 @@ class VIEW3D_PT_paint_texture_context_menu(Panel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
brush = context.tool_settings.image_paint.brush
|
||||
capabilities = brush.image_paint_capabilities
|
||||
|
||||
@@ -6684,8 +6712,8 @@ class VIEW3D_PT_paint_texture_context_menu(Panel):
|
||||
layout.prop(brush, "blend", text="")
|
||||
|
||||
if capabilities.has_radius:
|
||||
UnifiedPaintPanel.prop_unified_size(layout, context, brush, "size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength")
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "size", unified_name="use_unified_size", pressure_name="use_pressure_size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "strength", unified_name="use_unified_strength", pressure_name="use_pressure_strength", slider=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_paint_weight_context_menu(Panel):
|
||||
@@ -6698,9 +6726,9 @@ class VIEW3D_PT_paint_weight_context_menu(Panel):
|
||||
layout = self.layout
|
||||
|
||||
brush = context.tool_settings.weight_paint.brush
|
||||
UnifiedPaintPanel.prop_unified_weight(layout, context, brush, "weight", slider=True)
|
||||
UnifiedPaintPanel.prop_unified_size(layout, context, brush, "size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength")
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "weight", unified_name="use_unified_weight", slider=True)
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "size", unified_name="use_unified_size", pressure_name="use_pressure_size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "strength", unified_name="use_unified_strength", pressure_name="use_pressure_strength", slider=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_context_menu(Panel):
|
||||
@@ -6715,8 +6743,8 @@ class VIEW3D_PT_sculpt_context_menu(Panel):
|
||||
brush = context.tool_settings.sculpt.brush
|
||||
capabilities = brush.sculpt_capabilities
|
||||
|
||||
UnifiedPaintPanel.prop_unified_size(layout, context, brush, "size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength")
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "size", unified_name="use_unified_size", pressure_name="use_pressure_size", slider=True)
|
||||
UnifiedPaintPanel.prop_unified(layout, context, brush, "strength", unified_name="use_unified_strength", pressure_name="use_pressure_strength", slider=True)
|
||||
|
||||
if capabilities.has_auto_smooth:
|
||||
layout.prop(brush, "auto_smooth_factor", slider=True)
|
||||
|
||||
@@ -19,26 +19,30 @@
|
||||
# <pep8 compliant>
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
GreasePencilStrokeEditPanel,
|
||||
GreasePencilStrokeSculptPanel,
|
||||
GreasePencilSculptOptionsPanel,
|
||||
GreasePencilAppearancePanel,
|
||||
GreasePencilDisplayPanel,
|
||||
)
|
||||
from bl_ui.properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
brush_mask_texture_settings,
|
||||
brush_texpaint_common,
|
||||
brush_texpaint_common_color,
|
||||
brush_texpaint_common_gradient,
|
||||
brush_texpaint_common_clone,
|
||||
brush_texpaint_common_options,
|
||||
BrushSelectPanel,
|
||||
ClonePanel,
|
||||
TextureMaskPanel,
|
||||
ColorPalettePanel,
|
||||
StrokePanel,
|
||||
SmoothStrokePanel,
|
||||
FalloffPanel,
|
||||
DisplayPanel,
|
||||
brush_texture_settings,
|
||||
brush_mask_texture_settings,
|
||||
brush_settings,
|
||||
brush_settings_advanced,
|
||||
draw_color_settings,
|
||||
)
|
||||
from bl_ui.utils import PresetPanel
|
||||
|
||||
|
||||
class VIEW3D_MT_brush_context_menu(Menu):
|
||||
bl_label = "Material Specials"
|
||||
bl_label = "Brush Specials"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -110,9 +114,8 @@ def draw_vpaint_symmetry(layout, vpaint):
|
||||
col.use_property_decorate = False
|
||||
col.prop(vpaint, "radial_symmetry", text="Radial")
|
||||
|
||||
|
||||
# Most of these panels should not be visible in GP edit modes
|
||||
|
||||
|
||||
def is_not_gpencil_edit_mode(context):
|
||||
is_gpmode = (
|
||||
context.active_object and
|
||||
@@ -318,27 +321,41 @@ class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
|
||||
|
||||
# ********** default tools for paint modes ****************
|
||||
|
||||
class TEXTURE_UL_texpaintslots(UIList):
|
||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
# mat = data
|
||||
|
||||
class View3DPaintPanel(UnifiedPaintPanel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
layout.prop(item, "name", text="", emboss=False, icon_value=icon)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="")
|
||||
|
||||
class View3DPaintPanel(View3DPanel, UnifiedPaintPanel):
|
||||
bl_category = "Tool"
|
||||
|
||||
|
||||
class View3DPaintBrushPanel(View3DPaintPanel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
mode = cls.get_brush_mode(context)
|
||||
return mode is not None
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_particlemode(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_label = "Particle tools"
|
||||
bl_label = "Particle Tool"
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
settings = context.tool_settings.particle_edit
|
||||
return (settings and settings.brush and context.particle_edit_object)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
settings = self.paint_settings(context)
|
||||
settings = context.tool_settings.particle_edit
|
||||
brush = settings.brush
|
||||
tool = settings.tool
|
||||
|
||||
@@ -371,19 +388,15 @@ class VIEW3D_PT_tools_particlemode(Panel, View3DPaintPanel):
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_label = "Brush"
|
||||
class VIEW3D_PT_tools_brush_select(Panel, View3DPaintBrushPanel, BrushSelectPanel):
|
||||
bl_context = ".paint_common"
|
||||
bl_label = "Brushes"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
return (settings and
|
||||
settings.brush and
|
||||
(context.sculpt_object or
|
||||
context.vertex_paint_object or
|
||||
context.weight_paint_object or
|
||||
context.image_paint_object))
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_tools_brush_settings(Panel, View3DPaintBrushPanel):
|
||||
bl_context = ".paint_common"
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -394,158 +407,29 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
if not self.is_popover:
|
||||
row = layout.row()
|
||||
row.column().template_ID_preview(settings, "brush", new="brush.add", rows=3, cols=8)
|
||||
row.menu("VIEW3D_MT_brush_context_menu", icon='DOWNARROW_HLT', text="")
|
||||
brush_settings(layout.column(), context, brush, popover=self.is_popover)
|
||||
|
||||
# Sculpt Mode #
|
||||
if context.sculpt_object and brush:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_sculpt_settings,
|
||||
)
|
||||
class VIEW3D_PT_tools_brush_settings_advanced(Panel, View3DPaintBrushPanel):
|
||||
bl_context = ".paint_common"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_label = "Advanced"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
capabilities = brush.sculpt_capabilities
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
col = layout.column()
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
if not self.is_popover:
|
||||
brush_basic_sculpt_settings(col, context, brush)
|
||||
settings = UnifiedPaintPanel.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
# normal_radius_factor
|
||||
col.separator()
|
||||
row = col.row()
|
||||
row.prop(brush, "normal_radius_factor", slider=True)
|
||||
|
||||
if brush.sculpt_tool == 'ELASTIC_DEFORM':
|
||||
col.separator()
|
||||
row = col.row()
|
||||
row.prop(brush, "elastic_deform_type")
|
||||
row = col.row()
|
||||
row.prop(brush, "elastic_deform_volume_preservation", slider=True)
|
||||
elif brush.sculpt_tool == 'POSE':
|
||||
row = col.row()
|
||||
row.prop(brush, "pose_offset")
|
||||
row = col.row()
|
||||
row.prop(brush, "pose_smooth_iterations")
|
||||
elif brush.sculpt_tool == 'SCRAPE':
|
||||
row = col.row()
|
||||
row.prop(brush, "invert_to_scrape_fill", text = "Invert to Fill")
|
||||
elif brush.sculpt_tool == 'FILL':
|
||||
row = col.row()
|
||||
row.prop(brush, "invert_to_scrape_fill", text = "Invert to Scrape")
|
||||
elif brush.sculpt_tool == 'GRAB':
|
||||
col.separator()
|
||||
row = col.row()
|
||||
row.prop(brush, "use_grab_active_vertex")
|
||||
elif brush.sculpt_tool == 'MULTIPLANE_SCRAPE':
|
||||
row = col.row()
|
||||
row.prop(brush, "multiplane_scrape_angle")
|
||||
row = col.row()
|
||||
row.prop(brush, "use_multiplane_scrape_dynamic")
|
||||
row = col.row()
|
||||
row.prop(brush, "show_multiplane_scrape_planes_preview")
|
||||
|
||||
# topology_rake_factor
|
||||
if (
|
||||
capabilities.has_topology_rake and
|
||||
context.sculpt_object.use_dynamic_topology_sculpting
|
||||
):
|
||||
row = col.row()
|
||||
row.prop(brush, "topology_rake_factor", slider=True)
|
||||
|
||||
# auto_smooth_factor and use_inverse_smooth_pressure
|
||||
if capabilities.has_auto_smooth:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "auto_smooth_factor", slider=True)
|
||||
row.prop(brush, "use_inverse_smooth_pressure", toggle=True, text="")
|
||||
|
||||
# normal_weight
|
||||
if capabilities.has_normal_weight:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "normal_weight", slider=True)
|
||||
|
||||
# crease_pinch_factor
|
||||
if capabilities.has_pinch_factor:
|
||||
row = col.row(align=True)
|
||||
if brush.sculpt_tool in {'BLOB', 'SNAKE_HOOK'}:
|
||||
row.prop(brush, "crease_pinch_factor", slider=True, text="Magnify")
|
||||
else:
|
||||
row.prop(brush, "crease_pinch_factor", slider=True, text="Pinch")
|
||||
|
||||
# rake_factor
|
||||
if capabilities.has_rake_factor:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "rake_factor", slider=True)
|
||||
|
||||
if brush.sculpt_tool == 'MASK':
|
||||
col.prop(brush, "mask_tool")
|
||||
|
||||
# plane_offset, use_offset_pressure, use_plane_trim, plane_trim
|
||||
if capabilities.has_plane_offset:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "plane_offset", slider=True)
|
||||
row.prop(brush, "use_offset_pressure", text="")
|
||||
|
||||
col.separator()
|
||||
|
||||
row = col.row()
|
||||
row.prop(brush, "use_plane_trim", text="Plane Trim")
|
||||
row = col.row()
|
||||
row.active = brush.use_plane_trim
|
||||
row.prop(brush, "plane_trim", slider=True, text="Distance")
|
||||
|
||||
# height
|
||||
if capabilities.has_height:
|
||||
row = col.row()
|
||||
row.prop(brush, "height", slider=True, text="Height")
|
||||
|
||||
# use_persistent, set_persistent_base
|
||||
if capabilities.has_persistence:
|
||||
ob = context.sculpt_object
|
||||
do_persistent = True
|
||||
|
||||
# not supported yet for this case
|
||||
for md in ob.modifiers:
|
||||
if md.type == 'MULTIRES':
|
||||
do_persistent = False
|
||||
break
|
||||
|
||||
if do_persistent:
|
||||
col.prop(brush, "use_persistent")
|
||||
col.operator("sculpt.set_persistent_base")
|
||||
|
||||
# Texture Paint Mode #
|
||||
|
||||
elif context.image_paint_object and brush:
|
||||
brush_texpaint_common(self, context, layout, brush, settings, projpaint=True)
|
||||
|
||||
# Weight Paint Mode #
|
||||
elif context.weight_paint_object and brush:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_wpaint_settings,
|
||||
)
|
||||
|
||||
col = layout.column()
|
||||
|
||||
if not self.is_popover:
|
||||
brush_basic_wpaint_settings(col, context, brush)
|
||||
|
||||
# Vertex Paint Mode #
|
||||
elif context.vertex_paint_object and brush:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_vpaint_settings,
|
||||
)
|
||||
|
||||
col = layout.column()
|
||||
|
||||
if not self.is_popover:
|
||||
brush_basic_vpaint_settings(col, context, brush)
|
||||
brush_settings_advanced(layout.column(), context, brush, self.is_popover)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_color(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_label = "Color Picker"
|
||||
|
||||
@classmethod
|
||||
@@ -565,138 +449,22 @@ class VIEW3D_PT_tools_brush_color(Panel, View3DPaintPanel):
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
if context.vertex_paint_object:
|
||||
brush_texpaint_common_color(self, context, layout, brush, settings, projpaint=True)
|
||||
|
||||
else:
|
||||
layout.prop(brush, "color_type", expand=True)
|
||||
|
||||
if brush.color_type == 'COLOR':
|
||||
brush_texpaint_common_color(self, context, layout, brush, settings, projpaint=True)
|
||||
elif brush.color_type == 'GRADIENT':
|
||||
brush_texpaint_common_gradient(self, context, layout, brush, settings, projpaint=True)
|
||||
draw_color_settings(context, layout, brush, color_type = not context.vertex_paint_object)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_swatches(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush"
|
||||
class VIEW3D_PT_tools_brush_swatches(Panel, View3DPaintPanel, ColorPalettePanel):
|
||||
bl_context = ".paint_common"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_label = "Color Palette"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
brush = settings.brush
|
||||
if context.image_paint_object:
|
||||
capabilities = brush.image_paint_capabilities
|
||||
return capabilities.has_color
|
||||
|
||||
elif context.vertex_paint_object:
|
||||
capabilities = brush.vertex_paint_capabilities
|
||||
return capabilities.has_color
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = self.paint_settings(context)
|
||||
|
||||
layout.template_ID(settings, "palette", new="palette.new")
|
||||
if settings.palette:
|
||||
layout.template_palette(settings, "palette", color=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_clone(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush"
|
||||
class VIEW3D_PT_tools_brush_clone(Panel, View3DPaintPanel, ClonePanel):
|
||||
bl_context = ".paint_common"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_label = "Clone from Paint Slot"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
return brush.image_tool == 'CLONE'
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = self.paint_settings(context)
|
||||
self.layout.prop(settings, "use_clone_layer", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
layout.active = settings.use_clone_layer
|
||||
|
||||
brush_texpaint_common_clone(self, context, layout, brush, settings, projpaint=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_options(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush"
|
||||
bl_label = "Options"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
tool_settings = context.tool_settings
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
capabilities = brush.sculpt_capabilities
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
col = layout.column()
|
||||
|
||||
if context.image_paint_object and brush:
|
||||
brush_texpaint_common_options(self, context, layout, brush, settings, projpaint=True)
|
||||
|
||||
elif context.sculpt_object and brush:
|
||||
col.prop(brush, "use_automasking_topology")
|
||||
if capabilities.has_accumulate:
|
||||
col.prop(brush, "use_accumulate")
|
||||
|
||||
UnifiedPaintPanel.prop_unified_size(col, context, brush, "use_locked_size")
|
||||
|
||||
if capabilities.has_sculpt_plane:
|
||||
col.prop(brush, "sculpt_plane")
|
||||
col.prop(brush, "use_original_normal")
|
||||
col.prop(brush, "use_original_plane")
|
||||
|
||||
col.prop(brush, "use_frontface", text="Front Faces Only")
|
||||
col.prop(brush, "use_projected")
|
||||
|
||||
elif context.weight_paint_object and brush:
|
||||
|
||||
if brush.weight_tool != 'SMEAR':
|
||||
col.prop(brush, "use_accumulate")
|
||||
|
||||
col.prop(brush, "use_frontface", text="Front Faces Only")
|
||||
col.prop(brush, "use_projected")
|
||||
col.prop(tool_settings, "use_auto_normalize", text="Auto Normalize")
|
||||
col.prop(tool_settings, "use_multipaint", text="Multi-Paint")
|
||||
|
||||
elif context.vertex_paint_object and brush:
|
||||
|
||||
if brush.vertex_tool != 'SMEAR':
|
||||
col.prop(brush, "use_accumulate")
|
||||
|
||||
col.prop(brush, "use_alpha")
|
||||
col.prop(brush, "use_frontface", text="Front Faces Only")
|
||||
col.prop(brush, "use_projected")
|
||||
|
||||
|
||||
class TEXTURE_UL_texpaintslots(UIList):
|
||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
# mat = data
|
||||
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
layout.prop(item, "name", text="", emboss=False, icon_value=icon)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="")
|
||||
|
||||
|
||||
class VIEW3D_MT_tools_projectpaint_uvlayer(Menu):
|
||||
bl_label = "Clone Layer"
|
||||
@@ -782,9 +550,8 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
|
||||
layout.separator()
|
||||
layout.operator("image.save_all_modified", text="Save All Images", icon='FILE_TICK')
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
|
||||
|
||||
class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
|
||||
bl_category = "Tool"
|
||||
bl_context = ".imagepaint" # dot on purpose (access from topbar)
|
||||
@@ -836,73 +603,17 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_tools_brush_display(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_label = "Display"
|
||||
class VIEW3D_PT_tools_brush_display(Panel, View3DPaintBrushPanel, DisplayPanel):
|
||||
bl_context = ".paint_common"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_label = "Cursor"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
return (settings and
|
||||
settings.brush and
|
||||
(context.sculpt_object or
|
||||
context.vertex_paint_object or
|
||||
context.weight_paint_object or
|
||||
context.image_paint_object))
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
tex_slot = brush.texture_slot
|
||||
tex_slot_mask = brush.mask_texture_slot
|
||||
|
||||
col = layout.column()
|
||||
|
||||
row = col.row(align=True)
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.prop(brush, "cursor_overlay_alpha", text="Curve Alpha")
|
||||
sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
|
||||
row.prop(
|
||||
brush, "use_cursor_overlay", text="", toggle=True,
|
||||
icon='HIDE_OFF' if brush.use_cursor_overlay else 'HIDE_ON',
|
||||
)
|
||||
|
||||
col.active = brush.brush_capabilities.has_overlay
|
||||
|
||||
if context.image_paint_object or context.sculpt_object or context.vertex_paint_object:
|
||||
row = col.row(align=True)
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.prop(brush, "texture_overlay_alpha", text="Texture Alpha")
|
||||
sub.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
|
||||
if tex_slot.map_mode != 'STENCIL':
|
||||
row.prop(
|
||||
brush, "use_primary_overlay", text="", toggle=True,
|
||||
icon='HIDE_OFF' if brush.use_primary_overlay else 'HIDE_ON',
|
||||
)
|
||||
|
||||
if context.image_paint_object:
|
||||
row = col.row(align=True)
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.prop(brush, "mask_overlay_alpha", text="Mask Texture Alpha")
|
||||
sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
|
||||
if tex_slot_mask.map_mode != 'STENCIL':
|
||||
row.prop(
|
||||
brush, "use_secondary_overlay", text="", toggle=True,
|
||||
icon='HIDE_OFF' if brush.use_secondary_overlay else 'HIDE_ON',
|
||||
)
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_context = ".paint_common"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_label = "Texture"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@@ -926,9 +637,10 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel):
|
||||
class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel, TextureMaskPanel):
|
||||
bl_category = "Tool"
|
||||
bl_context = ".imagepaint" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_label = "Texture Mask"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@@ -950,151 +662,27 @@ class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel):
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
|
||||
class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel, StrokePanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_label = "Stroke"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
return (settings and
|
||||
settings.brush and
|
||||
(context.sculpt_object or
|
||||
context.vertex_paint_object or
|
||||
context.weight_paint_object or
|
||||
context.image_paint_object))
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
col = layout.column()
|
||||
|
||||
col.prop(brush, "stroke_method")
|
||||
|
||||
if brush.use_anchor:
|
||||
col.prop(brush, "use_edge_to_edge", text="Edge To Edge")
|
||||
|
||||
if brush.use_airbrush:
|
||||
col.prop(brush, "rate", text="Rate", slider=True)
|
||||
|
||||
if brush.use_space:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "spacing", text="Spacing")
|
||||
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
|
||||
col.prop(brush, "dash_ratio")
|
||||
col.prop(brush, "dash_samples")
|
||||
|
||||
if brush.use_line or brush.use_curve:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "spacing", text="Spacing")
|
||||
col.prop(brush, "dash_ratio")
|
||||
col.prop(brush, "dash_samples")
|
||||
|
||||
if brush.use_curve:
|
||||
col.template_ID(brush, "paint_curve", new="paintcurve.new")
|
||||
col.operator("paintcurve.draw")
|
||||
|
||||
if context.sculpt_object:
|
||||
|
||||
if brush.sculpt_capabilities.has_space_attenuation:
|
||||
col.prop(brush, "use_space_attenuation")
|
||||
|
||||
col.prop(brush, "use_scene_spacing")
|
||||
|
||||
if brush.sculpt_capabilities.has_jitter:
|
||||
|
||||
row = col.row(align=True)
|
||||
if brush.use_relative_jitter:
|
||||
row.prop(brush, "jitter", slider=True)
|
||||
else:
|
||||
row.prop(brush, "jitter_absolute")
|
||||
row.prop(brush, "use_relative_jitter", icon_only=True)
|
||||
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
|
||||
|
||||
else:
|
||||
|
||||
row = col.row(align=True)
|
||||
if brush.use_relative_jitter:
|
||||
row.prop(brush, "jitter", slider=True)
|
||||
else:
|
||||
row.prop(brush, "jitter_absolute")
|
||||
row.prop(brush, "use_relative_jitter", icon_only=True)
|
||||
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
|
||||
|
||||
col.prop(settings, "input_samples")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_stroke_smooth_stroke(Panel, View3DPaintPanel):
|
||||
class VIEW3D_PT_tools_brush_stroke_smooth_stroke(Panel, View3DPaintPanel, SmoothStrokePanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_label = "Smooth Stroke"
|
||||
bl_label = "Stabilize Stroke"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_stroke"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
brush = settings.brush
|
||||
if brush.brush_capabilities.has_smooth_stroke:
|
||||
return True
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
self.layout.prop(brush, "use_smooth_stroke", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.active = brush.use_smooth_stroke
|
||||
col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
|
||||
col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_tools_brush_falloff(Panel, View3DPaintPanel):
|
||||
class VIEW3D_PT_tools_brush_falloff(Panel, View3DPaintPanel, FalloffPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_label = "Falloff"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
return (settings and settings.brush and settings.brush.curve)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "curve_preset", text="")
|
||||
|
||||
if brush.curve_preset == 'CUSTOM':
|
||||
layout.template_curve_mapping(brush, "curve", brush=True)
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
|
||||
row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
|
||||
row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
|
||||
row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
|
||||
row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
|
||||
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_falloff_frontface(View3DPaintPanel, Panel):
|
||||
bl_context = ".imagepaint" # dot on purpose (access from topbar)
|
||||
@@ -1265,8 +853,6 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
|
||||
col.operator("object.voxel_remesh", text="Remesh")
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
|
||||
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
|
||||
bl_label = "Options"
|
||||
@@ -1293,24 +879,6 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
|
||||
col = flow.column()
|
||||
col.prop(sculpt, "use_deform_only")
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_options_unified(Panel, View3DPaintPanel):
|
||||
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "VIEW3D_PT_sculpt_options"
|
||||
bl_label = "Unified Brush"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.sculpt_object and context.tool_settings.sculpt)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
self.unified_paint_settings(layout, context)
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel):
|
||||
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "VIEW3D_PT_sculpt_options"
|
||||
@@ -1409,64 +977,6 @@ class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel):
|
||||
draw = VIEW3D_PT_sculpt_symmetry.draw
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_display_show_brush(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_label = "Show Brush"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_display"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = self.paint_settings(context)
|
||||
|
||||
self.layout.prop(settings, "show_brush", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.active = settings.show_brush
|
||||
|
||||
if context.sculpt_object and context.tool_settings.sculpt:
|
||||
if brush.sculpt_capabilities.has_secondary_color:
|
||||
col.prop(brush, "cursor_color_add", text="Add")
|
||||
col.prop(brush, "cursor_color_subtract", text="Subtract")
|
||||
else:
|
||||
col.prop(brush, "cursor_color_add", text="Color")
|
||||
else:
|
||||
col.prop(brush, "cursor_color_add", text="Color")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_display_custom_icon(Panel, View3DPaintPanel):
|
||||
bl_context = ".paint_common" # dot on purpose (access from topbar)
|
||||
bl_label = "Custom Icon"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_display"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header(self, context):
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
self.layout.prop(brush, "use_custom_icon", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.active = brush.use_custom_icon
|
||||
col.prop(brush, "icon_filepath", text="")
|
||||
|
||||
# ********** default tools for weight-paint ****************
|
||||
|
||||
|
||||
@@ -1512,6 +1022,10 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
|
||||
wpaint = tool_settings.weight_paint
|
||||
|
||||
col = layout.column()
|
||||
|
||||
col.prop(tool_settings, "use_auto_normalize", text="Auto Normalize")
|
||||
col.prop(tool_settings, "use_multipaint", text="Multi-Paint")
|
||||
|
||||
col.prop(wpaint, "use_group_restrict")
|
||||
|
||||
obj = context.weight_paint_object
|
||||
@@ -1523,19 +1037,6 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
|
||||
row.prop(mesh, "use_mirror_topology")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_weightpaint_options_unified(Panel, View3DPaintPanel):
|
||||
bl_context = ".weightpaint"
|
||||
bl_label = "Unified Brush"
|
||||
bl_parent_id = "VIEW3D_PT_tools_weightpaint_options"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
self.unified_paint_settings(layout, context)
|
||||
|
||||
# ********** default tools for vertex-paint ****************
|
||||
|
||||
|
||||
@@ -1545,16 +1046,16 @@ class VIEW3D_PT_tools_vertexpaint_options(Panel, View3DPaintPanel):
|
||||
bl_label = "Options"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
# This is currently unused, since there aren't any Vertex Paint mode specific options.
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.label(text="Unified Brush")
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
self.unified_paint_settings(layout, context)
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel):
|
||||
@@ -1676,19 +1177,6 @@ class VIEW3D_PT_tools_imagepaint_options(View3DPaintPanel, Panel):
|
||||
col.prop(ipaint, "use_backface_culling", text="Backface Culling")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_imagepaint_options_unified(Panel, View3DPaintPanel):
|
||||
bl_context = ".imagepaint" # dot on purpose (access from topbar)
|
||||
bl_parent_id = "VIEW3D_PT_tools_imagepaint_options"
|
||||
bl_label = "Unified Brush"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
self.unified_paint_settings(layout, context)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_imagepaint_options_cavity(View3DPaintPanel, Panel):
|
||||
bl_context = ".imagepaint" # dot on purpose (access from topbar)
|
||||
bl_label = "Cavity Mask"
|
||||
@@ -1719,13 +1207,14 @@ class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# This is currently unused, since there aren't any Vertex Paint mode specific options.
|
||||
return False
|
||||
return (context.image_paint_object and context.tool_settings.image_paint)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
col = layout.column()
|
||||
self.unified_paint_settings(col, context)
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
|
||||
class VIEW3D_MT_tools_projectpaint_stencil(Menu):
|
||||
@@ -1842,15 +1331,13 @@ class VIEW3D_PT_tools_particlemode_options_display(View3DPanel, Panel):
|
||||
# Grease Pencil drawing brushes
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
|
||||
class GreasePencilPanel:
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Brush"
|
||||
bl_category = "Tool"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
is_3d_view = context.space_data.type == 'VIEW_3D'
|
||||
if is_3d_view:
|
||||
if context.space_data.type in ('VIEW_3D', 'PROPERTIES'):
|
||||
if context.gpencil_data is None:
|
||||
return False
|
||||
|
||||
@@ -1859,6 +1346,10 @@ class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePencilPanel):
|
||||
bl_label = "Brushes"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
@@ -1868,15 +1359,40 @@ class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
|
||||
gpencil_paint = tool_settings.gpencil_paint
|
||||
|
||||
row = layout.row()
|
||||
col = row.column()
|
||||
col.template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
|
||||
row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
|
||||
|
||||
col = row.column()
|
||||
col.operator("gpencil.brush_presets_create", icon='PRESET_NEW', text="")
|
||||
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
brush = tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
|
||||
|
||||
if(brush.use_custom_icon):
|
||||
layout.row().prop(brush, "icon_filepath", text="")
|
||||
else:
|
||||
layout.row().prop(gp_settings, "gp_icon", text="Icon")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_settings(Panel, View3DPanel, GreasePencilPanel):
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
# What is the point of brush presets? Seems to serve the exact same purpose as brushes themselves??
|
||||
def draw_header_preset(self, _context):
|
||||
VIEW3D_PT_gpencil_brush_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.scene.tool_settings
|
||||
gpencil_paint = tool_settings.gpencil_paint
|
||||
|
||||
brush = gpencil_paint.brush
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.brush_presets_create", icon='PRESET_NEW', text="")
|
||||
|
||||
if brush is not None:
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
@@ -1895,63 +1411,68 @@ class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_paint_settings,
|
||||
)
|
||||
tool = context.workspace.tools.from_space_view3d_mode(context.mode, create=False)
|
||||
brush_basic_gpencil_paint_settings(layout, context, brush, tool, compact=True, is_toolbar=False)
|
||||
brush_basic_gpencil_paint_settings(layout, context, brush, compact=False)
|
||||
|
||||
|
||||
# Grease Pencil drawing brushes options
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_option(View3DPanel, Panel):
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Options"
|
||||
bl_label = "Advanced"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings'
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL'}
|
||||
|
||||
def draw_header_preset(self, _context):
|
||||
VIEW3D_PT_gpencil_brush_presets.draw_panel_header(self.layout)
|
||||
return brush is not None and brush.gpencil_tool != 'ERASE'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
tool_settings = context.scene.tool_settings
|
||||
gpencil_paint = tool_settings.gpencil_paint
|
||||
brush = gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
col = layout.column(align=True)
|
||||
if brush is not None:
|
||||
gp_settings = brush.gpencil_settings
|
||||
col = layout.column(align=True)
|
||||
col.prop(gp_settings, "input_samples")
|
||||
col.separator()
|
||||
if brush.gpencil_tool != 'FILL':
|
||||
col.prop(gp_settings, "input_samples")
|
||||
col.separator()
|
||||
|
||||
col.prop(gp_settings, "active_smooth_factor")
|
||||
col.separator()
|
||||
col.prop(gp_settings, "active_smooth_factor")
|
||||
col.separator()
|
||||
|
||||
col.prop(gp_settings, "angle", slider=True)
|
||||
col.prop(gp_settings, "angle_factor", text="Factor", slider=True)
|
||||
col.prop(gp_settings, "angle", slider=True)
|
||||
col.prop(gp_settings, "angle_factor", text="Factor", slider=True)
|
||||
|
||||
ob = context.object
|
||||
if ob and brush.gpencil_settings.use_material_pin is False:
|
||||
ma = ob.active_material
|
||||
elif brush.gpencil_settings.material:
|
||||
ma = brush.gpencil_settings.material
|
||||
else:
|
||||
ob = context.object
|
||||
ma = None
|
||||
if ob and brush.gpencil_settings.use_material_pin is False:
|
||||
ma = ob.active_material
|
||||
elif brush.gpencil_settings.material:
|
||||
ma = brush.gpencil_settings.material
|
||||
|
||||
col.separator()
|
||||
subcol = col.column(align=True)
|
||||
if ma and ma.grease_pencil.mode == 'LINE':
|
||||
subcol.enabled = False
|
||||
subcol.prop(gp_settings, "gradient_factor", slider=True)
|
||||
subcol.prop(gp_settings, "gradient_shape")
|
||||
col.separator()
|
||||
subcol = col.column(align=True)
|
||||
if ma and ma.grease_pencil.mode == 'LINE':
|
||||
subcol.enabled = False
|
||||
subcol.prop(gp_settings, "gradient_factor", slider=True)
|
||||
subcol.prop(gp_settings, "gradient_shape")
|
||||
|
||||
elif brush.gpencil_tool == 'FILL':
|
||||
col.prop(gp_settings, "fill_factor", text="Resolution")
|
||||
if gp_settings.fill_draw_mode != 'STROKE':
|
||||
col.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes")
|
||||
col.prop(gp_settings, "fill_threshold", text="Threshold")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(View3DPanel, Panel):
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
|
||||
bl_label = "Stabilize"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings'
|
||||
bl_label = "Stabilize Stroke"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@@ -1961,6 +1482,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(View3DPanel, Panel):
|
||||
return brush is not None and brush.gpencil_tool == 'DRAW'
|
||||
|
||||
def draw_header(self, context):
|
||||
if self.is_popover: return
|
||||
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
self.layout.prop(gp_settings, "use_settings_stabilizer", text="")
|
||||
@@ -1972,24 +1495,34 @@ class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(View3DPanel, Panel):
|
||||
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
layout.active = gp_settings.use_settings_stabilizer
|
||||
|
||||
layout.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
|
||||
layout.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
|
||||
if self.is_popover:
|
||||
row = layout.row()
|
||||
row.prop(gp_settings, "use_settings_stabilizer", text="")
|
||||
row.label(text=self.bl_label)
|
||||
|
||||
col = layout.column()
|
||||
col.active = gp_settings.use_settings_stabilizer
|
||||
|
||||
col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
|
||||
col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_settings(View3DPanel, Panel):
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_post_processing(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings'
|
||||
bl_label = "Post-Processing"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
return brush is not None and brush.gpencil_tool != 'ERASE'
|
||||
return brush is not None and brush.gpencil_tool not in ('ERASE', 'FILL')
|
||||
|
||||
def draw_header(self, context):
|
||||
if self.is_popover: return
|
||||
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
self.layout.prop(gp_settings, "use_settings_postprocess", text="")
|
||||
@@ -2001,30 +1534,37 @@ class VIEW3D_PT_tools_grease_pencil_brush_settings(View3DPanel, Panel):
|
||||
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
layout.active = gp_settings.use_settings_postprocess
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(gp_settings, "pen_smooth_factor")
|
||||
col.prop(gp_settings, "pen_smooth_steps")
|
||||
if self.is_popover:
|
||||
row = layout.row()
|
||||
row.prop(gp_settings, "use_settings_postprocess", text="")
|
||||
row.label(text=self.bl_label)
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(gp_settings, "pen_thick_smooth_factor")
|
||||
col.prop(gp_settings, "pen_thick_smooth_steps", text="Iterations")
|
||||
col = layout.column()
|
||||
col.active = gp_settings.use_settings_postprocess
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(gp_settings, "pen_subdivision_steps")
|
||||
col.prop(gp_settings, "random_subdiv", text="Randomness", slider=True)
|
||||
col1 = col.column(align=True)
|
||||
col1.prop(gp_settings, "pen_smooth_factor")
|
||||
col1.prop(gp_settings, "pen_smooth_steps")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(gp_settings, "simplify_factor")
|
||||
col1 = col.column(align=True)
|
||||
col1.prop(gp_settings, "pen_thick_smooth_factor")
|
||||
col1.prop(gp_settings, "pen_thick_smooth_steps", text="Iterations")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(gp_settings, "trim")
|
||||
col1 = col.column(align=True)
|
||||
col1.prop(gp_settings, "pen_subdivision_steps")
|
||||
col1.prop(gp_settings, "random_subdiv", text="Randomness", slider=True)
|
||||
|
||||
col1 = col.column(align=True)
|
||||
col1.prop(gp_settings, "simplify_factor")
|
||||
|
||||
col1 = col.column(align=True)
|
||||
col1.prop(gp_settings, "trim")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings'
|
||||
bl_label = "Randomize"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
@@ -2032,9 +1572,11 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
return brush is not None and brush.gpencil_tool != 'ERASE'
|
||||
return brush is not None and brush.gpencil_tool not in ('ERASE', 'FILL')
|
||||
|
||||
def draw_header(self, context):
|
||||
if self.is_popover: return
|
||||
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
self.layout.prop(gp_settings, "use_settings_random", text="")
|
||||
@@ -2046,13 +1588,20 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
|
||||
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
layout.active = gp_settings.use_settings_random
|
||||
|
||||
layout.prop(gp_settings, "random_pressure", text="Pressure", slider=True)
|
||||
layout.prop(gp_settings, "random_strength", text="Strength", slider=True)
|
||||
layout.prop(gp_settings, "uv_random", text="UV", slider=True)
|
||||
if self.is_popover:
|
||||
row = layout.row()
|
||||
row.prop(gp_settings, "use_settings_random", text="")
|
||||
row.label(text=self.bl_label)
|
||||
|
||||
row = layout.row(align=True)
|
||||
col = layout.column()
|
||||
col.active = gp_settings.use_settings_random
|
||||
|
||||
col.prop(gp_settings, "random_pressure", text="Pressure", slider=True)
|
||||
col.prop(gp_settings, "random_strength", text="Strength", slider=True)
|
||||
col.prop(gp_settings, "uv_random", text="UV", slider=True)
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(gp_settings, "pen_jitter", slider=True)
|
||||
row.prop(gp_settings, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
|
||||
@@ -2060,6 +1609,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
|
||||
# Grease Pencil drawingcurves
|
||||
class VIEW3D_PT_tools_grease_pencil_brushcurves(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings'
|
||||
bl_label = "Curves"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
@@ -2124,12 +1674,6 @@ class VIEW3D_PT_tools_grease_pencil_brushcurves_jitter(View3DPanel, Panel):
|
||||
use_negative_slope=True)
|
||||
|
||||
|
||||
# Grease Pencil stroke editing tools
|
||||
class VIEW3D_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_category = "Tool"
|
||||
|
||||
|
||||
# Grease Pencil stroke interpolation tools
|
||||
class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
@@ -2178,18 +1722,47 @@ class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
|
||||
|
||||
|
||||
# Grease Pencil stroke sculpting tools
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, View3DPanel, Panel):
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_select(Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_category = "Tools"
|
||||
bl_label = "Brush"
|
||||
bl_label = "Brushes"
|
||||
bl_category = "Tool"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
|
||||
layout.template_icon_view(settings, "sculpt_tool", show_labels=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_category = "Tool"
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
|
||||
if not self.is_popover:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_sculpt_settings,
|
||||
)
|
||||
brush_basic_gpencil_sculpt_settings(layout, context, brush)
|
||||
|
||||
# Grease Pencil weight painting tools
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_paint(View3DPanel, Panel):
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_paint_select(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_weight"
|
||||
bl_category = "Tools"
|
||||
bl_label = "Brush"
|
||||
bl_label = "Brushes"
|
||||
bl_category = "Tool"
|
||||
|
||||
def draw(self, context):
|
||||
@@ -2202,42 +1775,58 @@ class VIEW3D_PT_tools_grease_pencil_weight_paint(View3DPanel, Panel):
|
||||
|
||||
layout.template_icon_view(settings, "weight_tool", show_labels=True)
|
||||
|
||||
col = layout.column()
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_weight"
|
||||
bl_category = "Tool"
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
|
||||
|
||||
if not self.is_popover:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_weight_settings,
|
||||
)
|
||||
brush_basic_gpencil_weight_settings(col, context, brush)
|
||||
brush_basic_gpencil_weight_settings(layout, context, brush)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_options(GreasePencilSculptOptionsPanel, Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_sculpt_settings'
|
||||
bl_category = "Tool"
|
||||
bl_label = "Sculpt Strokes"
|
||||
|
||||
|
||||
# Grease Pencil Brush Appearance (one for each mode)
|
||||
class VIEW3D_PT_tools_grease_pencil_paint_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
|
||||
class VIEW3D_PT_tools_grease_pencil_paint_appearance(GreasePencilDisplayPanel, Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Display"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings'
|
||||
bl_label = "Cursor"
|
||||
bl_category = "Tool"
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_appearance(GreasePencilDisplayPanel, Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_label = "Display"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_sculpt_settings'
|
||||
bl_label = "Cursor"
|
||||
bl_category = "Tool"
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_options(GreasePencilSculptOptionsPanel, View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_label = "Sculpt Strokes"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_sculpt'
|
||||
bl_category = "Tool"
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_appearance(GreasePencilDisplayPanel, Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_weight"
|
||||
bl_label = "Display"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_weight_paint_settings'
|
||||
bl_category = "Tool"
|
||||
bl_label = "Cursor"
|
||||
|
||||
|
||||
class VIEW3D_PT_gpencil_brush_presets(PresetPanel, Panel):
|
||||
class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
|
||||
"""Brush settings"""
|
||||
bl_label = "Brush Presets"
|
||||
preset_subdir = "gpencil_brush"
|
||||
@@ -2255,12 +1844,14 @@ classes = (
|
||||
VIEW3D_PT_tools_curveedit_options_stroke,
|
||||
VIEW3D_PT_tools_armatureedit_options,
|
||||
VIEW3D_PT_tools_posemode_options,
|
||||
|
||||
VIEW3D_PT_slots_projectpaint,
|
||||
VIEW3D_PT_tools_brush,
|
||||
VIEW3D_PT_tools_brush_select,
|
||||
VIEW3D_PT_tools_brush_settings,
|
||||
VIEW3D_PT_tools_brush_color,
|
||||
VIEW3D_PT_tools_brush_swatches,
|
||||
VIEW3D_PT_tools_brush_settings_advanced,
|
||||
VIEW3D_PT_tools_brush_clone,
|
||||
VIEW3D_PT_tools_brush_options,
|
||||
TEXTURE_UL_texpaintslots,
|
||||
VIEW3D_MT_tools_projectpaint_uvlayer,
|
||||
VIEW3D_PT_stencil_projectpaint,
|
||||
@@ -2272,49 +1863,52 @@ classes = (
|
||||
VIEW3D_PT_tools_brush_falloff_frontface,
|
||||
VIEW3D_PT_tools_brush_falloff_normal,
|
||||
VIEW3D_PT_tools_brush_display,
|
||||
VIEW3D_PT_tools_brush_display_show_brush,
|
||||
VIEW3D_PT_tools_brush_display_custom_icon,
|
||||
|
||||
VIEW3D_PT_sculpt_dyntopo,
|
||||
VIEW3D_PT_sculpt_dyntopo_remesh,
|
||||
VIEW3D_PT_sculpt_voxel_remesh,
|
||||
VIEW3D_PT_sculpt_symmetry,
|
||||
VIEW3D_PT_sculpt_symmetry_for_topbar,
|
||||
VIEW3D_PT_sculpt_options,
|
||||
VIEW3D_PT_sculpt_options_unified,
|
||||
VIEW3D_PT_sculpt_options_gravity,
|
||||
|
||||
VIEW3D_PT_tools_weightpaint_symmetry,
|
||||
VIEW3D_PT_tools_weightpaint_symmetry_for_topbar,
|
||||
VIEW3D_PT_tools_weightpaint_options,
|
||||
VIEW3D_PT_tools_weightpaint_options_unified,
|
||||
|
||||
VIEW3D_PT_tools_vertexpaint_symmetry,
|
||||
VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar,
|
||||
VIEW3D_PT_tools_vertexpaint_options,
|
||||
|
||||
VIEW3D_PT_tools_imagepaint_symmetry,
|
||||
VIEW3D_PT_tools_imagepaint_options,
|
||||
VIEW3D_PT_tools_imagepaint_options_cavity,
|
||||
VIEW3D_PT_tools_imagepaint_options_unified,
|
||||
VIEW3D_PT_tools_imagepaint_options_external,
|
||||
VIEW3D_MT_tools_projectpaint_stencil,
|
||||
|
||||
VIEW3D_PT_tools_particlemode,
|
||||
VIEW3D_PT_tools_particlemode_options,
|
||||
VIEW3D_PT_tools_particlemode_options_shapecut,
|
||||
VIEW3D_PT_tools_particlemode_options_display,
|
||||
|
||||
VIEW3D_PT_gpencil_brush_presets,
|
||||
VIEW3D_PT_tools_grease_pencil_brush,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_option,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_select,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_settings,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_advanced,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_post_processing,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_stabilizer,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_random,
|
||||
VIEW3D_PT_tools_grease_pencil_brushcurves,
|
||||
VIEW3D_PT_tools_grease_pencil_brushcurves_sensitivity,
|
||||
VIEW3D_PT_tools_grease_pencil_brushcurves_strength,
|
||||
VIEW3D_PT_tools_grease_pencil_brushcurves_jitter,
|
||||
VIEW3D_PT_tools_grease_pencil_sculpt,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_paint,
|
||||
VIEW3D_PT_tools_grease_pencil_paint_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_sculpt_select,
|
||||
VIEW3D_PT_tools_grease_pencil_sculpt_settings,
|
||||
VIEW3D_PT_tools_grease_pencil_sculpt_options,
|
||||
VIEW3D_PT_tools_grease_pencil_sculpt_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_paint_select,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_paint_settings,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_interpolate,
|
||||
)
|
||||
|
||||
@@ -1596,6 +1596,22 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem brush_jitter_unit_items[] = {
|
||||
{BRUSH_ABSOLUTE_JITTER, "VIEW", 0, "View", "Jitterring happens in screen space, in pixels"},
|
||||
{0, "BRUSH", 0, "Brush", "Jitterring happens relative to the brush size"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem falloff_shape_unit_items[] = {
|
||||
{0, "SPHERE", 0, "Sphere", "Apply brush influence in a Sphere, outwards from the center"},
|
||||
{PAINT_FALLOFF_SHAPE_TUBE,
|
||||
"PROJECTED",
|
||||
0,
|
||||
"Projected",
|
||||
"Apply brush influence in a 2D circle, projected from the view"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem brush_curve_preset_items[] = {
|
||||
{BRUSH_CURVE_CUSTOM, "CUSTOM", ICON_RNDCURVE, "Custom", ""},
|
||||
{BRUSH_CURVE_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
|
||||
@@ -1704,6 +1720,19 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "jitter_unit", PROP_ENUM, PROP_NONE); /* as an enum */
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
|
||||
RNA_def_property_enum_items(prop, brush_jitter_unit_items);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Jitter Unit", "Jitter in screen space or relative to brush size");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "falloff_shape", PROP_ENUM, PROP_NONE); /* as an enum */
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "falloff_shape");
|
||||
RNA_def_property_enum_items(prop, falloff_shape_unit_items);
|
||||
RNA_def_property_ui_text(prop, "Falloff Shape", "Use projected or spherical falloff");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
/* number values */
|
||||
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
|
||||
RNA_def_property_int_funcs(prop, NULL, "rna_Brush_set_size", NULL);
|
||||
@@ -1993,13 +2022,6 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
/* flag */
|
||||
/* This is an enum but its unlikely we add other shapes, so expose as a boolean. */
|
||||
prop = RNA_def_property(srna, "use_projected", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "falloff_shape", PAINT_FALLOFF_SHAPE_TUBE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "2D Falloff", "Apply brush influence in 2D circle instead of a sphere");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_airbrush", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH);
|
||||
RNA_def_property_ui_text(
|
||||
@@ -2045,7 +2067,7 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
|
||||
prop = RNA_def_property(srna, "use_paint_antialiasing", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "sampling_flag", BRUSH_PAINT_ANTIALIASING);
|
||||
RNA_def_property_ui_text(prop, "Antialasing", "Smooths the edges of the strokes");
|
||||
RNA_def_property_ui_text(prop, "Anti-Aliasing", "Smooths the edges of the strokes");
|
||||
|
||||
prop = RNA_def_property(srna, "use_multiplane_scrape_dynamic", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_MULTIPLANE_SCRAPE_DYNAMIC);
|
||||
@@ -2117,13 +2139,6 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
prop, "Inverse Smooth Pressure", "Lighter pressure causes more smoothing to be applied");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_relative_jitter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BRUSH_ABSOLUTE_JITTER);
|
||||
RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Absolute Jitter", "Jittering happens in screen space, not relative to brush size");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_plane_trim", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_PLANE_TRIM);
|
||||
RNA_def_property_ui_text(prop, "Use Plane Trim", "Enable Plane Trim");
|
||||
|
||||
Reference in New Issue
Block a user