EasyWeight: Major update #317
@ -1,24 +1,11 @@
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from . import (
|
||||
rogue_weights,
|
||||
vertex_group_menu,
|
||||
vertex_group_operators,
|
||||
weight_paint_context_menu,
|
||||
toggle_weight_paint,
|
||||
force_apply_mirror,
|
||||
toggle_weight_paint,
|
||||
weight_paint_context_menu,
|
||||
vertex_group_operators,
|
||||
weight_cleaner,
|
||||
vertex_group_menu,
|
||||
rogue_weights,
|
||||
prefs,
|
||||
)
|
||||
import bpy
|
||||
@ -42,6 +29,7 @@ modules = [
|
||||
toggle_weight_paint,
|
||||
weight_paint_context_menu,
|
||||
vertex_group_operators,
|
||||
weight_cleaner,
|
||||
vertex_group_menu,
|
||||
rogue_weights,
|
||||
prefs,
|
||||
|
@ -1,15 +1,31 @@
|
||||
import bpy, json
|
||||
from bpy.props import BoolProperty
|
||||
from . import __package__ as base_package
|
||||
|
||||
|
||||
def get_addon_prefs(context=None):
|
||||
if not context:
|
||||
context = bpy.context
|
||||
if base_package.startswith('bl_ext'):
|
||||
# 4.2
|
||||
return context.preferences.addons[base_package].preferences
|
||||
else:
|
||||
return context.preferences.addons[base_package.split(".")[0]].preferences
|
||||
|
||||
|
||||
class EASYWEIGHT_addon_preferences(bpy.types.AddonPreferences):
|
||||
bl_idname = __package__
|
||||
easyweight_keymap_items = {}
|
||||
|
||||
auto_clean_weights: BoolProperty(
|
||||
name="Auto Clean",
|
||||
description="While this is enabled, zero-weights will be removed automatically after every brush stroke",
|
||||
default=True,
|
||||
)
|
||||
show_hotkeys: BoolProperty(
|
||||
name="Show Hotkeys",
|
||||
default=False,
|
||||
description="Reveal the hotkey list. You may customize or disable these hotkeys",
|
||||
default=False,
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
@ -205,12 +221,6 @@ def register():
|
||||
)
|
||||
register_hotkey(
|
||||
bl_idname='object.weight_paint_toggle',
|
||||
hotkey_kwargs={
|
||||
'type': 'TAB',
|
||||
'value': 'PRESS',
|
||||
'ctrl': True
|
||||
},
|
||||
hotkey_kwargs={'type': 'TAB', 'value': 'PRESS', 'ctrl': True},
|
||||
key_cat='3D View',
|
||||
)
|
||||
|
||||
|
||||
|
55
scripts-blender/addons/easy_weights/weight_cleaner.py
Normal file
55
scripts-blender/addons/easy_weights/weight_cleaner.py
Normal file
@ -0,0 +1,55 @@
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
from .prefs import get_addon_prefs
|
||||
|
||||
|
||||
@persistent
|
||||
def start_cleaner(scene, depsgraph):
|
||||
bpy.app.handlers.depsgraph_update_pre.append(WeightCleaner.clean_weights)
|
||||
bpy.app.handlers.depsgraph_update_post.append(WeightCleaner.reset_flag)
|
||||
|
||||
|
||||
class WeightCleaner:
|
||||
"""Run bpy.ops.object.vertex_group_clean on every depsgraph update while in weight paint mode (ie. every brush stroke)."""
|
||||
|
||||
# Flag set in post_depsgraph_update, to indicate to pre_depsgraph_update that the depsgraph update has indeed completed.
|
||||
can_clean = True
|
||||
# Flag set by pre_depsgraph_update to indicate to post_depsgraph_update that the cleanup operator is still running (in a different thread).
|
||||
cleaning_in_progress = False
|
||||
|
||||
@classmethod
|
||||
def clean_weights(cls, scene, depsgraph):
|
||||
context = bpy.context
|
||||
prefs = get_addon_prefs(context)
|
||||
if context.mode != 'PAINT_WEIGHT':
|
||||
return
|
||||
if not context or not hasattr(context, 'object') or not context.object:
|
||||
return
|
||||
if not prefs.auto_clean_weights:
|
||||
return
|
||||
if cls.can_clean:
|
||||
cls.can_clean = False
|
||||
cls.cleaning_in_progress = True
|
||||
# This will trigger a depsgraph update, and therefore clean_weights, again.
|
||||
bpy.ops.object.vertex_group_clean(group_select_mode='ALL', limit=0.001)
|
||||
cls.cleaning_in_progress = False
|
||||
|
||||
@classmethod
|
||||
def reset_flag(cls, scene, depsgraph):
|
||||
context = bpy.context
|
||||
if context.mode != 'PAINT_WEIGHT':
|
||||
return
|
||||
if not context or not hasattr(context, 'object') or not context.object:
|
||||
return
|
||||
if cls.cleaning_in_progress:
|
||||
return
|
||||
cls.can_clean = True
|
||||
|
||||
|
||||
def register():
|
||||
start_cleaner(None, None)
|
||||
bpy.app.handlers.load_post.append(start_cleaner)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.app.handlers.load_post.remove(start_cleaner)
|
@ -1,7 +1,7 @@
|
||||
import bpy
|
||||
from bpy.props import BoolProperty, EnumProperty
|
||||
from bpy.app.handlers import persistent
|
||||
from .vertex_group_operators import EASYWEIGHTS_OT_delete_empty_deform_groups, EASYWEIGHTS_OT_delete_unused_vertex_groups
|
||||
from .prefs import get_addon_prefs
|
||||
|
||||
class EASYWEIGHT_OT_wp_context_menu(bpy.types.Operator):
|
||||
""" Custom Weight Paint context menu """
|
||||
@ -9,10 +9,6 @@ class EASYWEIGHT_OT_wp_context_menu(bpy.types.Operator):
|
||||
bl_label = "Custom Weight Paint Context Menu"
|
||||
bl_options = {'REGISTER'}
|
||||
|
||||
def update_clean_weights(self, context):
|
||||
context.scene['clean_weights'] = self.clean_weights
|
||||
WeightCleaner.cleaner_active = context.scene['clean_weights']
|
||||
|
||||
def update_front_faces(self, context):
|
||||
for b in bpy.data.brushes:
|
||||
if not b.use_paint_weight:
|
||||
@ -35,8 +31,6 @@ class EASYWEIGHT_OT_wp_context_menu(bpy.types.Operator):
|
||||
b.cursor_color_add[i] = (
|
||||
0.5 if self.falloff_shape == 'SPHERE' else 2.0)
|
||||
|
||||
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", description="Toggle the Front Faces Only setting for all weight brushes", update=update_front_faces)
|
||||
accumulate: BoolProperty(
|
||||
@ -121,10 +115,12 @@ class EASYWEIGHT_OT_wp_context_menu(bpy.types.Operator):
|
||||
tool_settings = context.tool_settings
|
||||
layout.label(text="Weight Paint settings")
|
||||
|
||||
prefs = get_addon_prefs(context)
|
||||
|
||||
row = layout.row()
|
||||
row.prop(tool_settings, "use_auto_normalize",
|
||||
text="Auto Normalize", toggle=True)
|
||||
row.prop(self, "clean_weights", toggle=True)
|
||||
row.prop(prefs, "auto_clean_weights", toggle=True)
|
||||
row.prop(tool_settings, "use_multipaint",
|
||||
text="Multi-Paint", toggle=True)
|
||||
row = layout.row()
|
||||
@ -171,6 +167,7 @@ class EASYWEIGHT_OT_wp_context_menu(bpy.types.Operator):
|
||||
active_brush = context.tool_settings.weight_paint.brush
|
||||
self.front_faces = active_brush.use_frontface
|
||||
self.falloff_shape = active_brush.falloff_shape
|
||||
self.accumulate = active_brush.use_accumulate
|
||||
if 'clean_weights' not in context.scene:
|
||||
context.scene['clean_weights'] = False
|
||||
self.clean_weights = context.scene['clean_weights']
|
||||
@ -183,55 +180,10 @@ class EASYWEIGHT_OT_wp_context_menu(bpy.types.Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class WeightCleaner:
|
||||
"""Run bpy.ops.object.vertex_group_clean on every depsgraph update while in weight paint mode (ie. every brush stroke)."""
|
||||
# Most of the code is simply responsible for avoiding infinite looping depsgraph updates.
|
||||
# Flag set by the user via the custom WP context menu.
|
||||
cleaner_active = False
|
||||
|
||||
# Flag set in post_depsgraph_update, to indicate to pre_depsgraph_update that the depsgraph update has indeed completed.
|
||||
can_clean = True
|
||||
# Flag set by pre_depsgraph_update to indicate to post_depsgraph_update that the cleanup operator is still running (in a different thread).
|
||||
cleaning_in_progress = False
|
||||
|
||||
@classmethod
|
||||
def clean_weights(cls, scene, depsgraph):
|
||||
if bpy.context.mode != 'PAINT_WEIGHT':
|
||||
return
|
||||
if not bpy.context or not hasattr(bpy.context, 'object') or not bpy.context.object:
|
||||
return
|
||||
if not cls.cleaner_active:
|
||||
return
|
||||
if cls.can_clean:
|
||||
cls.can_clean = False
|
||||
cls.cleaning_in_progress = True
|
||||
# This will trigger a depsgraph update, and therefore clean_weights, again.
|
||||
bpy.ops.object.vertex_group_clean(
|
||||
group_select_mode='ALL', limit=0.001)
|
||||
cls.cleaning_in_progress = False
|
||||
|
||||
@classmethod
|
||||
def reset_flag(cls, scene, depsgraph):
|
||||
if bpy.context.mode != 'PAINT_WEIGHT':
|
||||
return
|
||||
if not bpy.context or not hasattr(bpy.context, 'object') or not bpy.context.object:
|
||||
return
|
||||
if cls.cleaning_in_progress:
|
||||
return
|
||||
if not cls.cleaner_active:
|
||||
return
|
||||
cls.can_clean = True
|
||||
|
||||
|
||||
def draw_menu_entry(self, context):
|
||||
self.layout.operator(EASYWEIGHT_OT_wp_context_menu.bl_idname)
|
||||
|
||||
|
||||
@persistent
|
||||
def start_cleaner(scene, depsgraph):
|
||||
bpy.app.handlers.depsgraph_update_pre.append(WeightCleaner.clean_weights)
|
||||
bpy.app.handlers.depsgraph_update_post.append(WeightCleaner.reset_flag)
|
||||
|
||||
registry = [
|
||||
EASYWEIGHT_OT_wp_context_menu
|
||||
]
|
||||
@ -243,13 +195,10 @@ def register():
|
||||
description="Hide options that are less frequently used",
|
||||
default=False
|
||||
)
|
||||
start_cleaner(None, None)
|
||||
bpy.app.handlers.load_post.append(start_cleaner)
|
||||
|
||||
bpy.types.VIEW3D_MT_paint_weight.append(draw_menu_entry)
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.easyweight_minimal
|
||||
bpy.app.handlers.load_post.remove(start_cleaner)
|
||||
|
||||
bpy.types.VIEW3D_MT_paint_weight.remove(draw_menu_entry)
|
||||
|
Loading…
Reference in New Issue
Block a user