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:
Diffstat (limited to 'space_view3d_brush_menus')
-rw-r--r--space_view3d_brush_menus/Utils/__init__.py0
-rw-r--r--space_view3d_brush_menus/__init__.py169
-rw-r--r--space_view3d_brush_menus/brush_menu.py630
-rw-r--r--space_view3d_brush_menus/brushes.py134
-rw-r--r--space_view3d_brush_menus/curve_menu.py58
-rw-r--r--space_view3d_brush_menus/dyntopo_menu.py77
-rw-r--r--space_view3d_brush_menus/stroke_menu.py128
-rw-r--r--space_view3d_brush_menus/symmetry_menu.py55
-rw-r--r--space_view3d_brush_menus/texture_menu.py344
-rw-r--r--space_view3d_brush_menus/utils_core.py (renamed from space_view3d_brush_menus/Utils/core.py)153
10 files changed, 973 insertions, 775 deletions
diff --git a/space_view3d_brush_menus/Utils/__init__.py b/space_view3d_brush_menus/Utils/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/space_view3d_brush_menus/Utils/__init__.py
+++ /dev/null
diff --git a/space_view3d_brush_menus/__init__.py b/space_view3d_brush_menus/__init__.py
index 6613b82f..a591187c 100644
--- a/space_view3d_brush_menus/__init__.py
+++ b/space_view3d_brush_menus/__init__.py
@@ -17,122 +17,115 @@
# ##### END GPL LICENSE BLOCK #####
# Modified by Meta-Androcto
-
""" Copyright 2011 GPL licence applies"""
bl_info = {
"name": "Sculpt/Paint Brush Menus",
"description": "Fast access to brushes & tools in Sculpt and Paint Modes",
"author": "Ryan Inch (Imaginer)",
- "version": (1, 1, 3),
+ "version": (1, 1, 4),
"blender": (2, 7, 8),
"location": "Alt V in Sculpt/Paint Modes",
- "warning": '', # used for warning icon and text in addons panel
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/3D_interaction/Advanced_UI_Menus",
+ "warning": '',
+ "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
+ "Scripts/3D_interaction/Advanced_UI_Menus",
"category": "3D View"}
-import sys
-import os
-from bl_ui.properties_paint_common import (
- UnifiedPaintPanel,
- brush_texture_settings,
- brush_texpaint_common,
- brush_mask_texture_settings,
- )
-from .Utils.core import *
-from . import brush_menu
-from . import brushes
-from . import curve_menu
-from . import dyntopo_menu
-from . import stroke_menu
-from . import symmetry_menu
-from . import texture_menu
+if "bpy" in locals():
+ import importlib
+ importlib.reload(utils_core)
+ importlib.reload(brush_menu)
+ importlib.reload(brushes)
+ importlib.reload(curve_menu)
+ importlib.reload(dyntopo_menu)
+ importlib.reload(stroke_menu)
+ importlib.reload(symmetry_menu)
+ importlib.reload(texture_menu)
+else:
+ from . import utils_core
+ from . import brush_menu
+ from . import brushes
+ from . import curve_menu
+ from . import dyntopo_menu
+ from . import stroke_menu
+ from . import symmetry_menu
+ from . import texture_menu
+
+
+import bpy
+from bpy.types import AddonPreferences
+from bpy.props import (
+ EnumProperty,
+ IntProperty,
+ )
-# Use compact brushes menus #
-def UseBrushesLists():
- # separate function just for more convience
- useLists = bpy.context.user_preferences.addons[__name__].preferences.use_brushes_lists
- return bool(useLists)
+class VIEW3D_MT_Brushes_Pref(AddonPreferences):
+ bl_idname = __name__
-class VIEW3D_MT_Brush_Selection1(bpy.types.Menu):
- bl_label = "Brush Tool"
+ use_brushes_menu_type = EnumProperty(
+ name="Choose Brushes Selection",
+ description="",
+ items=[('lists', "Use compact Menus",
+ "Use more compact menus instead \n"
+ "of thumbnails for displaying brushes"),
+ ('template', "Template ID Preview",
+ "Use Template ID preview menu (thumbnails) for brushes\n"
+ "(Still part of the menu)"),
+ ('popup', "Pop up menu",
+ "Use a separate pop-up window for accessing brushes")
+ ],
+ default='lists'
+ )
+ column_set = IntProperty(
+ name="Number of Columns",
+ description="Number of columns used for the brushes menu",
+ default=2,
+ min=1,
+ max=10
+ )
def draw(self, context):
layout = self.layout
- settings = UnifiedPaintPanel.paint_settings(context)
-
- # check if brush exists (for instance, in paint mode before adding a slot)
- if hasattr(settings, 'brush'):
- brush = settings.brush
- else:
- brush = None
-
- if not brush:
- return
-
- if not context.particle_edit_object:
- if UseBrushesLists():
- flow = layout.column_flow(columns=3)
-
- for brsh in bpy.data.brushes:
- if (context.sculpt_object and brsh.use_paint_sculpt):
- props = flow.operator("wm.context_set_id", text=brsh.name,
- icon_value=layout.icon(brsh))
- props.data_path = "tool_settings.sculpt.brush"
- props.value = brsh.name
- elif (context.image_paint_object and brsh.use_paint_image):
- props = flow.operator("wm.context_set_id", text=brsh.name,
- icon_value=layout.icon(brsh))
- props.data_path = "tool_settings.image_paint.brush"
- props.value = brsh.name
- elif (context.vertex_paint_object and brsh.use_paint_vertex):
- props = flow.operator("wm.context_set_id", text=brsh.name,
- icon_value=layout.icon(brsh))
- props.data_path = "tool_settings.vertex_paint.brush"
- props.value = brsh.name
- elif (context.weight_paint_object and brsh.use_paint_weight):
- props = flow.operator("wm.context_set_id", text=brsh.name,
- icon_value=layout.icon(brsh))
- props.data_path = "tool_settings.weight_paint.brush"
- props.value = brsh.name
- else:
- layout.template_ID_preview(settings, "brush", new="brush.add", rows=3, cols=8)
-
-
-class VIEW3D_MT_Brushes_Pref(bpy.types.AddonPreferences):
- bl_idname = __name__
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ row.prop(self, "use_brushes_menu_type", expand=True)
+ col.prop(self, "column_set", slider=True)
- use_brushes_lists = bpy.props.BoolProperty(
- name="Use compact menus for brushes",
- default=True,
- description=("Use more compact menus instead \n"
- "of thumbnails for displaying brushes")
- )
- def draw(self, context):
- layout = self.layout
- row = layout.row()
- row.prop(self, "use_brushes_lists")
+# New hotkeys and registration
+
+addon_keymaps = []
+
def register():
# register all blender classes
bpy.utils.register_module(__name__)
-
- # register brush menu
- brush_menu.register()
+
+ # set the add-on name variable to access the preferences
+ utils_core.get_addon_name = __name__
+
+ # register hotkeys
+ wm = bpy.context.window_manager
+ modes = ['Sculpt', 'Vertex Paint', 'Weight Paint', 'Image Paint', 'Particle']
+
+ for mode in modes:
+ km = wm.keyconfigs.addon.keymaps.new(name=mode)
+ kmi = km.keymap_items.new('wm.call_menu', 'V', 'PRESS', alt=True)
+ kmi.properties.name = "VIEW3D_MT_sv3_brush_options"
+ addon_keymaps.append((km, kmi))
+
def unregister():
- # unregister brush menu
- brush_menu.unregister()
-
- # delete all the properties you have created
- del_props()
-
+ for km, kmi in addon_keymaps:
+ km.keymap_items.remove(kmi)
+ addon_keymaps.clear()
+
# unregister all blender classes
bpy.utils.unregister_module(__name__)
+
if __name__ == "__main__":
register()
diff --git a/space_view3d_brush_menus/brush_menu.py b/space_view3d_brush_menus/brush_menu.py
index 91daf19c..6940304e 100644
--- a/space_view3d_brush_menus/brush_menu.py
+++ b/space_view3d_brush_menus/brush_menu.py
@@ -1,156 +1,212 @@
-from bpy.props import *
-from .Utils.core import *
+# gpl author: Ryan Inch (Imaginer)
+
+import bpy
+from bpy.types import (
+ Operator,
+ Menu,
+ )
+from bpy.props import BoolProperty
+from . import utils_core
+from bl_ui.properties_paint_common import UnifiedPaintPanel
+
def get_current_brush_icon(tool):
- if get_mode() == sculpt:
- icons = {"BLOB":'BRUSH_BLOB',
- "CLAY":'BRUSH_CLAY',
- "CLAY_STRIPS":'BRUSH_CLAY_STRIPS',
- "CREASE":'BRUSH_CREASE',
- "DRAW":'BRUSH_SCULPT_DRAW',
- "FILL":'BRUSH_FILL',
- "FLATTEN":'BRUSH_FLATTEN',
- "GRAB":'BRUSH_GRAB',
- "INFLATE":'BRUSH_INFLATE',
- "LAYER":'BRUSH_LAYER',
- "MASK":'BRUSH_MASK',
- "NUDGE":'BRUSH_NUDGE',
- "PINCH":'BRUSH_PINCH',
- "ROTATE":'BRUSH_ROTATE',
- "SCRAPE":'BRUSH_SCRAPE',
- "SIMPLIFY":'BRUSH_SUBTRACT',
- "SMOOTH":'BRUSH_SMOOTH',
- "SNAKE_HOOK":'BRUSH_SNAKE_HOOK',
- "THUMB":'BRUSH_THUMB'}
-
- elif get_mode() == vertex_paint:
- icons = {"ADD":'BRUSH_ADD',
- "BLUR":'BRUSH_BLUR',
- "DARKEN":'BRUSH_DARKEN',
- "LIGHTEN":'BRUSH_LIGHTEN',
- "MIX":'BRUSH_MIX',
- "MUL":'BRUSH_MULTIPLY',
- "SUB":'BRUSH_SUBTRACT'}
-
- elif get_mode() == weight_paint:
- icons = {"ADD":'BRUSH_ADD',
- "BLUR":'BRUSH_BLUR',
- "DARKEN":'BRUSH_DARKEN',
- "LIGHTEN":'BRUSH_LIGHTEN',
- "MIX":'BRUSH_MIX',
- "MUL":'BRUSH_MULTIPLY',
- "SUB":'BRUSH_SUBTRACT'}
-
- elif get_mode() == texture_paint:
- icons = {"CLONE":'BRUSH_CLONE',
- "DRAW":'BRUSH_TEXDRAW',
- "FILL":'BRUSH_TEXFILL',
- "MASK":'BRUSH_TEXMASK',
- "SMEAR":'BRUSH_SMEAR',
- "SOFTEN":'BRUSH_SOFTEN'}
-
+ if utils_core.get_mode() == utils_core.sculpt:
+ icons = {"BLOB": 'BRUSH_BLOB',
+ "CLAY": 'BRUSH_CLAY',
+ "CLAY_STRIPS": 'BRUSH_CLAY_STRIPS',
+ "CREASE": 'BRUSH_CREASE',
+ "DRAW": 'BRUSH_SCULPT_DRAW',
+ "FILL": 'BRUSH_FILL',
+ "FLATTEN": 'BRUSH_FLATTEN',
+ "GRAB": 'BRUSH_GRAB',
+ "INFLATE": 'BRUSH_INFLATE',
+ "LAYER": 'BRUSH_LAYER',
+ "MASK": 'BRUSH_MASK',
+ "NUDGE": 'BRUSH_NUDGE',
+ "PINCH": 'BRUSH_PINCH',
+ "ROTATE": 'BRUSH_ROTATE',
+ "SCRAPE": 'BRUSH_SCRAPE',
+ "SIMPLIFY": 'BRUSH_SUBTRACT',
+ "SMOOTH": 'BRUSH_SMOOTH',
+ "SNAKE_HOOK": 'BRUSH_SNAKE_HOOK',
+ "THUMB": 'BRUSH_THUMB'}
+
+ elif utils_core.get_mode() == utils_core.vertex_paint:
+ icons = {"ADD": 'BRUSH_ADD',
+ "BLUR": 'BRUSH_BLUR',
+ "DARKEN": 'BRUSH_DARKEN',
+ "LIGHTEN": 'BRUSH_LIGHTEN',
+ "MIX": 'BRUSH_MIX',
+ "MUL": 'BRUSH_MULTIPLY',
+ "SUB": 'BRUSH_SUBTRACT'}
+
+ elif utils_core.get_mode() == utils_core.weight_paint:
+ icons = {"ADD": 'BRUSH_ADD',
+ "BLUR": 'BRUSH_BLUR',
+ "DARKEN": 'BRUSH_DARKEN',
+ "LIGHTEN": 'BRUSH_LIGHTEN',
+ "MIX": 'BRUSH_MIX',
+ "MUL": 'BRUSH_MULTIPLY',
+ "SUB": 'BRUSH_SUBTRACT'}
+
+ elif utils_core.get_mode() == utils_core.texture_paint:
+ icons = {"CLONE": 'BRUSH_CLONE',
+ "DRAW": 'BRUSH_TEXDRAW',
+ "FILL": 'BRUSH_TEXFILL',
+ "MASK": 'BRUSH_TEXMASK',
+ "SMEAR": 'BRUSH_SMEAR',
+ "SOFTEN": 'BRUSH_SOFTEN'}
+
icon = icons[tool]
return icon
-class BrushOptionsMenu(bpy.types.Menu):
+
+class BrushOptionsMenu(Menu):
bl_label = "Brush Options"
bl_idname = "VIEW3D_MT_sv3_brush_options"
@classmethod
def poll(self, context):
- if get_mode() in [sculpt, vertex_paint, weight_paint, texture_paint, particle_edit]:
- return True
+ return utils_core.get_mode() in (
+ utils_core.sculpt, utils_core.vertex_paint,
+ utils_core.weight_paint, utils_core.texture_paint,
+ utils_core.particle_edit
+ )
+
+ def draw_brushes(self, menu, h_brush, ico, context):
+ if utils_core.addon_settings(lists=True) == 'popup' or not h_brush:
+ menu.add_item().operator(
+ "view3d.sv3_brush_menu_popup", text="Brush",
+ icon=ico
+ )
else:
- return False
+ menu.add_item().menu(
+ "VIEW3D_MT_sv3_brushes_menu", text="Brush",
+ icon=ico
+ )
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
- if get_mode() == sculpt:
+ if utils_core.get_mode() == utils_core.sculpt:
self.sculpt(menu, context)
- elif get_mode() in [vertex_paint, weight_paint]:
+ elif utils_core.get_mode() in (utils_core.vertex_paint,
+ utils_core.weight_paint):
self.vw_paint(menu, context)
- elif get_mode() == texture_paint:
+ elif utils_core.get_mode() == utils_core.texture_paint:
self.texpaint(menu, context)
else:
self.particle(menu, context)
def sculpt(self, menu, context):
- menu.add_item().menu("VIEW3D_MT_Brush_Selection1", text="Brush", icon=get_current_brush_icon(context.tool_settings.sculpt.brush.sculpt_tool))
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ icons = get_current_brush_icon(has_brush.sculpt_tool) if \
+ has_brush else "BRUSH_DATA"
+
+ self.draw_brushes(menu, has_brush, icons, context)
+
menu.add_item().menu(BrushRadiusMenu.bl_idname)
- menu.add_item().menu(BrushStrengthMenu.bl_idname)
- menu.add_item().menu(BrushAutosmoothMenu.bl_idname)
- menu.add_item().menu(BrushModeMenu.bl_idname)
- menu.add_item().menu("VIEW3D_MT_sv3_texture_menu")
- menu.add_item().menu("VIEW3D_MT_sv3_stroke_options")
- menu.add_item().menu("VIEW3D_MT_sv3_brush_curve_menu")
+
+ if has_brush:
+ # if the active brush is unlinked these menus don't do anything
+ menu.add_item().menu(BrushStrengthMenu.bl_idname)
+ menu.add_item().menu(BrushAutosmoothMenu.bl_idname)
+ menu.add_item().menu(BrushModeMenu.bl_idname)
+ menu.add_item().menu("VIEW3D_MT_sv3_texture_menu")
+ menu.add_item().menu("VIEW3D_MT_sv3_stroke_options")
+ menu.add_item().menu("VIEW3D_MT_sv3_brush_curve_menu")
+
menu.add_item().menu("VIEW3D_MT_sv3_dyntopo")
menu.add_item().menu("VIEW3D_MT_sv3_master_symmetry_menu")
-
+
def vw_paint(self, menu, context):
- if get_mode() == vertex_paint:
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ icons = get_current_brush_icon(has_brush.vertex_tool) if \
+ has_brush else "BRUSH_DATA"
+
+ if utils_core.get_mode() == utils_core.vertex_paint:
menu.add_item().operator(ColorPickerPopup.bl_idname, icon="COLOR")
menu.add_item().separator()
- menu.add_item().menu("VIEW3D_MT_Brush_Selection1", text="Brush", icon=get_current_brush_icon(context.tool_settings.vertex_paint.brush.vertex_tool))
+
+ self.draw_brushes(menu, has_brush, icons, context)
+
+ if utils_core.get_mode() == utils_core.vertex_paint:
menu.add_item().menu(BrushRadiusMenu.bl_idname)
- menu.add_item().menu(BrushStrengthMenu.bl_idname)
- menu.add_item().menu(BrushModeMenu.bl_idname)
- menu.add_item().menu("VIEW3D_MT_sv3_texture_menu")
- menu.add_item().menu("VIEW3D_MT_sv3_stroke_options")
- menu.add_item().menu("VIEW3D_MT_sv3_brush_curve_menu")
- if get_mode() == weight_paint:
- menu.add_item().menu("VIEW3D_MT_Brush_Selection1", text="Brush", icon=get_current_brush_icon(context.tool_settings.vertex_paint.brush.vertex_tool))
+
+ if has_brush:
+ # if the active brush is unlinked these menus don't do anything
+ menu.add_item().menu(BrushStrengthMenu.bl_idname)
+ menu.add_item().menu(BrushModeMenu.bl_idname)
+ menu.add_item().menu("VIEW3D_MT_sv3_texture_menu")
+ menu.add_item().menu("VIEW3D_MT_sv3_stroke_options")
+ menu.add_item().menu("VIEW3D_MT_sv3_brush_curve_menu")
+
+ if utils_core.get_mode() == utils_core.weight_paint:
menu.add_item().menu(BrushWeightMenu.bl_idname)
menu.add_item().menu(BrushRadiusMenu.bl_idname)
- menu.add_item().menu(BrushStrengthMenu.bl_idname)
- menu.add_item().menu(BrushModeMenu.bl_idname)
- menu.add_item().menu("VIEW3D_MT_sv3_stroke_options")
- menu.add_item().menu("VIEW3D_MT_sv3_brush_curve_menu")
+
+ if has_brush:
+ # if the active brush is unlinked these menus don't do anything
+ menu.add_item().menu(BrushStrengthMenu.bl_idname)
+ menu.add_item().menu(BrushModeMenu.bl_idname)
+ menu.add_item().menu("VIEW3D_MT_sv3_stroke_options")
+ menu.add_item().menu("VIEW3D_MT_sv3_brush_curve_menu")
def texpaint(self, menu, context):
toolsettings = context.tool_settings.image_paint
-
+
if context.image_paint_object and not toolsettings.detect_data():
- menu.add_item().label("Missing Data", icon='ERROR')
- menu.add_item().label("See Tool Shelf")
+ menu.add_item().label("Missing Data", icon="INFO")
+ menu.add_item().label("See Tool Shelf", icon="BACK")
else:
- if toolsettings.brush.image_tool in {'DRAW', 'FILL'} and \
- toolsettings.brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'}:
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ if has_brush and has_brush.image_tool in {'DRAW', 'FILL'} and \
+ has_brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'}:
menu.add_item().operator(ColorPickerPopup.bl_idname, icon="COLOR")
menu.add_item().separator()
-
- menu.add_item().menu("VIEW3D_MT_Brush_Selection1", text="Brush", icon=get_current_brush_icon(toolsettings.brush.image_tool))
-
- if toolsettings.brush.image_tool in {'MASK'}:
- menu.add_item().menu(BrushWeightMenu.bl_idname, text="Mask Value")
-
- if toolsettings.brush.image_tool not in {'FILL'}:
- menu.add_item().menu(BrushRadiusMenu.bl_idname)
-
- menu.add_item().menu(BrushStrengthMenu.bl_idname)
-
- if toolsettings.brush.image_tool in {'DRAW'}:
- menu.add_item().menu(BrushModeMenu.bl_idname)
- menu.add_item().menu("VIEW3D_MT_sv3_texture_menu")
- menu.add_item().menu("VIEW3D_MT_sv3_stroke_options")
- menu.add_item().menu("VIEW3D_MT_sv3_brush_curve_menu")
- menu.add_item().menu("VIEW3D_MT_sv3_master_symmetry_menu")
+ icons = get_current_brush_icon(has_brush.image_tool) if \
+ has_brush else "BRUSH_DATA"
+
+ self.draw_brushes(menu, has_brush, icons, context)
+
+ 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'}:
+ menu.add_item().menu(BrushWeightMenu.bl_idname, text="Mask Value")
+
+ if has_brush and has_brush.image_tool not in {'FILL'}:
+ menu.add_item().menu(BrushRadiusMenu.bl_idname)
+
+ menu.add_item().menu(BrushStrengthMenu.bl_idname)
+
+ if has_brush and has_brush.image_tool in {'DRAW'}:
+ menu.add_item().menu(BrushModeMenu.bl_idname)
+
+ menu.add_item().menu("VIEW3D_MT_sv3_texture_menu")
+ menu.add_item().menu("VIEW3D_MT_sv3_stroke_options")
+ menu.add_item().menu("VIEW3D_MT_sv3_brush_curve_menu")
+
+ menu.add_item().menu("VIEW3D_MT_sv3_master_symmetry_menu")
def particle(self, menu, context):
if context.tool_settings.particle_edit.tool == 'NONE':
- menu.add_item().label("No Brush Selected")
- menu.add_item().menu("VIEW3D_MT_sv3_brushes_menu", text="Select Brush")
+ menu.add_item().label("No Brush Selected", icon="INFO")
+ menu.add_item().separator()
+ menu.add_item().menu("VIEW3D_MT_sv3_brushes_menu",
+ text="Select Brush", icon="BRUSH_DATA")
else:
- menu.add_item().menu("VIEW3D_MT_sv3_brushes_menu")
+ menu.add_item().menu("VIEW3D_MT_sv3_brushes_menu",
+ icon="BRUSH_DATA")
menu.add_item().menu(BrushRadiusMenu.bl_idname)
+
if context.tool_settings.particle_edit.tool != 'ADD':
menu.add_item().menu(BrushStrengthMenu.bl_idname)
-
else:
menu.add_item().menu(ParticleCountMenu.bl_idname)
menu.add_item().separator()
@@ -173,19 +229,20 @@ class BrushOptionsMenu(bpy.types.Menu):
"use_puff_volume", toggle=True)
-class BrushRadiusMenu(bpy.types.Menu):
+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, context):
- if get_mode() == particle_edit:
+ if utils_core.get_mode() == utils_core.particle_edit:
settings = [["100", 100],
["70", 70],
["50", 50],
["30", 30],
["20", 20],
["10", 10]]
-
+
datapath = "tool_settings.particle_edit.brush.size"
proppath = context.tool_settings.particle_edit.brush
@@ -196,7 +253,7 @@ class BrushRadiusMenu(bpy.types.Menu):
["50", 50],
["35", 35],
["10", 10]]
-
+
datapath = "tool_settings.unified_paint_settings.size"
proppath = context.tool_settings.unified_paint_settings
@@ -204,7 +261,7 @@ class BrushRadiusMenu(bpy.types.Menu):
def draw(self, context):
settings, datapath, proppath = self.init(context)
- menu = Menu(self)
+ menu = utils_core.Menu(self)
# add the top slider
menu.add_item().prop(proppath, "size", slider=True)
@@ -212,12 +269,14 @@ class BrushRadiusMenu(bpy.types.Menu):
# add the rest of the menu items
for i in range(len(settings)):
- menuprop(menu.add_item(), settings[i][0], settings[i][1],
- datapath, icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON')
+ utils_core.menuprop(
+ menu.add_item(), settings[i][0], settings[i][1],
+ datapath, icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
-class BrushStrengthMenu(bpy.types.Menu):
+class BrushStrengthMenu(Menu):
bl_label = "Strength"
bl_idname = "VIEW3D_MT_sv3_brush_strength_menu"
@@ -229,21 +288,19 @@ class BrushStrengthMenu(bpy.types.Menu):
["0.2", 0.2],
["0.1", 0.1]]
- if get_mode() == sculpt:
+ proppath = utils_core.get_brush_link(context, types="brush")
+
+ if utils_core.get_mode() == utils_core.sculpt:
datapath = "tool_settings.sculpt.brush.strength"
- proppath = context.tool_settings.sculpt.brush
- elif get_mode() == vertex_paint:
+ elif utils_core.get_mode() == utils_core.vertex_paint:
datapath = "tool_settings.vertex_paint.brush.strength"
- proppath = context.tool_settings.vertex_paint.brush
- elif get_mode() == weight_paint:
+ elif utils_core.get_mode() == utils_core.weight_paint:
datapath = "tool_settings.weight_paint.brush.strength"
- proppath = context.tool_settings.weight_paint.brush
- elif get_mode() == texture_paint:
+ elif utils_core.get_mode() == utils_core.texture_paint:
datapath = "tool_settings.image_paint.brush.strength"
- proppath = context.tool_settings.image_paint.brush
else:
datapath = "tool_settings.particle_edit.brush.strength"
@@ -253,63 +310,80 @@ class BrushStrengthMenu(bpy.types.Menu):
def draw(self, context):
settings, datapath, proppath = self.init(context)
- menu = Menu(self)
+ menu = utils_core.Menu(self)
# add the top slider
- menu.add_item().prop(proppath, "strength", slider=True)
- menu.add_item().separator()
+ if proppath:
+ menu.add_item().prop(proppath, "strength", slider=True)
+ menu.add_item().separator()
- # add the rest of the menu items
- for i in range(len(settings)):
- menuprop(menu.add_item(), settings[i][0], settings[i][1],
- datapath, icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON')
+ # add the rest of the menu items
+ for i in range(len(settings)):
+ utils_core.menuprop(
+ menu.add_item(), settings[i][0], settings[i][1],
+ datapath, icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ menu.add_item().label("No brushes available", icon="INFO")
-class BrushModeMenu(bpy.types.Menu):
+class BrushModeMenu(Menu):
bl_label = "Brush Mode"
bl_idname = "VIEW3D_MT_sv3_brush_mode_menu"
def init(self):
- if get_mode() == sculpt:
- enum = bpy.context.tool_settings.sculpt.brush.bl_rna.properties['sculpt_plane'].enum_items
+ has_brush = utils_core.get_brush_link(bpy.context, types="brush")
+
+ if utils_core.get_mode() == utils_core.sculpt:
+ enum = has_brush.bl_rna.properties['sculpt_plane'].enum_items if \
+ has_brush else None
path = "tool_settings.sculpt.brush.sculpt_plane"
- elif get_mode() == texture_paint:
- enum = bpy.context.tool_settings.image_paint.brush.bl_rna.properties['blend'].enum_items
+ elif utils_core.get_mode() == utils_core.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 = bpy.context.tool_settings.vertex_paint.brush.bl_rna.properties['vertex_tool'].enum_items
+ enum = has_brush.bl_rna.properties['vertex_tool'].enum_items if \
+ has_brush else None
path = "tool_settings.vertex_paint.brush.vertex_tool"
return enum, path
def draw(self, context):
enum, path = self.init()
- menu = Menu(self)
+ menu = utils_core.Menu(self)
+ colum_n = utils_core.addon_settings(lists=False)
menu.add_item().label(text="Brush Mode")
menu.add_item().separator()
- if get_mode() == texture_paint:
- column_flow = menu.add_item("column_flow", columns=2)
-
- # add all the brush modes to the menu
- for brush in enum:
- menuprop(menu.add_item(parent=column_flow), brush.name,
- brush.identifier, path, icon='RADIOBUT_OFF',
- disable=True, disable_icon='RADIOBUT_ON')
-
+ if enum:
+ if utils_core.get_mode() == utils_core.texture_paint:
+ column_flow = menu.add_item("column_flow", columns=colum_n)
+
+ # add all the brush modes to the menu
+ for brush in enum:
+ utils_core.menuprop(
+ menu.add_item(parent=column_flow), 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(
+ menu.add_item(), 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:
- menuprop(menu.add_item(), brush.name,
- brush.identifier, path, icon='RADIOBUT_OFF',
- disable=True, disable_icon='RADIOBUT_ON')
+ menu.add_item().label("No brushes available", icon="INFO")
-class BrushAutosmoothMenu(bpy.types.Menu):
+class BrushAutosmoothMenu(Menu):
bl_label = "Autosmooth"
bl_idname = "VIEW3D_MT_sv3_brush_autosmooth_menu"
@@ -325,27 +399,32 @@ class BrushAutosmoothMenu(bpy.types.Menu):
def draw(self, context):
settings = self.init()
- menu = Menu(self)
+ menu = utils_core.Menu(self)
+ has_brush = utils_core.get_brush_link(context, types="brush")
- # add the top slider
- menu.add_item().prop(context.tool_settings.sculpt.brush,
- "auto_smooth_factor", slider=True)
- menu.add_item().separator()
+ if has_brush:
+ # add the top slider
+ menu.add_item().prop(has_brush, "auto_smooth_factor", slider=True)
+ menu.add_item().separator()
- # add the rest of the menu items
- for i in range(len(settings)):
- menuprop(menu.add_item(), settings[i][0], settings[i][1],
- "tool_settings.sculpt.brush.auto_smooth_factor",
- icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON')
+ # add the rest of the menu items
+ for i in range(len(settings)):
+ utils_core.menuprop(
+ menu.add_item(), settings[i][0], settings[i][1],
+ "tool_settings.sculpt.brush.auto_smooth_factor",
+ icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ menu.add_item().label("No Smooth options available", icon="INFO")
-class BrushWeightMenu(bpy.types.Menu):
+class BrushWeightMenu(Menu):
bl_label = "Weight"
bl_idname = "VIEW3D_MT_sv3_brush_weight_menu"
def draw(self, context):
- if get_mode() == weight_paint:
+ if utils_core.get_mode() == utils_core.weight_paint:
brush = context.tool_settings.unified_paint_settings
brushstr = "tool_settings.unified_paint_settings.weight"
name = "Weight"
@@ -353,29 +432,33 @@ class BrushWeightMenu(bpy.types.Menu):
brush = context.tool_settings.image_paint.brush
brushstr = "tool_settings.image_paint.brush.weight"
name = "Mask Value"
-
- menu = Menu(self)
+
+ menu = utils_core.Menu(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 brush:
+ # add the top slider
+ menu.add_item().prop(brush,
+ "weight", text=name, slider=True)
+ menu.add_item().separator()
- # add the top slider
- menu.add_item().prop(brush,
- "weight", text=name, slider=True)
- menu.add_item().separator()
-
- # add the rest of the menu items
- for i in range(len(settings)):
- menuprop(menu.add_item(), settings[i][0], settings[i][1],
- brushstr,
- icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON')
+ # add the rest of the menu items
+ for i in range(len(settings)):
+ utils_core.menuprop(
+ menu.add_item(), settings[i][0], settings[i][1],
+ brushstr,
+ icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ menu.add_item().label("No brush available", icon="INFO")
-class ParticleCountMenu(bpy.types.Menu):
+class ParticleCountMenu(Menu):
bl_label = "Count"
bl_idname = "VIEW3D_MT_sv3_particle_count_menu"
@@ -391,7 +474,7 @@ class ParticleCountMenu(bpy.types.Menu):
def draw(self, context):
settings = self.init()
- menu = Menu(self)
+ menu = utils_core.Menu(self)
# add the top slider
menu.add_item().prop(context.tool_settings.particle_edit.brush,
@@ -400,123 +483,168 @@ class ParticleCountMenu(bpy.types.Menu):
# add the rest of the menu items
for i in range(len(settings)):
- menuprop(menu.add_item(), settings[i][0], settings[i][1],
- "tool_settings.particle_edit.brush.count",
- icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON')
+ utils_core.menuprop(
+ menu.add_item(), settings[i][0], settings[i][1],
+ "tool_settings.particle_edit.brush.count",
+ icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
-class ParticleLengthMenu(bpy.types.Menu):
+class ParticleLengthMenu(Menu):
bl_label = "Length Mode"
bl_idname = "VIEW3D_MT_sv3_particle_length_menu"
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
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:
- menuprop(menu.add_item(), item.name, item.identifier, path,
- icon='RADIOBUT_OFF',
- disable=True,
- disable_icon='RADIOBUT_ON')
+ for item in context.tool_settings.particle_edit.brush. \
+ bl_rna.properties['length_mode'].enum_items:
+ utils_core.menuprop(
+ menu.add_item(), item.name, item.identifier, path,
+ icon='RADIOBUT_OFF',
+ disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
-class ParticlePuffMenu(bpy.types.Menu):
+
+class ParticlePuffMenu(Menu):
bl_label = "Puff Mode"
bl_idname = "VIEW3D_MT_sv3_particle_puff_menu"
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
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:
- menuprop(menu.add_item(), item.name, item.identifier, path,
- icon='RADIOBUT_OFF',
- disable=True,
- disable_icon='RADIOBUT_ON')
+ for item in context.tool_settings.particle_edit.brush. \
+ bl_rna.properties['puff_mode'].enum_items:
+ utils_core.menuprop(
+ menu.add_item(), item.name, item.identifier, path,
+ icon='RADIOBUT_OFF',
+ disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+
-class FlipColorsTex(bpy.types.Operator):
+class FlipColorsAll(Operator):
bl_label = "Flip Colors"
- bl_idname = "view3d.sv3_flip_colors_tex"
+ 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:
- bpy.ops.paint.brush_colors_flip()
- except:
- pass
+ if self.is_tex is False:
+ color = context.tool_settings.vertex_paint.brush.color
+ secondary_color = context.tool_settings.vertex_paint.brush.secondary_color
- return {'FINISHED'}
-
-class FlipColorsVert(bpy.types.Operator):
- bl_label = "Flip Colors"
- bl_idname = "view3d.sv3_flip_colors_vert"
-
- def execute(self, context):
- 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
-
- return {'FINISHED'}
-
-class ColorPickerPopup(bpy.types.Operator):
+ orig_prim = color.hsv
+ orig_sec = secondary_color.hsv
+
+ color.hsv = orig_sec
+ secondary_color.hsv = orig_prim
+ else:
+ bpy.ops.paint.brush_colors_flip()
+
+ 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):
bl_label = "Color"
bl_idname = "view3d.sv3_color_picker_popup"
bl_options = {'REGISTER'}
+ @classmethod
+ def poll(self, context):
+ return utils_core.get_mode() in (
+ utils_core.vertex_paint,
+ utils_core.texture_paint
+ )
+
def check(self, context):
return True
-
+
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
- if get_mode() == texture_paint:
+ if utils_core.get_mode() == utils_core.texture_paint:
settings = context.tool_settings.image_paint
- brush = settings.brush
-
+ brush = getattr(settings, "brush", None)
else:
settings = context.tool_settings.vertex_paint
brush = settings.brush
+ brush = getattr(settings, "brush", None)
+
+ if brush:
+ menu.add_item().template_color_picker(brush, "color", value_slider=True)
+ menu.add_item("row", align=True).prop(brush, "color", text="")
+ menu.current_item.prop(brush, "secondary_color", text="")
+
+ if utils_core.get_mode() == utils_core.vertex_paint:
+ menu.current_item.operator(
+ FlipColorsAll.bl_idname,
+ icon='FILE_REFRESH', text=""
+ ).is_tex = False
+ else:
+ menu.current_item.operator(
+ FlipColorsAll.bl_idname,
+ icon='FILE_REFRESH', text=""
+ ).is_tex = True
- menu.add_item().template_color_picker(brush, "color", value_slider=True)
- menu.add_item().prop(brush, "color", text="")
- menu.current_item.prop(brush, "secondary_color", text="")
- if get_mode() == vertex_paint:
- menu.current_item.operator(FlipColorsVert.bl_idname, icon='FILE_REFRESH', text="")
+ if settings.palette:
+ menu.add_item("column").template_palette(settings, "palette", color=True)
+
+ menu.add_item().template_ID(settings, "palette", new="palette.new")
else:
- menu.current_item.operator(FlipColorsTex.bl_idname, icon='FILE_REFRESH', text="")
+ menu.add_item().label("No brushes currently available", icon="INFO")
+
+ return
- if settings.palette:
- menu.add_item("column").template_palette(settings, "palette", color=True)
-
- menu.add_item().template_ID(settings, "palette", new="palette.new")
-
def execute(self, context):
return context.window_manager.invoke_popup(self, width=180)
-### ------------ New hotkeys and registration ------------ ###
+class BrushMenuPopup(Operator):
+ bl_label = "Color"
+ bl_idname = "view3d.sv3_brush_menu_popup"
+ bl_options = {'REGISTER'}
-addon_keymaps = []
+ @classmethod
+ def poll(self, context):
+ return utils_core.get_mode() in (
+ utils_core.vertex_paint,
+ utils_core.texture_paint,
+ utils_core.sculpt,
+ utils_core.weight_paint
+ )
+ def check(self, context):
+ return True
-def register():
- wm = bpy.context.window_manager
- modes = ['Sculpt', 'Vertex Paint', 'Weight Paint', 'Image Paint', 'Particle']
+ def draw(self, context):
+ layout = self.layout
+ settings = UnifiedPaintPanel.paint_settings(context)
+ colum_n = utils_core.addon_settings(lists=False)
- for mode in modes:
- km = wm.keyconfigs.addon.keymaps.new(name=mode)
- kmi = km.keymap_items.new('wm.call_menu', 'V', 'PRESS', alt=True)
- kmi.properties.name = "VIEW3D_MT_sv3_brush_options"
- addon_keymaps.append((km, kmi))
+ if utils_core.addon_settings(lists=True) != 'popup':
+ layout.label(text="Seems no active brush", icon="INFO")
+ layout.label(text="in the Tool Shelf", icon="BACK")
+ layout.template_ID_preview(settings, "brush",
+ new="brush.add", rows=3, cols=colum_n)
-def unregister():
- for km, kmi in addon_keymaps:
- km.keymap_items.remove(kmi)
- addon_keymaps.clear()
+ def execute(self, context):
+ return context.window_manager.invoke_popup(self, width=180)
diff --git a/space_view3d_brush_menus/brushes.py b/space_view3d_brush_menus/brushes.py
index 48a0ca38..280b0367 100644
--- a/space_view3d_brush_menus/brushes.py
+++ b/space_view3d_brush_menus/brushes.py
@@ -1,14 +1,17 @@
-from bpy.props import *
-from .Utils.core import *
+# gpl author: Ryan Inch (Imaginer)
+import bpy
+from bpy.types import Menu
+from . import utils_core
+from bl_ui.properties_paint_common import UnifiedPaintPanel
-
-class BrushesMenu(bpy.types.Menu):
+
+class BrushesMenu(Menu):
bl_label = "Brush"
bl_idname = "VIEW3D_MT_sv3_brushes_menu"
def init(self):
- if get_mode() == sculpt:
+ if utils_core.get_mode() == utils_core.sculpt:
datapath = "tool_settings.sculpt.brush"
icon = {"BLOB": 'BRUSH_BLOB',
"CLAY": 'BRUSH_CLAY',
@@ -29,8 +32,7 @@ class BrushesMenu(bpy.types.Menu):
"SMOOTH": 'BRUSH_SMOOTH',
"SNAKE_HOOK": 'BRUSH_SNAKE_HOOK',
"THUMB": 'BRUSH_THUMB'}
-
- elif get_mode() == vertex_paint:
+ elif utils_core.get_mode() == utils_core.vertex_paint:
datapath = "tool_settings.vertex_paint.brush"
icon = {"ADD": 'BRUSH_ADD',
"BLUR": 'BRUSH_BLUR',
@@ -39,8 +41,7 @@ class BrushesMenu(bpy.types.Menu):
"MIX": 'BRUSH_MIX',
"MUL": 'BRUSH_MULTIPLY',
"SUB": 'BRUSH_SUBTRACT'}
-
- elif get_mode() == weight_paint:
+ elif utils_core.get_mode() == utils_core.weight_paint:
datapath = "tool_settings.weight_paint.brush"
icon = {"ADD": 'BRUSH_ADD',
"BLUR": 'BRUSH_BLUR',
@@ -49,8 +50,7 @@ class BrushesMenu(bpy.types.Menu):
"MIX": 'BRUSH_MIX',
"MUL": 'BRUSH_MULTIPLY',
"SUB": 'BRUSH_SUBTRACT'}
-
- elif get_mode() == texture_paint:
+ elif utils_core.get_mode() == utils_core.texture_paint:
datapath = "tool_settings.image_paint.brush"
icon = {"CLONE": 'BRUSH_CLONE',
"DRAW": 'BRUSH_TEXDRAW',
@@ -58,11 +58,9 @@ class BrushesMenu(bpy.types.Menu):
"MASK": 'BRUSH_TEXMASK',
"SMEAR": 'BRUSH_SMEAR',
"SOFTEN": 'BRUSH_SOFTEN'}
-
- elif get_mode() == particle_edit:
+ elif utils_core.get_mode() == utils_core.particle_edit:
datapath = "tool_settings.particle_edit.tool"
icon = None
-
else:
datapath = ""
@@ -70,18 +68,21 @@ class BrushesMenu(bpy.types.Menu):
def draw(self, context):
datapath, icon = self.init()
- menu = Menu(self)
+ menu = utils_core.Menu(self)
+ settings = UnifiedPaintPanel.paint_settings(context)
+ colum_n = utils_core.addon_settings(lists=False)
menu.add_item().label(text="Brush")
menu.add_item().separator()
- current_brush = eval("bpy.context.{}".format(datapath))
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ current_brush = eval("bpy.context.{}".format(datapath)) if has_brush else None
# get the current brush's name
- if current_brush and get_mode() != particle_edit:
+ if current_brush and utils_core.get_mode() != utils_core.particle_edit:
current_brush = current_brush.name
- if get_mode() == particle_edit:
+ if utils_core.get_mode() == utils_core.particle_edit:
particle_tools = [["None", 'NONE'],
["Comb", 'COMB'],
["Smooth", 'SMOOTH'],
@@ -93,45 +94,60 @@ class BrushesMenu(bpy.types.Menu):
# if you are in particle edit mode add the menu items for particle mode
for tool in particle_tools:
- menuprop(menu.add_item(), tool[0], tool[1], datapath,
- icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON')
-
+ utils_core.menuprop(
+ menu.add_item(), tool[0], tool[1], datapath,
+ icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
else:
- # iterate over all the brushes
- for item in bpy.data.brushes:
- if get_mode() == sculpt:
- if item.use_paint_sculpt:
- # if you are in sculpt mode and the brush is a sculpt brush add the brush to the menu
- menuprop(menu.add_item(), item.name,
- 'bpy.data.brushes["%s"]' % item.name,
- datapath, icon=icon[item.sculpt_tool],
- disable=True, custom_disable_exp=[item.name, current_brush],
- path=True)
-
- if get_mode() == vertex_paint:
- if item.use_paint_vertex:
- # if you are in vertex paint mode and the brush is a vertex paint brush add the brush to the menu
- menuprop(menu.add_item(), item.name,
- 'bpy.data.brushes["%s"]' % item.name,
- datapath, icon=icon[item.vertex_tool],
- disable=True, custom_disable_exp=[item.name, current_brush],
- path=True)
-
- if get_mode() == weight_paint:
- if item.use_paint_weight:
- # if you are in weight paint mode and the brush is a weight paint brush add the brush to the menu
- menuprop(menu.add_item(), item.name,
- 'bpy.data.brushes["%s"]' % item.name,
- datapath, icon=icon[item.vertex_tool],
- disable=True, custom_disable_exp=[item.name, current_brush],
- path=True)
-
- if get_mode() == texture_paint:
- if item.use_paint_image:
- # if you are in texture paint mode and the brush is a texture paint brush add the brush to the menu
- menuprop(menu.add_item(), item.name,
- 'bpy.data.brushes["%s"]' % item.name,
- datapath, icon=icon[item.image_tool],
- disable=True, custom_disable_exp=[item.name, current_brush],
- path=True)
+ column_flow = menu.add_item("column_flow", columns=colum_n)
+ if utils_core.addon_settings(lists=True) == 'template':
+ self.layout.template_ID_preview(settings, "brush",
+ new="brush.add", rows=3, cols=colum_n)
+ else:
+ # iterate over all the brushes
+ for item in bpy.data.brushes:
+ if utils_core.get_mode() == utils_core.sculpt:
+ if item.use_paint_sculpt:
+ # if you are in sculpt mode and the brush
+ # is a sculpt brush add the brush to the menu
+ utils_core.menuprop(
+ menu.add_item(parent=column_flow), item.name,
+ 'bpy.data.brushes["%s"]' % item.name,
+ datapath, icon=icon[item.sculpt_tool],
+ disable=True, custom_disable_exp=[item.name, current_brush],
+ path=True
+ )
+ if utils_core.get_mode() == utils_core.vertex_paint:
+ if item.use_paint_vertex:
+ # if you are in vertex paint mode and the brush
+ # is a vertex paint brush add the brush to the menu
+ utils_core.menuprop(
+ menu.add_item(parent=column_flow), item.name,
+ 'bpy.data.brushes["%s"]' % item.name,
+ datapath, icon=icon[item.vertex_tool],
+ disable=True, custom_disable_exp=[item.name, current_brush],
+ path=True
+ )
+ if utils_core.get_mode() == utils_core.weight_paint:
+ if item.use_paint_weight:
+ # if you are in weight paint mode and the brush
+ # is a weight paint brush add the brush to the menu
+ utils_core.menuprop(
+ menu.add_item(parent=column_flow), item.name,
+ 'bpy.data.brushes["%s"]' % item.name,
+ datapath, icon=icon[item.vertex_tool],
+ disable=True, custom_disable_exp=[item.name, current_brush],
+ path=True
+ )
+ if utils_core.get_mode() == utils_core.texture_paint:
+ if item.use_paint_image:
+ # if you are in texture paint mode and the brush
+ # is a texture paint brush add the brush to the menu
+ utils_core.menuprop(
+ menu.add_item(parent=column_flow), item.name,
+ 'bpy.data.brushes["%s"]' % item.name,
+ datapath, icon=icon[item.image_tool],
+ disable=True, custom_disable_exp=[item.name, current_brush],
+ path=True
+ )
diff --git a/space_view3d_brush_menus/curve_menu.py b/space_view3d_brush_menus/curve_menu.py
index b7762e01..32d488bd 100644
--- a/space_view3d_brush_menus/curve_menu.py
+++ b/space_view3d_brush_menus/curve_menu.py
@@ -1,19 +1,26 @@
-from .Utils.core import *
+# gpl author: Ryan Inch (Imaginer)
+from bpy.types import (
+ Operator,
+ Menu,
+ )
+from . import utils_core
-class BrushCurveMenu(bpy.types.Menu):
+
+class BrushCurveMenu(Menu):
bl_label = "Curve"
bl_idname = "VIEW3D_MT_sv3_brush_curve_menu"
@classmethod
def poll(self, context):
- if get_mode() in [sculpt, vertex_paint, weight_paint, texture_paint, particle_edit]:
- return True
- else:
- return False
+ return utils_core.get_mode() in (
+ utils_core.sculpt, utils_core.vertex_paint,
+ utils_core.weight_paint, utils_core.texture_paint,
+ utils_core.particle_edit
+ )
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
curves = [["Smooth", "SMOOTH", "SMOOTHCURVE"],
["Sphere", "ROUND", "SPHERECURVE"],
["Root", "ROOT", "ROOTCURVE"],
@@ -27,31 +34,38 @@ class BrushCurveMenu(bpy.types.Menu):
# add the rest of the menu items
for curve in curves:
- item = menu.add_item().operator("brush.curve_preset", text=curve[0], icon=curve[2])
+ item = menu.add_item().operator("brush.curve_preset",
+ text=curve[0], icon=curve[2])
item.shape = curve[1]
-class CurvePopup(bpy.types.Operator):
+class CurvePopup(Operator):
bl_label = "Adjust Curve"
bl_idname = "view3d.sv3_curve_popup"
bl_options = {'REGISTER'}
- def draw(self, context):
- menu = Menu(self)
-
- if get_mode() == sculpt:
- brush = context.tool_settings.sculpt.brush
-
- elif get_mode() == vertex_paint:
- brush = context.tool_settings.vertex_paint.brush
+ @classmethod
+ def poll(self, context):
+ return utils_core.get_mode() in (
+ utils_core.sculpt, utils_core.vertex_paint,
+ utils_core.weight_paint, utils_core.texture_paint
+ )
- elif get_mode() == weight_paint:
- brush = context.tool_settings.weight_paint.brush
+ def draw(self, context):
+ menu = utils_core.Menu(self)
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ if utils_core.get_mode() == utils_core.sculpt or \
+ utils_core.get_mode() == utils_core.vertex_paint or \
+ utils_core.get_mode() == utils_core.weight_paint or \
+ utils_core.get_mode() == utils_core.texture_paint:
+ if has_brush:
+ menu.add_item("column").template_curve_mapping(has_brush,
+ "curve", brush=True)
+ else:
+ menu.add_item().label("No brushes available", icon="INFO")
else:
- brush = context.tool_settings.image_paint.brush
-
- menu.add_item("column").template_curve_mapping(brush, "curve", brush=True)
+ menu.add_item().label("No brushes available", icon="INFO")
def execute(self, context):
return context.window_manager.invoke_popup(self, width=180)
diff --git a/space_view3d_brush_menus/dyntopo_menu.py b/space_view3d_brush_menus/dyntopo_menu.py
index a15c562c..bab317f6 100644
--- a/space_view3d_brush_menus/dyntopo_menu.py
+++ b/space_view3d_brush_menus/dyntopo_menu.py
@@ -1,22 +1,24 @@
-from bpy.props import *
-from .Utils.core import *
+# gpl author: Ryan Inch (Imaginer)
-class DynTopoMenu(bpy.types.Menu):
+import bpy
+from bpy.types import Menu
+from . import utils_core
+
+
+class DynTopoMenu(Menu):
bl_label = "Dyntopo"
bl_idname = "VIEW3D_MT_sv3_dyntopo"
@classmethod
def poll(self, context):
- if get_mode() == sculpt:
- return True
- else:
- return False
+ return utils_core.get_mode() == utils_core.sculpt
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
if context.object.use_dynamic_topology_sculpting:
- menu.add_item().operator("sculpt.dynamic_topology_toggle", "Disable Dynamic Topology")
+ menu.add_item().operator("sculpt.dynamic_topology_toggle",
+ "Disable Dynamic Topology")
menu.add_item().separator()
@@ -26,19 +28,21 @@ class DynTopoMenu(bpy.types.Menu):
menu.add_item().separator()
menu.add_item().operator("sculpt.optimize")
- if bpy.context.tool_settings.sculpt.detail_type_method == 'CONSTANT':
+ if context.tool_settings.sculpt.detail_type_method == 'CONSTANT':
menu.add_item().operator("sculpt.detail_flood_fill")
menu.add_item().menu(SymmetrizeMenu.bl_idname)
- menu.add_item().prop(context.tool_settings.sculpt, "use_smooth_shading", toggle=True)
+ menu.add_item().prop(context.tool_settings.sculpt,
+ "use_smooth_shading", toggle=True)
else:
menu.add_item()
menu.current_item.operator_context = 'INVOKE_DEFAULT'
- menu.current_item.operator("sculpt.dynamic_topology_toggle", "Enable Dynamic Topology")
+ menu.current_item.operator("sculpt.dynamic_topology_toggle",
+ "Enable Dynamic Topology")
-class DynDetailMenu(bpy.types.Menu):
+class DynDetailMenu(Menu):
bl_label = "Detail Size"
bl_idname = "VIEW3D_MT_sv3_dyn_detail"
@@ -58,25 +62,28 @@ class DynDetailMenu(bpy.types.Menu):
def draw(self, context):
settings, datapath, slider_setting = self.init()
- menu = Menu(self)
+ menu = utils_core.Menu(self)
# add the top slider
- menu.add_item().prop(context.tool_settings.sculpt, slider_setting, slider=True)
+ menu.add_item().prop(context.tool_settings.sculpt,
+ slider_setting, slider=True)
menu.add_item().separator()
# add the rest of the menu items
for i in range(len(settings)):
- menuprop(menu.add_item(), settings[i][0], settings[i][1], datapath,
- icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON')
+ utils_core.menuprop(
+ menu.add_item(), settings[i][0], settings[i][1], datapath,
+ icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
-class DetailMethodMenu(bpy.types.Menu):
+class DetailMethodMenu(Menu):
bl_label = "Detail Method"
bl_idname = "VIEW3D_MT_sv3_detail_method_menu"
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
refine_path = "tool_settings.sculpt.detail_refine_method"
type_path = "tool_settings.sculpt.detail_type_method"
@@ -92,8 +99,12 @@ class DetailMethodMenu(bpy.types.Menu):
# add the refine menu items
for item in refine_items:
- menuprop(menu.add_item(), item[0], item[1], refine_path, disable=True,
- icon='RADIOBUT_OFF', disable_icon='RADIOBUT_ON')
+ utils_core.menuprop(
+ menu.add_item(), item[0], item[1],
+ refine_path, disable=True,
+ icon='RADIOBUT_OFF',
+ disable_icon='RADIOBUT_ON'
+ )
menu.add_item().label("")
@@ -102,16 +113,19 @@ class DetailMethodMenu(bpy.types.Menu):
# add the type menu items
for item in type_items:
- menuprop(menu.add_item(), item[0], item[1], type_path, disable=True,
- icon='RADIOBUT_OFF', disable_icon='RADIOBUT_ON')
+ utils_core.menuprop(
+ menu.add_item(), item[0], item[1],
+ type_path, disable=True,
+ icon='RADIOBUT_OFF', disable_icon='RADIOBUT_ON'
+ )
-class SymmetrizeMenu(bpy.types.Menu):
+class SymmetrizeMenu(Menu):
bl_label = "Symmetrize"
bl_idname = "VIEW3D_MT_sv3_symmetrize_menu"
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
path = "tool_settings.sculpt.symmetrize_direction"
# add the the symmetrize operator to the menu
@@ -119,7 +133,10 @@ class SymmetrizeMenu(bpy.types.Menu):
menu.add_item().separator()
# add the rest of the menu items
- for item in context.tool_settings.sculpt.bl_rna.properties['symmetrize_direction'].enum_items:
- menuprop(menu.add_item(), item.name, item.identifier, path, disable=True,
- icon='RADIOBUT_OFF', disable_icon='RADIOBUT_ON')
-
+ for item in context.tool_settings.sculpt. \
+ bl_rna.properties['symmetrize_direction'].enum_items:
+ utils_core.menuprop(
+ menu.add_item(), item.name, item.identifier,
+ path, disable=True,
+ icon='RADIOBUT_OFF', disable_icon='RADIOBUT_ON'
+ )
diff --git a/space_view3d_brush_menus/stroke_menu.py b/space_view3d_brush_menus/stroke_menu.py
index ff0708e7..c2163999 100644
--- a/space_view3d_brush_menus/stroke_menu.py
+++ b/space_view3d_brush_menus/stroke_menu.py
@@ -1,5 +1,8 @@
-from bpy.props import *
-from .Utils.core import *
+# gpl author: Ryan Inch (Imaginer)
+
+import bpy
+from bpy.types import Menu
+from . import utils_core
airbrush = 'AIRBRUSH'
anchored = 'ANCHORED'
@@ -10,108 +13,115 @@ line = 'LINE'
curve = 'CURVE'
-class StrokeOptionsMenu(bpy.types.Menu):
+class StrokeOptionsMenu(Menu):
bl_label = "Stroke Options"
bl_idname = "VIEW3D_MT_sv3_stroke_options"
@classmethod
def poll(self, context):
- if get_mode() in [sculpt, vertex_paint, weight_paint, texture_paint, particle_edit]:
- return True
- else:
- return False
+ return utils_core.get_mode() in (
+ utils_core.sculpt, utils_core.vertex_paint,
+ utils_core.weight_paint, utils_core.texture_paint,
+ utils_core.particle_edit
+ )
def init(self):
- if get_mode() == sculpt:
+ has_brush = utils_core.get_brush_link(bpy.context, types="brush")
+ if utils_core.get_mode() == utils_core.sculpt:
settings = bpy.context.tool_settings.sculpt
- brush = settings.brush
-
- if bpy.app.version > (2, 71):
- stroke_method = brush.stroke_method
-
- else:
- stroke_method = brush.sculpt_stroke_method
- elif get_mode() == texture_paint:
+ elif utils_core.get_mode() == utils_core.texture_paint:
settings = bpy.context.tool_settings.image_paint
- brush = settings.brush
- stroke_method = brush.stroke_method
else:
settings = bpy.context.tool_settings.vertex_paint
- brush = settings.brush
- stroke_method = brush.stroke_method
- return settings, brush, stroke_method
+ stroke_method = has_brush.stroke_method if has_brush else None
+
+ return settings, has_brush, stroke_method
def draw(self, context):
settings, brush, stroke_method = self.init()
- menu = Menu(self)
+ menu = utils_core.Menu(self)
menu.add_item().menu(StrokeMethodMenu.bl_idname)
-
menu.add_item().separator()
- if stroke_method == space:
- menu.add_item().prop(brush, "spacing", text=PIW+"Spacing", slider=True)
+ if stroke_method:
+ if stroke_method == space and brush:
+ menu.add_item().prop(brush, "spacing",
+ text=utils_core.PIW + "Spacing", slider=True)
- elif stroke_method == airbrush:
- menu.add_item().prop(brush, "rate", text=PIW+"Rate", slider=True)
+ elif stroke_method == airbrush and brush:
+ menu.add_item().prop(brush, "rate",
+ text=utils_core.PIW + "Rate", slider=True)
- elif stroke_method == anchored:
+ elif stroke_method == anchored and brush:
menu.add_item().prop(brush, "use_edge_to_edge")
-
- else:
- pass
- if get_mode() == sculpt and stroke_method in [drag_dot, anchored]:
- pass
- else:
- menu.add_item().prop(brush, "jitter", text=PIW+"Jitter", slider=True)
+ else:
+ pass
- menu.add_item().prop(settings, "input_samples", text=PIW+"Input Samples", slider=True)
-
- if stroke_method in [dots, space, airbrush]:
- menu.add_item().separator()
+ if utils_core.get_mode() == utils_core.sculpt and stroke_method in (drag_dot, anchored):
+ pass
+ else:
+ if brush:
+ menu.add_item().prop(brush, "jitter",
+ text=utils_core.PIW + "Jitter", slider=True)
- menu.add_item().prop(brush, "use_smooth_stroke", toggle=True)
+ menu.add_item().prop(settings, "input_samples",
+ text=utils_core.PIW + "Input Samples", slider=True)
- if brush.use_smooth_stroke:
- menu.add_item().prop(brush, "smooth_stroke_radius", text=PIW+"Radius", slider=True)
- menu.add_item().prop(brush, "smooth_stroke_factor", text=PIW+"Factor", slider=True)
+ if stroke_method in [dots, space, airbrush] and brush:
+ menu.add_item().separator()
+ menu.add_item().prop(brush, "use_smooth_stroke", toggle=True)
-class StrokeMethodMenu(bpy.types.Menu):
+ if brush.use_smooth_stroke:
+ menu.add_item().prop(brush, "smooth_stroke_radius",
+ text=utils_core.PIW + "Radius", slider=True)
+ menu.add_item().prop(brush, "smooth_stroke_factor",
+ text=utils_core.PIW + "Factor", slider=True)
+ else:
+ menu.add_item().label("No Stroke Options available", icon="INFO")
+
+
+class StrokeMethodMenu(Menu):
bl_label = "Stroke Method"
bl_idname = "VIEW3D_MT_sv3_stroke_method"
def init(self):
- if get_mode() == sculpt:
- brush = bpy.context.tool_settings.sculpt.brush
+ has_brush = utils_core.get_brush_link(bpy.context, types="brush")
+ if utils_core.get_mode() == utils_core.sculpt:
path = "tool_settings.sculpt.brush.stroke_method"
- elif get_mode() == texture_paint:
- brush = bpy.context.tool_settings.image_paint.brush
+ elif utils_core.get_mode() == utils_core.texture_paint:
path = "tool_settings.image_paint.brush.stroke_method"
else:
- brush = bpy.context.tool_settings.vertex_paint.brush
path = "tool_settings.vertex_paint.brush.stroke_method"
- return brush, path
+ return has_brush, path
def draw(self, context):
brush, path = self.init()
- menu = Menu(self)
+ menu = utils_core.Menu(self)
menu.add_item().label(text="Stroke Method")
menu.add_item().separator()
- # add the menu items dynamicaly based on values in enum property
- for tool in brush.bl_rna.properties['stroke_method'].enum_items:
- if tool.identifier in [anchored, drag_dot] and get_mode() in [vertex_paint, weight_paint]:
- continue
-
- menuprop(menu.add_item(), tool.name, tool.identifier, path,
- icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON')
+ if brush:
+ # add the menu items dynamicaly based on values in enum property
+ for tool in brush.bl_rna.properties['stroke_method'].enum_items:
+ if tool.identifier in [anchored, drag_dot] and \
+ utils_core.get_mode() in [utils_core.vertex_paint,
+ utils_core.weight_paint]:
+ continue
+
+ utils_core.menuprop(
+ menu.add_item(), tool.name, tool.identifier, path,
+ icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ menu.add_item().label("No Stroke Method available", icon="INFO")
diff --git a/space_view3d_brush_menus/symmetry_menu.py b/space_view3d_brush_menus/symmetry_menu.py
index f345e290..6762ddb6 100644
--- a/space_view3d_brush_menus/symmetry_menu.py
+++ b/space_view3d_brush_menus/symmetry_menu.py
@@ -1,55 +1,64 @@
-from bpy.props import *
-from .Utils.core import *
+# gpl author: Ryan Inch (Imaginer)
+from bpy.types import Menu
+from . import utils_core
-class MasterSymmetryMenu(bpy.types.Menu):
+
+class MasterSymmetryMenu(Menu):
bl_label = "Symmetry Options"
bl_idname = "VIEW3D_MT_sv3_master_symmetry_menu"
@classmethod
def poll(self, context):
- if get_mode() in [sculpt, texture_paint]:
- return True
- else:
- return False
+ return utils_core.get_mode() in (
+ utils_core.sculpt,
+ utils_core.texture_paint
+ )
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
- if get_mode() == texture_paint:
- menu.add_item().prop(context.tool_settings.image_paint, "use_symmetry_x", toggle=True)
- menu.add_item().prop(context.tool_settings.image_paint, "use_symmetry_y", toggle=True)
- menu.add_item().prop(context.tool_settings.image_paint, "use_symmetry_z", toggle=True)
+ if utils_core.get_mode() == utils_core.texture_paint:
+ menu.add_item().prop(context.tool_settings.image_paint,
+ "use_symmetry_x", toggle=True)
+ menu.add_item().prop(context.tool_settings.image_paint,
+ "use_symmetry_y", toggle=True)
+ menu.add_item().prop(context.tool_settings.image_paint,
+ "use_symmetry_z", toggle=True)
else:
-
menu.add_item().menu(SymmetryMenu.bl_idname)
menu.add_item().menu(SymmetryRadialMenu.bl_idname)
- menu.add_item().prop(context.tool_settings.sculpt, "use_symmetry_feather", toggle=True)
+ menu.add_item().prop(context.tool_settings.sculpt,
+ "use_symmetry_feather", toggle=True)
-class SymmetryMenu(bpy.types.Menu):
+class SymmetryMenu(Menu):
bl_label = "Symmetry"
bl_idname = "VIEW3D_MT_sv3_symmetry_menu"
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
menu.add_item().label(text="Symmetry")
menu.add_item().separator()
- menu.add_item().prop(context.tool_settings.sculpt, "use_symmetry_x", toggle=True)
- menu.add_item().prop(context.tool_settings.sculpt, "use_symmetry_y", toggle=True)
- menu.add_item().prop(context.tool_settings.sculpt, "use_symmetry_z", toggle=True)
+ menu.add_item().prop(context.tool_settings.sculpt,
+ "use_symmetry_x", toggle=True)
+ menu.add_item().prop(context.tool_settings.sculpt,
+ "use_symmetry_y", toggle=True)
+ menu.add_item().prop(context.tool_settings.sculpt,
+ "use_symmetry_z", toggle=True)
-class SymmetryRadialMenu(bpy.types.Menu):
+class SymmetryRadialMenu(Menu):
bl_label = "Radial"
bl_idname = "VIEW3D_MT_sv3_symmetry_radial_menu"
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
menu.add_item().label(text="Radial")
menu.add_item().separator()
-
- menu.add_item("column").prop(context.tool_settings.sculpt, "radial_symmetry", text="", slider=True)
+
+ menu.add_item("column").prop(context.tool_settings.sculpt,
+ "radial_symmetry", text="", slider=True)
diff --git a/space_view3d_brush_menus/texture_menu.py b/space_view3d_brush_menus/texture_menu.py
index 1f44bc8f..d961410b 100644
--- a/space_view3d_brush_menus/texture_menu.py
+++ b/space_view3d_brush_menus/texture_menu.py
@@ -1,87 +1,98 @@
-from bpy.props import *
-from .Utils.core import *
+# gpl author: Ryan Inch (Imaginer)
+import bpy
+from bpy.types import Menu
+from . import utils_core
-class TextureMenu(bpy.types.Menu):
+
+class TextureMenu(Menu):
bl_label = "Texture Options"
bl_idname = "VIEW3D_MT_sv3_texture_menu"
@classmethod
def poll(self, context):
- if get_mode() in [sculpt, vertex_paint, texture_paint]:
- return True
- else:
- return False
+ return utils_core.get_mode() in (
+ utils_core.sculpt,
+ utils_core.vertex_paint,
+ utils_core.texture_paint
+ )
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
- if get_mode() == sculpt:
+ if utils_core.get_mode() == utils_core.sculpt:
self.sculpt(menu, context)
- elif get_mode() == vertex_paint:
+ elif utils_core.get_mode() == utils_core.vertex_paint:
self.vertpaint(menu, context)
else:
self.texpaint(menu, context)
def sculpt(self, menu, context):
- tex_slot = context.tool_settings.sculpt.brush.texture_slot
-
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ tex_slot = has_brush.texture_slot if has_brush else None
+
# Menus
menu.add_item().menu(Textures.bl_idname)
menu.add_item().menu(TextureMapMode.bl_idname)
+ menu.add_item().separator()
# Checkboxes
- if tex_slot.map_mode != '3D':
- if tex_slot.map_mode in ['RANDOM', 'VIEW_PLANE', 'AREA_PLANE']:
- if bpy.app.version >= (2, 75):
+ if tex_slot:
+ if tex_slot.map_mode != '3D':
+ if tex_slot.map_mode in ['RANDOM', 'VIEW_PLANE', 'AREA_PLANE']:
menu.add_item().prop(tex_slot, "use_rake", toggle=True)
menu.add_item().prop(tex_slot, "use_random", toggle=True)
- else:
- menu.add_item().menu(TextureAngleSource.bl_idname)
- # Sliders
- menu.add_item().prop(tex_slot, "angle", text=PIW+"Angle", slider=True)
-
- if tex_slot.tex_paint_map_mode in ['RANDOM', 'VIEW_PLANE'] and tex_slot.use_random:
- menu.add_item().prop(tex_slot, "random_angle", text=PIW+"Random Angle", slider=True)
-
- # Operator
- if tex_slot.tex_paint_map_mode == 'STENCIL':
- menu.add_item().operator("brush.stencil_reset_transform")
+ # Sliders
+ menu.add_item().prop(tex_slot, "angle",
+ text=utils_core.PIW + "Angle", slider=True)
+
+ if tex_slot.tex_paint_map_mode in ['RANDOM', 'VIEW_PLANE'] and tex_slot.use_random:
+ menu.add_item().prop(tex_slot, "random_angle",
+ text=utils_core.PIW + "Random Angle", slider=True)
+
+ # Operator
+ if tex_slot.tex_paint_map_mode == 'STENCIL':
+ menu.add_item().operator("brush.stencil_reset_transform")
+ else:
+ menu.add_item().label("No Texture Slot available", icon="INFO")
def vertpaint(self, menu, context):
- tex_slot = context.tool_settings.vertex_paint.brush.texture_slot
-
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ tex_slot = has_brush.texture_slot if has_brush else None
+
# Menus
menu.add_item().menu(Textures.bl_idname)
menu.add_item().menu(TextureMapMode.bl_idname)
# Checkboxes
- if tex_slot.tex_paint_map_mode != '3D':
+ if tex_slot and tex_slot.tex_paint_map_mode != '3D':
if tex_slot.tex_paint_map_mode in ['RANDOM', 'VIEW_PLANE']:
- if bpy.app.version >= (2, 75):
- menu.add_item().prop(tex_slot, "use_rake", toggle=True)
- menu.add_item().prop(tex_slot, "use_random", toggle=True)
- else:
- menu.add_item().menu(TextureAngleSource.bl_idname)
+ menu.add_item().prop(tex_slot, "use_rake", toggle=True)
+ menu.add_item().prop(tex_slot, "use_random", toggle=True)
# Sliders
- menu.add_item().prop(tex_slot, "angle", text=PIW+"Angle", slider=True)
-
+ menu.add_item().prop(tex_slot, "angle",
+ text=utils_core.PIW + "Angle", slider=True)
+
if tex_slot.tex_paint_map_mode in ['RANDOM', 'VIEW_PLANE'] and tex_slot.use_random:
- menu.add_item().prop(tex_slot, "random_angle", text=PIW+"Random Angle", slider=True)
-
+ menu.add_item().prop(tex_slot, "random_angle",
+ text=utils_core.PIW + "Random Angle", slider=True)
+
# Operator
if tex_slot.tex_paint_map_mode == 'STENCIL':
menu.add_item().operator("brush.stencil_reset_transform")
+ else:
+ menu.add_item().label("No Texture Slot available", icon="INFO")
def texpaint(self, menu, context):
- tex_slot = context.tool_settings.image_paint.brush.texture_slot
- mask_tex_slot = context.tool_settings.image_paint.brush.mask_texture_slot
-
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ tex_slot = has_brush.texture_slot if has_brush else None
+ mask_tex_slot = has_brush.mask_texture_slot if has_brush else None
+
# Texture Section
menu.add_item().label(text="Texture", icon='TEXTURE')
@@ -90,20 +101,19 @@ class TextureMenu(bpy.types.Menu):
menu.add_item().menu(TextureMapMode.bl_idname)
# Checkboxes
- if tex_slot.tex_paint_map_mode != '3D':
+ if tex_slot and tex_slot.tex_paint_map_mode != '3D':
if tex_slot.tex_paint_map_mode in ['RANDOM', 'VIEW_PLANE']:
- if bpy.app.version >= (2, 75):
- menu.add_item().prop(tex_slot, "use_rake", toggle=True)
- menu.add_item().prop(tex_slot, "use_random", toggle=True)
- else:
- menu.add_item().menu(TextureAngleSource.bl_idname)
+ menu.add_item().prop(tex_slot, "use_rake", toggle=True)
+ menu.add_item().prop(tex_slot, "use_random", toggle=True)
# Sliders
- menu.add_item().prop(tex_slot, "angle", text=PIW+"Angle", slider=True)
+ menu.add_item().prop(tex_slot, "angle",
+ text=utils_core.PIW + "Angle", slider=True)
if tex_slot.tex_paint_map_mode in ['RANDOM', 'VIEW_PLANE'] and tex_slot.use_random:
- menu.add_item().prop(tex_slot, "random_angle", text=PIW+"Random Angle", slider=True)
-
+ menu.add_item().prop(tex_slot, "random_angle",
+ text=utils_core.PIW + "Random Angle", slider=True)
+
# Operator
if tex_slot.tex_paint_map_mode == 'STENCIL':
menu.add_item().operator("brush.stencil_reset_transform")
@@ -118,37 +128,40 @@ class TextureMenu(bpy.types.Menu):
menu.add_item().menu(MaskMapMode.bl_idname)
# Checkboxes
- if mask_tex_slot.mask_map_mode in ['RANDOM', 'VIEW_PLANE']:
- if bpy.app.version >= (2, 75):
+ if mask_tex_slot:
+ if mask_tex_slot.mask_map_mode in ['RANDOM', 'VIEW_PLANE']:
menu.add_item().prop(mask_tex_slot, "use_rake", toggle=True)
menu.add_item().prop(mask_tex_slot, "use_random", toggle=True)
- else:
- menu.add_item().menu(TextureAngleSource.bl_idname)
- # Sliders
- menu.add_item().prop(mask_tex_slot, "angle", text=PIW+"Angle", icon_value=5, slider=True)
+ # Sliders
+ menu.add_item().prop(mask_tex_slot, "angle",
+ text=utils_core.PIW + "Angle", icon_value=5, slider=True)
- if mask_tex_slot.mask_map_mode in ['RANDOM', 'VIEW_PLANE'] and mask_tex_slot.use_random:
- menu.add_item().prop(mask_tex_slot, "random_angle", text=PIW+"Random Angle", slider=True)
-
- # Operator
- if mask_tex_slot.mask_map_mode == 'STENCIL':
- prop = menu.add_item().operator("brush.stencil_reset_transform")
- prop.mask = True
+ if mask_tex_slot.mask_map_mode in ['RANDOM', 'VIEW_PLANE'] and \
+ mask_tex_slot.use_random:
+ menu.add_item().prop(mask_tex_slot, "random_angle",
+ text=utils_core.PIW + "Random Angle", slider=True)
+ # Operator
+ if mask_tex_slot.mask_map_mode == 'STENCIL':
+ prop = menu.add_item().operator("brush.stencil_reset_transform")
+ prop.mask = True
+ else:
+ menu.add_item().label("Mask Texture not available", icon="INFO")
-class Textures(bpy.types.Menu):
+
+class Textures(Menu):
bl_label = "Brush Texture"
bl_idname = "VIEW3D_MT_sv3_texture_list"
def init(self):
- if get_mode() == sculpt:
+ if utils_core.get_mode() == utils_core.sculpt:
datapath = "tool_settings.sculpt.brush.texture"
- elif get_mode() == vertex_paint:
+ elif utils_core.get_mode() == utils_core.vertex_paint:
datapath = "tool_settings.vertex_paint.brush.texture"
- elif get_mode() == texture_paint:
+ elif utils_core.get_mode() == utils_core.texture_paint:
datapath = "tool_settings.image_paint.brush.texture"
else:
@@ -158,8 +171,10 @@ class Textures(bpy.types.Menu):
def draw(self, context):
datapath = self.init()
- current_texture = eval("bpy.context.{}".format(datapath))
- menu = Menu(self)
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ current_texture = eval("bpy.context.{}".format(datapath)) if \
+ has_brush else None
+ menu = utils_core.Menu(self)
# get the current texture's name
if current_texture:
@@ -169,7 +184,7 @@ class Textures(bpy.types.Menu):
menu.add_item().separator()
# add an item to set the texture to None
- menuprop(menu.add_item(), "None", "None",
+ utils_core.menuprop(menu.add_item(), "None", "None",
datapath, icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON',
custom_disable_exp=[None, current_texture],
@@ -177,7 +192,7 @@ class Textures(bpy.types.Menu):
# add the menu items
for item in bpy.data.textures:
- menuprop(menu.add_item(), item.name,
+ utils_core.menuprop(menu.add_item(), item.name,
'bpy.data.textures["%s"]' % item.name,
datapath, icon='RADIOBUT_OFF',
disable=True,
@@ -186,121 +201,156 @@ class Textures(bpy.types.Menu):
path=True)
-class TextureMapMode(bpy.types.Menu):
+class TextureMapMode(Menu):
bl_label = "Brush Mapping"
bl_idname = "VIEW3D_MT_sv3_texture_map_mode"
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
+ has_brush = utils_core.get_brush_link(context, types="brush")
menu.add_item().label(text="Brush Mapping")
menu.add_item().separator()
- if get_mode() == sculpt:
- path = "tool_settings.sculpt.brush.texture_slot.map_mode"
-
- # add the menu items
- for item in context.tool_settings.sculpt.brush.texture_slot.bl_rna.properties['map_mode'].enum_items:
- menuprop(menu.add_item(), item.name, item.identifier, path,
- icon='RADIOBUT_OFF',
- disable=True,
- disable_icon='RADIOBUT_ON')
-
- elif get_mode() == vertex_paint:
- path = "tool_settings.vertex_paint.brush.texture_slot.tex_paint_map_mode"
-
- # add the menu items
- for item in context.tool_settings.vertex_paint.brush.texture_slot.bl_rna.properties['tex_paint_map_mode'].enum_items:
- menuprop(menu.add_item(), item.name, item.identifier, path,
- icon='RADIOBUT_OFF',
- disable=True,
- disable_icon='RADIOBUT_ON')
-
+ if has_brush:
+ if utils_core.get_mode() == utils_core.sculpt:
+ path = "tool_settings.sculpt.brush.texture_slot.map_mode"
+
+ # add the menu items
+ for item in has_brush. \
+ texture_slot.bl_rna.properties['map_mode'].enum_items:
+ utils_core.menuprop(
+ menu.add_item(), item.name, item.identifier, path,
+ icon='RADIOBUT_OFF',
+ disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ elif utils_core.get_mode() == utils_core.vertex_paint:
+ path = "tool_settings.vertex_paint.brush.texture_slot.tex_paint_map_mode"
+
+ # add the menu items
+ for item in has_brush. \
+ texture_slot.bl_rna.properties['tex_paint_map_mode'].enum_items:
+ utils_core.menuprop(
+ menu.add_item(), item.name, item.identifier, path,
+ icon='RADIOBUT_OFF',
+ disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ path = "tool_settings.image_paint.brush.texture_slot.tex_paint_map_mode"
+
+ # add the menu items
+ for item in has_brush. \
+ texture_slot.bl_rna.properties['tex_paint_map_mode'].enum_items:
+ utils_core.menuprop(
+ menu.add_item(), item.name, item.identifier, path,
+ icon='RADIOBUT_OFF',
+ disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
else:
- path = "tool_settings.image_paint.brush.texture_slot.tex_paint_map_mode"
-
- # add the menu items
- for item in context.tool_settings.image_paint.brush.texture_slot.bl_rna.properties['tex_paint_map_mode'].enum_items:
- menuprop(menu.add_item(), item.name, item.identifier, path,
- icon='RADIOBUT_OFF',
- disable=True,
- disable_icon='RADIOBUT_ON')
+ menu.add_item().label("No brushes available", icon="INFO")
-class MaskTextures(bpy.types.Menu):
+class MaskTextures(Menu):
bl_label = "Mask Texture"
bl_idname = "VIEW3D_MT_sv3_mask_texture_list"
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
datapath = "tool_settings.image_paint.brush.mask_texture"
- current_texture = eval("bpy.context.{}".format(datapath))
+ has_brush = utils_core.get_brush_link(context, types="brush")
+ current_texture = eval("bpy.context.{}".format(datapath)) if \
+ has_brush else None
menu.add_item().label(text="Mask Texture")
menu.add_item().separator()
- # get the current texture's name
- if current_texture:
- current_texture = current_texture.name
+ if has_brush:
+ # get the current texture's name
+ if current_texture:
+ current_texture = current_texture.name
- # add an item to set the texture to None
- menuprop(menu.add_item(), "None", "None",
- datapath, icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON',
- custom_disable_exp=[None, current_texture],
- path=True)
+ # add an item to set the texture to None
+ utils_core.menuprop(
+ menu.add_item(), "None", "None",
+ datapath, icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON',
+ custom_disable_exp=[None, current_texture],
+ path=True
+ )
- # add the menu items
- for item in bpy.data.textures:
- menuprop(menu.add_item(), item.name, 'bpy.data.textures["%s"]' % item.name,
- datapath, icon='RADIOBUT_OFF', disable=True,
- disable_icon='RADIOBUT_ON',
- custom_disable_exp=[item.name, current_texture],
- path=True)
+ # add the menu items
+ for item in bpy.data.textures:
+ utils_core.menuprop(
+ menu.add_item(), item.name, 'bpy.data.textures["%s"]' % item.name,
+ datapath, icon='RADIOBUT_OFF', disable=True,
+ disable_icon='RADIOBUT_ON',
+ custom_disable_exp=[item.name, current_texture],
+ path=True
+ )
+ else:
+ menu.add_item().label("No brushes available", icon="INFO")
-class MaskMapMode(bpy.types.Menu):
+class MaskMapMode(Menu):
bl_label = "Mask Mapping"
bl_idname = "VIEW3D_MT_sv3_mask_map_mode"
def draw(self, context):
- menu = Menu(self)
-
+ menu = utils_core.Menu(self)
path = "tool_settings.image_paint.brush.mask_texture_slot.mask_map_mode"
+ has_brush = utils_core.get_brush_link(context, types="brush")
menu.add_item().label(text="Mask Mapping")
menu.add_item().separator()
-
- # add the menu items
- for item in context.tool_settings.image_paint.brush.mask_texture_slot.bl_rna.properties['mask_map_mode'].enum_items:
- menuprop(menu.add_item(), item.name, item.identifier, path,
- icon='RADIOBUT_OFF',
- disable=True,
- disable_icon='RADIOBUT_ON')
+ if has_brush:
+ items = has_brush. \
+ mask_texture_slot.bl_rna.properties['mask_map_mode'].enum_items
+ # add the menu items
+ for item in items:
+ utils_core.menuprop(
+ menu.add_item(), item.name, item.identifier, path,
+ icon='RADIOBUT_OFF',
+ disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ menu.add_item().label("No brushes available", icon="INFO")
-class TextureAngleSource(bpy.types.Menu):
+class TextureAngleSource(Menu):
bl_label = "Texture Angle Source"
bl_idname = "VIEW3D_MT_sv3_texture_angle_source"
def draw(self, context):
- menu = Menu(self)
+ menu = utils_core.Menu(self)
+ has_brush = utils_core.get_brush_link(context, types="brush")
- if get_mode() == sculpt:
- items = context.tool_settings.sculpt.brush.bl_rna.properties['texture_angle_source_random'].enum_items
- path = "tool_settings.sculpt.brush.texture_angle_source_random"
+ if has_brush:
+ if utils_core.get_mode() == utils_core.sculpt:
+ items = has_brush. \
+ bl_rna.properties['texture_angle_source_random'].enum_items
+ path = "tool_settings.sculpt.brush.texture_angle_source_random"
- elif get_mode() == vertex_paint:
- items = context.tool_settings.vertex_paint.brush.bl_rna.properties['texture_angle_source_random'].enum_items
- path = "tool_settings.vertex_paint.brush.texture_angle_source_random"
+ elif utils_core.get_mode() == utils_core.vertex_paint:
+ items = has_brush. \
+ bl_rna.properties['texture_angle_source_random'].enum_items
+ path = "tool_settings.vertex_paint.brush.texture_angle_source_random"
- else:
- items = context.tool_settings.image_paint.brush.bl_rna.properties['texture_angle_source_random'].enum_items
- path = "tool_settings.image_paint.brush.texture_angle_source_random"
+ else:
+ items = has_brush. \
+ bl_rna.properties['texture_angle_source_random'].enum_items
+ path = "tool_settings.image_paint.brush.texture_angle_source_random"
- # add the menu items
- for item in items:
- menuprop(menu.add_item(), item[0], item[1], path,
- icon='RADIOBUT_OFF',
- disable=True,
- disable_icon='RADIOBUT_ON')
+ # add the menu items
+ for item in items:
+ utils_core.menuprop(
+ menu.add_item(), item[0], item[1], path,
+ icon='RADIOBUT_OFF',
+ disable=True,
+ disable_icon='RADIOBUT_ON'
+ )
+ else:
+ menu.add_item().label("No brushes available", icon="INFO")
diff --git a/space_view3d_brush_menus/Utils/core.py b/space_view3d_brush_menus/utils_core.py
index ea73a87b..ecac6073 100644
--- a/space_view3d_brush_menus/Utils/core.py
+++ b/space_view3d_brush_menus/utils_core.py
@@ -1,8 +1,6 @@
+# gpl author: Ryan Inch (Imaginer)
+
import bpy
-import time
-import sys
-import os
-import re
object_mode = 'OBJECT'
edit = 'EDIT'
@@ -13,10 +11,53 @@ texture_paint = 'TEXTURE_PAINT'
particle_edit = 'PARTICLE_EDIT'
pose = 'POSE'
gpencil_edit = 'GPENCIL_EDIT'
+get_addon_name = 'space_view3d_brush_menus'
PIW = ' '
-a_props = []
+
+# check for (currently) brushes being linked
+def get_brush_link(context, types="brush"):
+ tool_settings = context.tool_settings
+ has_brush = None
+
+ if get_mode() == sculpt:
+ datapath = tool_settings.sculpt
+
+ elif get_mode() == vertex_paint:
+ datapath = tool_settings.vertex_paint
+
+ elif get_mode() == weight_paint:
+ datapath = tool_settings.weight_paint
+
+ elif get_mode() == texture_paint:
+ datapath = tool_settings.image_paint
+ else:
+ datapath = None
+
+ if types == "brush":
+ has_brush = getattr(datapath, "brush", None)
+
+ return has_brush
+
+
+# Addon settings
+def addon_settings(lists=True):
+ # separate function just for more convience
+ addon = bpy.context.user_preferences.addons[get_addon_name]
+ colum_n = addon.preferences.column_set if addon else 1
+ use_list = addon.preferences.use_brushes_menu_type
+
+ return use_list if lists else colum_n
+
+
+def error_handlers(self, op_name, error, reports="ERROR", func=False):
+ if self and reports:
+ self.report({'WARNING'}, reports + " (See Console for more info)")
+
+ is_func = "Function" if func else "Operator"
+ print("\n[Sculpt/Paint Brush Menus]\n{}: {}\nError: {}\n".format(is_func, op_name, error))
+
class Menu():
def __init__(self, menu):
@@ -34,7 +75,7 @@ class Menu():
# set unique identifier for new items
if not name:
name = len(self.items) + 1
-
+
# create and return a ui layout
if ui_type == "row":
self.current_item = self.items[name] = layout.row(**kwargs)
@@ -60,43 +101,21 @@ class Menu():
self.current_item = self.items[name] = layout.split(**kwargs)
return self.current_item
-
else:
print("Unknown Type")
-def get_selected():
- # get the number of verts from the information string on the info header
- sel_verts_num = (e for e in bpy.context.scene.statistics().split(" | ")
- if e.startswith("Verts:")).__next__()[6:].split("/")
-
- # turn the number of verts from a string to an int
- sel_verts_num = int(sel_verts_num[0].replace("," ,""))
-
- # get the number of edges from the information string on the info header
- sel_edges_num = (e for e in bpy.context.scene.statistics().split(" | ")
- if e.startswith("Edges:")).__next__()[6:].split("/")
-
- # turn the number of edges from a string to an int
- sel_edges_num = int(sel_edges_num[0].replace(",", ""))
-
- # get the number of faces from the information string on the info header
- sel_faces_num = (e for e in bpy.context.scene.statistics().split(" | ")
- if e.startswith("Faces:")).__next__()[6:].split("/")
-
- # turn the number of faces from a string to an int
- sel_faces_num = int(sel_faces_num[0].replace(",", ""))
-
- return sel_verts_num, sel_edges_num, sel_faces_num
-
-
def get_mode():
- if bpy.context.gpencil_data and \
- bpy.context.object.mode == object_mode and \
- bpy.context.scene.grease_pencil.use_stroke_edit_mode:
- return gpencil_edit
- else:
- return bpy.context.object.mode
+ try:
+ if bpy.context.gpencil_data and \
+ bpy.context.object.mode == object_mode and \
+ bpy.context.scene.grease_pencil.use_stroke_edit_mode:
+ return gpencil_edit
+ else:
+ return bpy.context.object.mode
+ except:
+ return None
+
def menuprop(item, name, value, data_path,
icon='NONE', disable=False, disable_icon=None,
@@ -144,61 +163,3 @@ def menuprop(item, name, value, data_path,
# sets the path to what is changed
prop.data_path = data_path
-
-# used for global blender properties
-def set_prop(prop_type, path, **kwargs):
- kwstring = ""
-
- # turn **kwargs into a string that can be used with exec
- for k, v in kwargs.items():
- if type(v) is str:
- v = '"{}"'.format(v)
-
- if callable(v):
- exec("from {0} import {1}".format(v.__module__, v.__name__))
- v = v.__name__
-
- kwstring += "{0}={1}, ".format(k, v)
-
- kwstring = kwstring[:-2]
-
- # create the property
- exec("{0} = bpy.props.{1}({2})".format(path, prop_type, kwstring))
-
- # add the path to a list of property paths
- a_props.append(path)
-
- return eval(path)
-
-# used for removing properties created with set_prop
-def del_props():
- for prop in a_props:
- exec("del {}".format(prop))
-
- a_props.clear()
-
-class SendReport(bpy.types.Operator):
- bl_label = "Send Report"
- bl_idname = "view3d.send_report"
-
- message = bpy.props.StringProperty()
-
- def draw(self, context):
- self.layout.label("Error", icon='ERROR')
- self.layout.label(self.message)
-
- def invoke(self, context, event):
- wm = context.window_manager
- return wm.invoke_popup(self, width=400, height=200)
-
- def execute(self, context):
- self.report({'INFO'}, self.message)
- print(self.message)
- return {'FINISHED'}
-
-def send_report(message):
- def report(scene):
- bpy.ops.view3d.send_report('INVOKE_DEFAULT', message=message)
- bpy.app.handlers.scene_update_pre.remove(report)
-
- bpy.app.handlers.scene_update_pre.append(report)