Add Easy_Weight to Addons #47

Merged
Nick Alberelli merged 48 commits from feature/easy_weights into main 2023-05-17 22:13:57 +02:00
Showing only changes of commit 16edf4694e - Show all commits

View File

@ -8,14 +8,19 @@ class EASYWEIGHT_OT_wp_context_menu(bpy.types.Operator):
bl_label = "Custom Weight Paint Context Menu" bl_label = "Custom Weight Paint Context Menu"
bl_options = {'REGISTER'} bl_options = {'REGISTER'}
def update_weight_cleaner(self, context): def update_clean_weights(self, context):
context.scene['weight_cleaner'] = self.weight_cleaner context.scene['clean_weights'] = self.clean_weights
WeightCleaner.cleaner_active = context.scene['weight_cleaner'] WeightCleaner.cleaner_active = context.scene['clean_weights']
def update_front_faces(self, context): def update_front_faces(self, context):
for b in bpy.data.brushes: for b in bpy.data.brushes:
if not b.use_paint_weight: continue if not b.use_paint_weight: continue
b.use_frontface = self.front_faces b.use_frontface = self.front_faces
def update_accumulate(self, context):
for b in bpy.data.brushes:
if not b.use_paint_weight: continue
b.use_accumulate = self.accumulate
def update_falloff_shape(self, context): def update_falloff_shape(self, context):
for b in bpy.data.brushes: for b in bpy.data.brushes:
@ -25,9 +30,10 @@ class EASYWEIGHT_OT_wp_context_menu(bpy.types.Operator):
if val > 0: if val > 0:
b.cursor_color_add[i] = (0.5 if self.falloff_shape=='SPHERE' else 2.0) b.cursor_color_add[i] = (0.5 if self.falloff_shape=='SPHERE' else 2.0)
weight_cleaner: BoolProperty(name="Weight Cleaner", update=update_weight_cleaner) clean_weights: BoolProperty(name="Clean Weights", description="Run the Clean Vertex Groups operator after every weight brush stroke", update=update_clean_weights)
front_faces: BoolProperty(name="Front Faces Only", update=update_front_faces) front_faces: BoolProperty(name="Front Faces Only", description="Toggle the Front Faces Only setting for all weight brushes", update=update_front_faces)
falloff_shape: EnumProperty(name="Falloff Shape", update=update_falloff_shape, accumulate: BoolProperty(name="Accumulate", description="Toggle the Accumulate setting for all weight brushes", update=update_accumulate)
falloff_shape: EnumProperty(name="Falloff Type", description="Select the Falloff Shape setting for all weight brushes", update=update_falloff_shape,
items=[ items=[
('SPHERE', 'Sphere', "The brush influence falls off along a sphere whose center is the mesh under the cursor's pointer"), ('SPHERE', 'Sphere', "The brush influence falls off along a sphere whose center is the mesh under the cursor's pointer"),
('PROJECTED', 'Projected', "The brush influence falls off in a tube around the cursor. This is useful for painting backfaces, as long as Front Faces Only is off.") ('PROJECTED', 'Projected', "The brush influence falls off in a tube around the cursor. This is useful for painting backfaces, as long as Front Faces Only is off.")
@ -41,46 +47,78 @@ class EASYWEIGHT_OT_wp_context_menu(bpy.types.Operator):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
layout.label(text="Brush Settings (Global)") minimal = context.scene.easyweight_minimal
overlay = context.space_data.overlay
tool_settings = context.tool_settings
row = layout.row()
row.label(text="Brush Settings (Global)")
icon = 'HIDE_ON' if context.scene.easyweight_minimal else 'HIDE_OFF'
row.prop(context.scene, "easyweight_minimal", icon=icon, toggle=False, text="", emboss=False)
layout.prop(self, "accumulate", toggle=True)
layout.prop(self, "front_faces", toggle=True) layout.prop(self, "front_faces", toggle=True)
layout.prop(self, "falloff_shape", expand=True) row = layout.row(heading="Falloff Shape: ")
row.prop(self, "falloff_shape", expand=True)
layout.separator() layout.separator()
if minimal:
row = layout.row(heading="Symmetry: ")
# Compatibility for versions between rB5502517c3c12086c111a and rBfa9b05149c2ca3915a4fb26.
if hasattr(context.weight_paint_object.data, "use_mirror_vertex_group_x"):
row.prop(context.weight_paint_object.data, "use_mirror_vertex_group_x", text="X-Mirror", toggle=True)
else:
row.prop(context.weight_paint_object.data, "use_mirror_x", text="X-Mirror", toggle=True)
if hasattr(context.weight_paint_object.data, 'use_mirror_vertex_groups'):
row.prop(context.weight_paint_object.data, 'use_mirror_vertex_groups', text="Flip Groups", toggle=True)
row = layout.row(heading="Mesh Display: ")
row.prop(overlay, "show_wpaint_contours", text="Weight Contours", toggle=True)
row.prop(overlay, "show_paint_wire", text="Wireframe", toggle=True)
row = layout.row(heading="Bone Display: ")
row.prop(overlay, "show_bones", text="Bones", toggle=True)
row.prop(context.pose_object, "show_in_front", toggle=True)
return
layout.label(text="Weight Paint settings") layout.label(text="Weight Paint settings")
tool_settings = context.tool_settings
row = layout.row() row = layout.row()
row.prop(tool_settings, "use_auto_normalize", text="Auto Normalize", toggle=True) row.prop(tool_settings, "use_auto_normalize", text="Auto Normalize", toggle=True)
row.prop(self, "weight_cleaner", toggle=True) row.prop(self, "clean_weights", toggle=True)
row = layout.row()
row.prop(tool_settings, "use_multipaint", text="Multi-Paint", toggle=True) row.prop(tool_settings, "use_multipaint", text="Multi-Paint", toggle=True)
row = layout.row()
# Compatibility for versions between rB5502517c3c12086c111a and rBfa9b05149c2ca3915a4fb26.
if hasattr(context.weight_paint_object.data, "use_mirror_vertex_group_x"): if hasattr(context.weight_paint_object.data, "use_mirror_vertex_group_x"):
row.prop(context.weight_paint_object.data, "use_mirror_vertex_group_x", text="X-Mirror", toggle=True) row.prop(context.weight_paint_object.data, "use_mirror_vertex_group_x", text="X-Mirror", toggle=True)
else: # Compatibility pre rB5502517c3c12086c111a else:
row.prop(context.weight_paint_object.data, "use_mirror_x", toggle=True) row.prop(context.weight_paint_object.data, "use_mirror_x", text="X-Mirror", toggle=True)
if hasattr(context.weight_paint_object.data, 'use_mirror_vertex_groups'):
row.prop(context.weight_paint_object.data, 'use_mirror_vertex_groups', text="Flip Groups", toggle=True)
layout.separator() layout.separator()
layout.label(text="Overlay") layout.label(text="Overlay")
row = layout.row() row = layout.row()
row.use_property_split=True row.use_property_split=True
row.prop(tool_settings, "vertex_group_user", text="Zero Weights", expand=True) row.prop(tool_settings, "vertex_group_user", text="Zero Weights Display", expand=True)
if hasattr(context.space_data, "overlay"): if hasattr(context.space_data, "overlay"):
overlay = context.space_data.overlay row = layout.row()
layout.prop(overlay, "show_wpaint_contours", text="Weight Contours", toggle=True) row.prop(overlay, "show_wpaint_contours", text="Weight Contours", toggle=True)
layout.prop(overlay, "show_paint_wire", text="Wireframe", toggle=True) row.prop(overlay, "show_paint_wire", text="Wireframe", toggle=True)
row.prop(overlay, "show_bones", text="Bones", toggle=True)
if context.pose_object: if context.pose_object:
layout.label(text="Armature Display") layout.label(text="Armature Display")
layout.prop(context.pose_object.data, "display_type", expand=True) layout.prop(context.pose_object.data, "display_type", expand=True)
layout.prop(context.pose_object, "show_in_front", toggle=True) layout.prop(context.pose_object, "show_in_front", toggle=True)
def invoke(self, context, event): def invoke(self, context, event):
active_brush = context.tool_settings.weight_paint.brush active_brush = context.tool_settings.weight_paint.brush
self.front_faces = active_brush.use_frontface self.front_faces = active_brush.use_frontface
self.falloff_shape = active_brush.falloff_shape self.falloff_shape = active_brush.falloff_shape
if 'weight_cleaner' not in context.scene: if 'clean_weights' not in context.scene:
context.scene['weight_cleaner'] = False context.scene['clean_weights'] = False
self.weight_cleaner = context.scene['weight_cleaner'] self.clean_weights = context.scene['clean_weights']
wm = context.window_manager wm = context.window_manager
return wm.invoke_props_dialog(self) return wm.invoke_props_dialog(self)
@ -124,10 +162,12 @@ def start_cleaner(scene, depsgraph):
def register(): def register():
from bpy.utils import register_class from bpy.utils import register_class
register_class(EASYWEIGHT_OT_wp_context_menu) register_class(EASYWEIGHT_OT_wp_context_menu)
bpy.types.Scene.easyweight_minimal = BoolProperty(name="Minimal", description="Hide options that are less frequently used", default=False)
start_cleaner(None, None) start_cleaner(None, None)
bpy.app.handlers.load_post.append(start_cleaner) bpy.app.handlers.load_post.append(start_cleaner)
def unregister(): def unregister():
from bpy.utils import unregister_class from bpy.utils import unregister_class
del bpy.types.Scene.easyweight_minimal
unregister_class(EASYWEIGHT_OT_wp_context_menu) unregister_class(EASYWEIGHT_OT_wp_context_menu)
bpy.app.handlers.load_post.remove(start_cleaner) bpy.app.handlers.load_post.remove(start_cleaner)