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:
authorlijenstina <lijenstina@gmail.com>2017-04-22 04:54:45 +0300
committerlijenstina <lijenstina@gmail.com>2017-04-22 04:54:45 +0300
commit29f2b2f34a8255828cf1621edd5c725167338f9f (patch)
treed478f0eb44d078137d62ad5b76d7320bbaf4f494 /space_view3d_brush_menus
parent3fe42bb946bd780e7732afc4c1d100d13830d7e3 (diff)
Sculpt Paint Brush Menus: cleanup, refactor, various fixes
Bumped version to 1.1.4 Remove the Utils folder and move it to file utils_core Remove star imports and replace them with namespace Remove unused imports Use importlib for reloading files Add customization to the brushes (column size, 3 types of menus) Remove the VIEW3D_MT_Brush_Selection1 menu Remove versioning code Add some helper functions in utils_core Fix crash with poll functions get_mode if no active object Fix several crashes with unlinked missing active brush (hope i got it all) Move the shortcut register to the init Update wiki link NOTE: Remove unused operators and functions Part of it is something to do with properties creation Haven't seen the code used anywhere so it was removed If it is needed for something it could be restored later
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)