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
This commit is contained in:
parent
3fe42bb946
commit
29f2b2f34a
|
@ -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,
|
||||
|
||||
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,
|
||||
)
|
||||
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
|
||||
|
||||
# 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_Brush_Selection1(bpy.types.Menu):
|
||||
bl_label = "Brush Tool"
|
||||
|
||||
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):
|
||||
class VIEW3D_MT_Brushes_Pref(AddonPreferences):
|
||||
bl_idname = __name__
|
||||
|
||||
|
||||
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")
|
||||
)
|
||||
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
|
||||
row = layout.row()
|
||||
row.prop(self, "use_brushes_lists")
|
||||
|
||||
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)
|
||||
|
||||
|
||||
# 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()
|
||||
|
|
|
@ -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'}
|
||||
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 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 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 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 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'}
|
||||
|
||||
elif get_mode() == 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")
|
||||
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:
|
||||
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))
|
||||
menu.add_item().menu(BrushRadiusMenu.bl_idname)
|
||||
|
||||
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")
|
||||
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))
|
||||
|
||||
menu.add_item().menu("VIEW3D_MT_sv3_dyntopo")
|
||||
menu.add_item().menu("VIEW3D_MT_sv3_master_symmetry_menu")
|
||||
|
||||
def vw_paint(self, menu, context):
|
||||
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()
|
||||
|
||||
self.draw_brushes(menu, has_brush, icons, context)
|
||||
|
||||
if utils_core.get_mode() == utils_core.vertex_paint:
|
||||
menu.add_item().menu(BrushRadiusMenu.bl_idname)
|
||||
|
||||
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")
|
||||
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'}
|
||||
orig_prim = color.hsv
|
||||
orig_sec = secondary_color.hsv
|
||||
|
||||
class ColorPickerPopup(bpy.types.Operator):
|
||||
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)
|
||||
|
||||
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 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
|
||||
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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'}
|
||||
|
||||
@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
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
elif get_mode() == weight_paint:
|
||||
brush = context.tool_settings.weight_paint.brush
|
||||
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)
|
||||
|
|
|
@ -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'
|
||||
)
|
||||
|
|
|
@ -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 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(settings, "input_samples",
|
||||
text=utils_core.PIW + "Input Samples", 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)
|
||||
|
||||
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:
|
||||
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)
|
||||
|
||||
menu.add_item().prop(settings, "input_samples", text=PIW+"Input Samples", slider=True)
|
||||
|
||||
if stroke_method in [dots, space, airbrush]:
|
||||
menu.add_item().separator()
|
||||
|
||||
menu.add_item().prop(brush, "use_smooth_stroke", toggle=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)
|
||||
menu.add_item().label("No Stroke Options available", icon="INFO")
|
||||
|
||||
|
||||
class StrokeMethodMenu(bpy.types.Menu):
|
||||
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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
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 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')
|
||||
# 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"
|
||||
|
||||
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')
|
||||
# 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 = 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:
|
||||
utils_core.menuprop(
|
||||
menu.add_item(), item[0], item[1], path,
|
||||
icon='RADIOBUT_OFF',
|
||||
disable=True,
|
||||
disable_icon='RADIOBUT_ON'
|
||||
)
|
||||
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"
|
||||
|
||||
# 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')
|
||||
menu.add_item().label("No brushes available", icon="INFO")
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue