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
4 changed files with 10 additions and 110 deletions
Showing only changes of commit 6daff43b15 - Show all commits

View File

@ -1,19 +1,9 @@
Easy Weight is an addon focused on quality of life improvements for weight painting in Blender.
### Brush Switching
The addon will force-register keybinds for this operator to the 1, 2, 3 keys in Weight Paint mode:
1: Change to Add Brush.
2: Change to Subtract Brush.
3: Change to Blur Brush.
The brushes must have their default name, ie. "Add", "Subtract", "Blur".
### Entering Weight Paint Mode
The Toggle Weight Paint Mode operator lets you switch into weight paint mode easier.
Select your object and run the operator.
- It will find the first armature modifier of your mesh, if there is one. It will ensure the armature is visible and in pose mode.
- It will set the shading settings to a pure white.
- If your object's display type was set to Wire, it will set it to Solid.
Run the operator again to restore everything to how it was before.
Simply select your mesh object and run the operator. The armature will be un-hidden and put into pose mode if necessary.
Run the operator again to reset the armature object's visibility states to what they were before you entered weight paint mode.
I recommend setting up a keybind for this, eg.:
<img src="docs/toggle_wp_shortcut.png" width="400" />
@ -54,10 +44,13 @@ The Vertex Groups context menu is re-organized with more icons and better labels
- **Delete Unselected Deform Groups**: Delete all deforming groups that don't correspond to a selected pose bone. Only in Weight Paint mode.
- **Ensure Mirror Groups**: If your object has a Mirror modifier, this will create any missing vertex groups.
- **Focus Deforming Bones**: Reveal and select all bones deforming this mesh. Only in Weight Paint mode.
- **Focus Rogue Weights**: This real clever operator will cycle through vertex groups whose weights consist of more than a single island, then enter vertex masking mode and select the vertices of the smallest island. This still requires human eyes to check and make sure the islands are definitely not needed. You are meant to run this operator many times over and over to cycle through such vertex groups.
TODO: Operator to ensure symmetrical weights.
If you have any more suggestions, feel free to open an Issue with a feature request.
### Force Apply Mirror Modifier
In Blender, you cannot apply a mirror modifier to meshes that have shape keys.
This operator tries to anyways, by duplicating your mesh, flipping it on the X axis and merging into the original. It will also flip vertex groups, shape keys, shape key masks, and even (attempt) shape key drivers, assuming everything is named with .L/.R suffixes.
### Previous Features
Over time as more things have been fixed on Blender's side, some features have been removed. To avoid confusion, these are listed here:
- As of [Blender 3.1](https://developer.blender.org/rBa215d7e230d3286abbed0108a46359ce57104bc1), holding the Ctrl and Shift buttons in weight painting will use the Subtract and Blur brushes respectively, removing the need for the shortcuts on the 1, 2, 3 keys this addon used to add to provide quick brush switching.
- As of [Blender 3.0](https://developer.blender.org/rBSc0f600cad1d2d107d189b15b12e2fcc6bba0985c), the weight paint overlay is no longer multiplied on top of the underlying colors, removing the need for this addon to change shading or object display settings when using the Toggle Weight Paint mode operator.

View File

@ -28,7 +28,6 @@ import importlib
from . import smart_weight_transfer
from . import force_apply_mirror
from . import toggle_weight_paint
from . import change_brush
from . import weight_paint_context_menu
from . import vertex_group_operators
from . import vertex_group_menu
@ -39,7 +38,6 @@ modules = [
smart_weight_transfer,
force_apply_mirror,
toggle_weight_paint,
change_brush,
weight_paint_context_menu,
vertex_group_operators,
vertex_group_menu,

View File

@ -1,79 +0,0 @@
import bpy
from bpy.props import *
from bpy.app.handlers import persistent
class EASYWEIGHT_OT_change_brush(bpy.types.Operator):
"""Change the weight paint brush to a specific brush"""
bl_idname = "brush.set_specific"
bl_label = "Set WP Brush"
bl_options = {'REGISTER', 'UNDO'}
brush: EnumProperty(name="Brush",
items=[('Add', 'Add', 'Add'),
('Subtract', 'Subtract', 'Subtract'),
('Draw', 'Draw', 'Draw'),
('Average', 'Average', 'Average'),
('Blur', 'Blur', 'Blur'),
],
default="Add")
def execute(self, context):
brush_name = self.brush
brush = bpy.data.brushes.get(brush_name)
if not brush:
# Create the brush.
brush = bpy.data.brushes.new(brush_name, mode='WEIGHT_PAINT')
if brush_name == 'Add':
brush.blend = 'ADD'
if brush_name == 'Subtract':
brush.blend = 'SUB'
if brush_name == 'Blur':
brush.weight_tool = 'BLUR'
if brush_name == 'Average':
brush.weight_tool = 'AVERAGE'
# Configure brush.
value = 0.5 if brush.falloff_shape == 'SPHERE' else 1.0 # We use a darker color to indicate when falloff shape is set to Sphere.
if brush_name=='Add':
brush.cursor_color_add = [value, 0.0, 0.0, 1.0]
if brush_name=='Subtract':
brush.cursor_color_add = [0.0, 0.0, value, 1.0]
if brush_name=='Blur':
brush.cursor_color_add = [value, value, value, 1.0]
# Set the brush as the active one.
bpy.context.tool_settings.weight_paint.brush = brush
return { 'FINISHED' }
@persistent
def register_brush_switch_hotkeys(dummy):
# Without this, the hotkeys' properties get reset whenever the addon is disabled, which results in having to set the Add, Subtract, Blur brushes on the hotkeys manually every time.
# However, with this, the hotkey cannot be changed, since this will forcibly re-create the original anyways.
active_keyconfig = bpy.context.window_manager.keyconfigs.active
if not active_keyconfig: return # Avoid error when running without UI.
wp_hotkeys = active_keyconfig.keymaps['Weight Paint'].keymap_items
add_hotkey = wp_hotkeys.new('brush.set_specific',value='PRESS',type='ONE',ctrl=False,alt=False,shift=False,oskey=False)
add_hotkey.properties.brush = 'Add'
add_hotkey.type = add_hotkey.type
sub_hotkey = wp_hotkeys.new('brush.set_specific',value='PRESS',type='TWO',ctrl=False,alt=False,shift=False,oskey=False)
sub_hotkey.properties.brush = 'Subtract'
sub_hotkey.type = sub_hotkey.type
blur_hotkey = wp_hotkeys.new('brush.set_specific',value='PRESS',type='THREE',ctrl=False,alt=False,shift=False,oskey=False)
blur_hotkey.properties.brush = 'Blur'
blur_hotkey.type = blur_hotkey.type
def register():
from bpy.utils import register_class
register_class(EASYWEIGHT_OT_change_brush)
register_brush_switch_hotkeys(None)
bpy.app.handlers.load_post.append(register_brush_switch_hotkeys)
def unregister():
from bpy.utils import unregister_class
unregister_class(EASYWEIGHT_OT_change_brush)
bpy.app.handlers.load_post.remove(register_brush_switch_hotkeys)

View File

@ -5,13 +5,12 @@ from bpy.types import Object, Operator, VIEW3D_MT_paint_weight, VIEW3D_MT_object
# It does the following:
# Set active object to weight paint mode
# Make sure active object is not in wireframe or bounding box display type
# Find first armature via the object's modifiers.
# Ensure it is visible, select it and set it to pose mode.
# This allows you to start weight painting with a single button press from any state.
# When running the operator again, it should restore everything to how it was before.
# When running the operator again, it should restore all armature visibility related settings to how it was before.
def get_armature_of_meshob(obj: Object):
"""Find and return the armature that deforms this mesh object."""
@ -26,12 +25,6 @@ def enter_wp(context) -> bool:
obj = context.object
wm = context.window_manager
# Store old display_type setting in a Custom Property on the Object.
obj['wpt_display_type'] = obj.display_type
# Ensure display_type is SOLID; weights don't display in WIRE or BOUNDS.
if obj.display_type not in ['SOLID', 'TEXTURED']:
obj.display_type = 'SOLID'
# Store old shading settings in a Custom Property dictionary in the Scene.
if 'wpt' not in wm:
wm['wpt'] = {}
@ -40,7 +33,7 @@ def enter_wp(context) -> bool:
wpt_as_dict = wpt.to_dict()
# If we are entering WP mode for the first time or if the last time
# the operator was exiting WP mode, then save current shading info.
# the operator was exiting WP mode, then save current state.
if 'last_switch_in' not in wpt_as_dict or wpt_as_dict['last_switch_in']==False:
wpt['active_object'] = obj
@ -87,11 +80,6 @@ def leave_wp(context):
obj = context.object
wm = context.window_manager
# Restore object display type
if 'wpt_display_type' in obj:
obj.display_type = obj['wpt_display_type']
del obj['wpt_display_type']
if 'wpt' not in wm or 'mode' not in wm['wpt'].to_dict():
# There is no saved data to restore from, nothing else to do.
bpy.ops.object.mode_set(mode='OBJECT')