Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Inch <mythologylover75@gmail.com>2019-08-31 07:04:43 +0300
committerRyan Inch <mythologylover75@gmail.com>2019-08-31 07:04:43 +0300
commitc63bb5abce16b85dd0f6888b0114c65092747e7a (patch)
treecf86e4fb884894b37fdf558b5802cbab8d9cddc9 /space_view3d_brush_menus/brush_menu.py
parent9f3bea45726e50b01491596993779e1e05306b99 (diff)
Dynamic Brush Menus: return to release: T68350 T63750 437e41a06681
Diffstat (limited to 'space_view3d_brush_menus/brush_menu.py')
-rw-r--r--space_view3d_brush_menus/brush_menu.py630
1 files changed, 630 insertions, 0 deletions
diff --git a/space_view3d_brush_menus/brush_menu.py b/space_view3d_brush_menus/brush_menu.py
new file mode 100644
index 00000000..28caf747
--- /dev/null
+++ b/space_view3d_brush_menus/brush_menu.py
@@ -0,0 +1,630 @@
+# gpl author: Ryan Inch (Imaginer)
+
+import bpy
+from bpy.types import (
+ Operator,
+ Menu,
+ )
+from bpy.props import BoolProperty
+from . import utils_core
+from . import brushes
+from bl_ui.properties_paint_common import UnifiedPaintPanel
+
+class BrushOptionsMenu(Menu):
+ bl_label = "Brush Options"
+ bl_idname = "VIEW3D_MT_sv3_brush_options"
+
+ @classmethod
+ def poll(self, context):
+ return utils_core.get_mode() in (
+ 'SCULPT', 'VERTEX_PAINT',
+ 'WEIGHT_PAINT', 'TEXTURE_PAINT',
+ 'PARTICLE_EDIT'
+ )
+
+ def draw(self, context):
+ mode = utils_core.get_mode()
+ layout = self.layout
+
+ if mode == 'SCULPT':
+ self.sculpt(mode, layout, context)
+
+ elif mode in ('VERTEX_PAINT', 'WEIGHT_PAINT'):
+ self.vw_paint(mode, layout, context)
+
+ elif mode == 'TEXTURE_PAINT':
+ self.texpaint(mode, layout, context)
+
+ else:
+ self.particle(layout, context)
+
+ def sculpt(self, mode, layout, context):
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ icons = brushes.brush_icon[mode][has_brush.sculpt_tool] if \
+ has_brush else "BRUSH_DATA"
+ layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
+ layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
+ icon=icons)
+
+ layout.row().menu(BrushRadiusMenu.bl_idname)
+
+ if has_brush:
+ # if the active brush is unlinked these menus don't do anything
+ layout.row().menu(BrushStrengthMenu.bl_idname)
+ layout.row().menu(BrushAutosmoothMenu.bl_idname)
+ layout.row().menu(BrushModeMenu.bl_idname)
+ layout.row().menu("VIEW3D_MT_sv3_texture_menu")
+ layout.row().menu("VIEW3D_MT_sv3_stroke_options")
+ layout.row().menu("VIEW3D_MT_sv3_brush_curve_menu")
+
+ layout.row().menu("VIEW3D_MT_sv3_dyntopo")
+ layout.row().menu("VIEW3D_MT_sv3_master_symmetry_menu")
+
+ def vw_paint(self, mode, layout, context):
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ icons = brushes.brush_icon[mode][has_brush.vertex_tool] if \
+ has_brush else "BRUSH_DATA"
+
+ layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
+
+ if mode == 'VERTEX_PAINT':
+ layout.row().operator(ColorPickerPopup.bl_idname, icon="COLOR")
+ layout.row().separator()
+
+ layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
+ icon=icons)
+
+ if mode == 'VERTEX_PAINT':
+ layout.row().menu(BrushRadiusMenu.bl_idname)
+
+ if has_brush:
+ # if the active brush is unlinked these menus don't do anything
+ layout.row().menu(BrushStrengthMenu.bl_idname)
+ layout.row().menu(BrushModeMenu.bl_idname)
+ layout.row().menu("VIEW3D_MT_sv3_texture_menu")
+ layout.row().menu("VIEW3D_MT_sv3_stroke_options")
+ layout.row().menu("VIEW3D_MT_sv3_brush_curve_menu")
+
+ if mode == 'WEIGHT_PAINT':
+ layout.row().menu(BrushWeightMenu.bl_idname)
+ layout.row().menu(BrushRadiusMenu.bl_idname)
+
+ if has_brush:
+ # if the active brush is unlinked these menus don't do anything
+ layout.row().menu(BrushStrengthMenu.bl_idname)
+ layout.row().menu(BrushModeMenu.bl_idname)
+ layout.row().menu("VIEW3D_MT_sv3_stroke_options")
+ layout.row().menu("VIEW3D_MT_sv3_brush_curve_menu")
+
+ def texpaint(self, mode, layout, context):
+ toolsettings = context.tool_settings.image_paint
+
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ icons = brushes.brush_icon[mode][has_brush.image_tool] if \
+ has_brush else "BRUSH_DATA"
+
+ if context.image_paint_object and not toolsettings.detect_data():
+ if toolsettings.missing_uvs or toolsettings.missing_materials or \
+ toolsettings.missing_texture:
+ layout.row().label(text="Missing Data", icon='ERROR')
+ layout.row().operator_menu_enum("paint.add_texture_paint_slot", \
+ "type", \
+ icon='ADD', \
+ text="Add Texture Paint Slot")
+
+ return
+
+ elif toolsettings.missing_stencil:
+ layout.row().label(text="Missing Data", icon='ERROR')
+ layout.row().label(text="See Mask Properties", icon='FORWARD')
+ layout.row().separator()
+ layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
+ layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
+ icon=icons)
+
+ return
+
+ else:
+ layout.row().label(text="Missing Data", icon="INFO")
+
+ else:
+ layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
+
+ if has_brush and has_brush.image_tool in {'DRAW', 'FILL'} and \
+ has_brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'}:
+ layout.row().operator(ColorPickerPopup.bl_idname, icon="COLOR")
+ layout.row().separator()
+
+ layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
+ icon=icons)
+
+ if has_brush:
+ # if the active brush is unlinked these menus don't do anything
+ if has_brush and has_brush.image_tool in {'MASK'}:
+ layout.row().menu(BrushWeightMenu.bl_idname, text="Mask Value")
+
+ if has_brush and has_brush.image_tool not in {'FILL'}:
+ layout.row().menu(BrushRadiusMenu.bl_idname)
+
+ layout.row().menu(BrushStrengthMenu.bl_idname)
+
+ if has_brush and has_brush.image_tool in {'DRAW'}:
+ layout.row().menu(BrushModeMenu.bl_idname)
+
+ layout.row().menu("VIEW3D_MT_sv3_texture_menu")
+ layout.row().menu("VIEW3D_MT_sv3_stroke_options")
+ layout.row().menu("VIEW3D_MT_sv3_brush_curve_menu")
+
+ layout.row().menu("VIEW3D_MT_sv3_master_symmetry_menu")
+
+ def particle(self, layout, context):
+ particle_edit = context.tool_settings.particle_edit
+
+ layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
+
+ layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
+ icon="BRUSH_DATA")
+ layout.row().menu(BrushRadiusMenu.bl_idname)
+
+ if particle_edit.tool != 'ADD':
+ layout.row().menu(BrushStrengthMenu.bl_idname)
+ else:
+ layout.row().menu(ParticleCountMenu.bl_idname)
+ layout.row().separator()
+ layout.row().prop(particle_edit, "use_default_interpolate", toggle=True)
+
+ layout.row().prop(particle_edit.brush, "steps", slider=True)
+ layout.row().prop(particle_edit, "default_key_count", slider=True)
+
+ if particle_edit.tool == 'LENGTH':
+ layout.row().separator()
+ layout.row().menu(ParticleLengthMenu.bl_idname)
+
+ if particle_edit.tool == 'PUFF':
+ layout.row().separator()
+ layout.row().menu(ParticlePuffMenu.bl_idname)
+ layout.row().prop(particle_edit.brush, "use_puff_volume", toggle=True)
+
+
+class BrushRadiusMenu(Menu):
+ bl_label = "Radius"
+ bl_idname = "VIEW3D_MT_sv3_brush_radius_menu"
+ bl_description = "Change the size of the brushes"
+
+ def init(self):
+ if utils_core.get_mode() == 'PARTICLE_EDIT':
+ settings = (("100", 100),
+ ("70", 70),
+ ("50", 50),
+ ("30", 30),
+ ("20", 20),
+ ("10", 10))
+
+ datapath = "tool_settings.particle_edit.brush.size"
+ proppath = bpy.context.tool_settings.particle_edit.brush
+
+ else:
+ settings = (("200", 200),
+ ("150", 150),
+ ("100", 100),
+ ("50", 50),
+ ("35", 35),
+ ("10", 10))
+
+ datapath = "tool_settings.unified_paint_settings.size"
+ proppath = bpy.context.tool_settings.unified_paint_settings
+
+ return settings, datapath, proppath
+
+ def draw(self, context):
+ settings, datapath, proppath = self.init()
+ layout = self.layout
+
+ # add the top slider
+ layout.row().prop(proppath, "size", slider=True)
+ layout.row().separator()
+
+ # add the rest of the menu items
+ for i in range(len(settings)):
+ utils_core.menuprop(
+ layout.row(), settings[i][0], settings[i][1],
+ datapath, icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+
+
+class BrushStrengthMenu(Menu):
+ bl_label = "Strength"
+ bl_idname = "VIEW3D_MT_sv3_brush_strength_menu"
+
+ def init(self):
+ mode = utils_core.get_mode()
+ settings = (("1.0", 1.0),
+ ("0.7", 0.7),
+ ("0.5", 0.5),
+ ("0.3", 0.3),
+ ("0.2", 0.2),
+ ("0.1", 0.1))
+
+ proppath = utils_core.get_brush_link(bpy.context, types="brush")
+
+ if mode == 'SCULPT':
+ datapath = "tool_settings.sculpt.brush.strength"
+
+ elif mode == 'VERTEX_PAINT':
+ datapath = "tool_settings.vertex_paint.brush.strength"
+
+ elif mode == 'WEIGHT_PAINT':
+ datapath = "tool_settings.weight_paint.brush.strength"
+
+ elif mode == 'TEXTURE_PAINT':
+ datapath = "tool_settings.image_paint.brush.strength"
+
+ else:
+ datapath = "tool_settings.particle_edit.brush.strength"
+ proppath = bpy.context.tool_settings.particle_edit.brush
+
+ return settings, datapath, proppath
+
+ def draw(self, context):
+ settings, datapath, proppath = self.init()
+ layout = self.layout
+
+ # add the top slider
+ if proppath:
+ layout.row().prop(proppath, "strength", slider=True)
+ layout.row().separator()
+
+ # add the rest of the menu items
+ for i in range(len(settings)):
+ utils_core.menuprop(
+ layout.row(), settings[i][0], settings[i][1],
+ datapath, icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ layout.row().label(text="No brushes available", icon="INFO")
+
+
+class BrushModeMenu(Menu):
+ bl_label = "Brush Mode"
+ bl_idname = "VIEW3D_MT_sv3_brush_mode_menu"
+
+ def init(self):
+ mode = utils_core.get_mode()
+ has_brush = utils_core.get_brush_link(bpy.context, types="brush")
+
+ if mode == 'SCULPT':
+ enum = has_brush.bl_rna.properties['sculpt_plane'].enum_items if \
+ has_brush else None
+ path = "tool_settings.sculpt.brush.sculpt_plane"
+
+ elif mode == 'VERTEX_PAINT':
+ enum = has_brush.bl_rna.properties['blend'].enum_items if \
+ has_brush else None
+ path = "tool_settings.vertex_paint.brush.blend"
+
+ elif mode == 'WEIGHT_PAINT':
+ enum = has_brush.bl_rna.properties['blend'].enum_items if \
+ has_brush else None
+ path = "tool_settings.weight_paint.brush.blend"
+
+ elif mode == 'TEXTURE_PAINT':
+ enum = has_brush.bl_rna.properties['blend'].enum_items if \
+ has_brush else None
+ path = "tool_settings.image_paint.brush.blend"
+
+ else:
+ enum = None
+ path = ""
+
+ return enum, path
+
+ def draw(self, context):
+ enum, path = self.init()
+ layout = self.layout
+ colum_n = utils_core.addon_settings()
+
+ layout.row().label(text="Brush Mode")
+ layout.row().separator()
+
+ if enum:
+ if utils_core.get_mode() != 'SCULPT':
+ column_flow = layout.column_flow(columns=colum_n)
+
+ # add all the brush modes to the menu
+ for brush in enum:
+ utils_core.menuprop(
+ column_flow.row(), brush.name,
+ brush.identifier, path, icon='RADIOBUT_OFF',
+ disable=True, disable_icon='RADIOBUT_ON'
+ )
+ else:
+ # add all the brush modes to the menu
+ for brush in enum:
+ utils_core.menuprop(
+ layout.row(), brush.name,
+ brush.identifier, path, icon='RADIOBUT_OFF',
+ disable=True, disable_icon='RADIOBUT_ON'
+ )
+ else:
+ layout.row().label(text="No brushes available", icon="INFO")
+
+
+class BrushAutosmoothMenu(Menu):
+ bl_label = "Autosmooth"
+ bl_idname = "VIEW3D_MT_sv3_brush_autosmooth_menu"
+
+ def init(self):
+ settings = (("1.0", 1.0),
+ ("0.7", 0.7),
+ ("0.5", 0.5),
+ ("0.3", 0.3),
+ ("0.2", 0.2),
+ ("0.1", 0.1))
+
+ return settings
+
+ def draw(self, context):
+ settings = self.init()
+ layout = self.layout
+ has_brush = utils_core.get_brush_link(context, types="brush")
+
+ if has_brush:
+ # add the top slider
+ layout.row().prop(has_brush, "auto_smooth_factor", slider=True)
+ layout.row().separator()
+
+ # add the rest of the menu items
+ for i in range(len(settings)):
+ utils_core.menuprop(
+ layout.row(), settings[i][0], settings[i][1],
+ "tool_settings.sculpt.brush.auto_smooth_factor",
+ icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ layout.row().label(text="No Smooth options available", icon="INFO")
+
+
+class BrushWeightMenu(Menu):
+ bl_label = "Weight"
+ bl_idname = "VIEW3D_MT_sv3_brush_weight_menu"
+
+ def init(self):
+ settings = (("1.0", 1.0),
+ ("0.7", 0.7),
+ ("0.5", 0.5),
+ ("0.3", 0.3),
+ ("0.2", 0.2),
+ ("0.1", 0.1))
+
+ if utils_core.get_mode() == 'WEIGHT_PAINT':
+ brush = bpy.context.tool_settings.unified_paint_settings
+ brushstr = "tool_settings.unified_paint_settings.weight"
+ name = "Weight"
+
+ else:
+ brush = bpy.context.tool_settings.image_paint.brush
+ brushstr = "tool_settings.image_paint.brush.weight"
+ name = "Mask Value"
+
+ return settings, brush, brushstr, name
+
+ def draw(self, context):
+ settings, brush, brushstr, name = self.init()
+ layout = self.layout
+
+ if brush:
+ # add the top slider
+ layout.row().prop(brush, "weight", text=name, slider=True)
+ layout.row().separator()
+
+ # add the rest of the menu items
+ for i in range(len(settings)):
+ utils_core.menuprop(
+ layout.row(), settings[i][0], settings[i][1],
+ brushstr,
+ icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ layout.row().label(text="No brush available", icon="INFO")
+
+
+class ParticleCountMenu(Menu):
+ bl_label = "Count"
+ bl_idname = "VIEW3D_MT_sv3_particle_count_menu"
+
+ def init(self):
+ settings = (("50", 50),
+ ("25", 25),
+ ("10", 10),
+ ("5", 5),
+ ("3", 3),
+ ("1", 1))
+
+ return settings
+
+ def draw(self, context):
+ settings = self.init()
+ layout = self.layout
+
+ # add the top slider
+ layout.row().prop(context.tool_settings.particle_edit.brush,
+ "count", slider=True)
+ layout.row().separator()
+
+ # add the rest of the menu items
+ for i in range(len(settings)):
+ utils_core.menuprop(
+ layout.row(), settings[i][0], settings[i][1],
+ "tool_settings.particle_edit.brush.count",
+ icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+
+
+class ParticleLengthMenu(Menu):
+ bl_label = "Length Mode"
+ bl_idname = "VIEW3D_MT_sv3_particle_length_menu"
+
+ def draw(self, context):
+ layout = self.layout
+ path = "tool_settings.particle_edit.brush.length_mode"
+
+ # add the menu items
+ for item in context.tool_settings.particle_edit.brush. \
+ bl_rna.properties['length_mode'].enum_items:
+ utils_core.menuprop(
+ layout.row(), item.name, item.identifier, path,
+ icon='RADIOBUT_OFF',
+ disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+
+
+class ParticlePuffMenu(Menu):
+ bl_label = "Puff Mode"
+ bl_idname = "VIEW3D_MT_sv3_particle_puff_menu"
+
+ def draw(self, context):
+ layout = self.layout
+ path = "tool_settings.particle_edit.brush.puff_mode"
+
+ # add the menu items
+ for item in context.tool_settings.particle_edit.brush. \
+ bl_rna.properties['puff_mode'].enum_items:
+ utils_core.menuprop(
+ layout.row(), item.name, item.identifier, path,
+ icon='RADIOBUT_OFF',
+ disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+
+
+class FlipColorsAll(Operator):
+ """Switch between Foreground and Background colors"""
+ bl_label = "Flip Colors"
+ bl_idname = "view3d.sv3_flip_colors_all"
+ bl_description = "Switch between Foreground and Background colors"
+
+ is_tex: BoolProperty(
+ default=False,
+ options={'HIDDEN'}
+ )
+
+ def execute(self, context):
+ try:
+ if self.is_tex is False:
+ color = context.tool_settings.vertex_paint.brush.color
+ secondary_color = context.tool_settings.vertex_paint.brush.secondary_color
+
+ orig_prim = color.hsv
+ orig_sec = secondary_color.hsv
+
+ color.hsv = orig_sec
+ secondary_color.hsv = orig_prim
+ else:
+ color = context.tool_settings.image_paint.brush.color
+ secondary_color = context.tool_settings.image_paint.brush.secondary_color
+
+ orig_prim = color.hsv
+ orig_sec = secondary_color.hsv
+
+ color.hsv = orig_sec
+ secondary_color.hsv = orig_prim
+
+ return {'FINISHED'}
+
+ except Exception as e:
+ utils_core.error_handlers(self, "view3d.sv3_flip_colors_all", e,
+ "Flip Colors could not be completed")
+
+ return {'CANCELLED'}
+
+
+class ColorPickerPopup(Operator):
+ """Open Color Picker"""
+ bl_label = "Color"
+ bl_idname = "view3d.sv3_color_picker_popup"
+ bl_description = "Open Color Picker"
+ bl_options = {'REGISTER'}
+
+ @classmethod
+ def poll(self, context):
+ return utils_core.get_mode() in (
+ 'VERTEX_PAINT',
+ 'TEXTURE_PAINT'
+ )
+
+ def check(self, context):
+ return True
+
+ def init(self):
+ if utils_core.get_mode() == 'TEXTURE_PAINT':
+ settings = bpy.context.tool_settings.image_paint
+ brush = getattr(settings, "brush", None)
+ else:
+ settings = bpy.context.tool_settings.vertex_paint
+ brush = settings.brush
+ brush = getattr(settings, "brush", None)
+
+ return settings, brush
+
+ def draw(self, context):
+ layout = self.layout
+ settings, brush = self.init()
+
+
+ if brush:
+ layout.row().template_color_picker(brush, "color", value_slider=True)
+ prim_sec_row = layout.row(align=True)
+ prim_sec_row.prop(brush, "color", text="")
+ prim_sec_row.prop(brush, "secondary_color", text="")
+
+ if utils_core.get_mode() == 'VERTEX_PAINT':
+ prim_sec_row.operator(
+ FlipColorsAll.bl_idname,
+ icon='FILE_REFRESH', text=""
+ ).is_tex = False
+ else:
+ prim_sec_row.operator(
+ FlipColorsAll.bl_idname,
+ icon='FILE_REFRESH', text=""
+ ).is_tex = True
+
+ if settings.palette:
+ layout.column().template_palette(settings, "palette", color=True)
+
+ layout.row().template_ID(settings, "palette", new="palette.new")
+ else:
+ layout.row().label(text="No brushes currently available", icon="INFO")
+
+ return
+
+ def execute(self, context):
+ return context.window_manager.invoke_popup(self, width=180)
+
+
+classes = (
+ BrushOptionsMenu,
+ BrushRadiusMenu,
+ BrushStrengthMenu,
+ BrushModeMenu,
+ BrushAutosmoothMenu,
+ BrushWeightMenu,
+ ParticleCountMenu,
+ ParticleLengthMenu,
+ ParticlePuffMenu,
+ FlipColorsAll,
+ ColorPickerPopup
+ )
+
+def register():
+ for cls in classes:
+ bpy.utils.register_class(cls)
+
+def unregister():
+ for cls in classes:
+ bpy.utils.unregister_class(cls)