Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
waylow committed Apr 10, 2024
2 parents d10525b + 6090dfb commit f70bf15
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 127 deletions.
45 changes: 22 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,19 @@ First select the mesh shape you want to use (object mode), then shift select the
#### Hide/Show Collection:
As the name would suggest this will toggle the visibility of the widget collection.
<b>Note:</b>
This will only toggle the visibility of the designated widget collection (set in the preferences). If the rig uses a

This will only toggle the visibility of the designated widget collection (set in the preferences).


### To Do:
- complete the documentation with images to this readme file
- [Enhancement] Doesn't work well with Rigify naming scheme (solve this)
- [Feature] Let the user change the widget suffix to a prefix for a different naming convention
- [Feature] Extract and edit a widget? Say you're editing a rig that doesn't have mesh objects for the widgets in the file (only mesh data).
Maybe there can be a way of extracting them and making them real objects.
- [Bug] The match Bone Transforms does not work well when the bone scale is not at 1.0
- [Enchantment] Rewrite the mirrorShape function so it will work when you have the mesh shape selected (not just the bone in pose mode)
-import/export library of shapes.
-redesign to include image of the shapes


##v2.0 Release Notes:
- changed the default name of the n panel to 'Rigging' rather than 'Rig Tools'
- [fixed Bug] if the bone was using an override transform, it will use this bone mirror the widget to rather than just taking that bone's matrix
- [Enhancement] Added setting in the user preferences so it can optionally use the Rigify naming convention for widget creation (collection and widget names).

## v1.9 Release Notes:
- [Fix] widget collection no longer needs to be in the master scene for the addon to find it.
Expand All @@ -124,6 +124,20 @@ Maybe there can be a way of extracting them and making them real objects.
* Functionality change: I rewrote the way to add the selected object as a widget without having to read and write to a text file
* Fix: If collection is 'excluded' in the outliner it now re-enables it.

## v1.7 Release Notes
* Fix: Allow rename of Addons-Folder
* Fix: Fixed the symmetrize error if the .L or the .R didn't have a widget
* Fix: Symmetrize Operator caused Error when clicking in Object mode
* Fix: Return to Armature: Didn't unselect widget-object before returning to armature
* Fix: Edit Widget: Show only if active bone has a widget
* Feature: Widgets renamed: Gear --> Gear_complex, Root --> Root_1
* Feature: New Widgets: 3 Axes, 6 Axes, Arrow_double_sided, Arrow_head, Chest, Clavicle, Eyes_Target, FK_Limb, Gear_simple,
Roll, Root_2, Torso
* Feature: New Property: Panel Category
* Feature: New Property: Bone Widget symmetry suffix
* Feature: Add selected Mesh as widget-shape
* Feature: Added Logger

### Widget Edits (from v1.7)
* Resized '3 Axes' widget to better match a default size of 1 blender unit (and sits over the 6 axes nicely)
* Renamed 'FK_Limb' to 'FK Limb 1'
Expand All @@ -150,21 +164,6 @@ Maybe there can be a way of extracting them and making them real objects.
* Flipped "Arrow Head" and renamed to "Pyramid"


## v1.7 Release Notes
* Fix: Allow rename of Addons-Folder
* Fix: Fixed the symmetrize error if the .L or the .R didn't have a widget
* Fix: Symmetrize Operator caused Error when clicking in Object mode
* Fix: Return to Armature: Didn't unselect widget-object before returning to armature
* Fix: Edit Widget: Show only if active bone has a widget
* Feature: Widgets renamed: Gear --> Gear_complex, Root --> Root_1
* Feature: New Widgets: 3 Axes, 6 Axes, Arrow_double_sided, Arrow_head, Chest, Clavicle, Eyes_Target, FK_Limb, Gear_simple,
Roll, Root_2, Torso
* Feature: New Property: Panel Category
* Feature: New Property: Bone Widget symmetry suffix
* Feature: Add selected Mesh as widget-shape
* Feature: Added Logger


## v1.6 Release Notes
* Fixed the "DELETE UNUSED WIDGETS" function (was crashing because the context was wrong)

Expand Down
12 changes: 8 additions & 4 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
bl_info = {
"name": "Bone Widget",
"author": "Manuel Rais, Christophe Seux, Bassam Kurdali, Wayne Dixon, Blender Defender, Max Nadolny",
"version": (1, 9),
"blender": (2, 93, 0),
"version": (2, 0),
"blender": (3, 4, 0),
"location": "UI > Properties Panel",
"description": "Easily Create Bone Widgets",
"warning": "",
Expand Down Expand Up @@ -73,23 +73,27 @@ def check_version(major, minor, _):
def register():
operators.register()
menus.register()

bl_class_registry.BlClassRegistry.register()

# Apply preferences of the panel location.
context = bpy.context
pref = get_user_preferences(context).addons[__package__].preferences
# Only default panel location is available in < 2.80
if check_version(2, 80, 0) < 0:
pref.panel_category = "Rig Tools"
pref.panel_category = "Rigging"
prefs.BoneWidgetPreferences.panel_category_update_fn(pref, context)

#panels.register()

def unregister():
operators.unregister()
menus.unregister()

# TODO: Unregister by BlClassRegistry
bl_class_registry.BlClassRegistry.unregister()

#panels.unregister()


if __name__ == "__main__":
register()
81 changes: 58 additions & 23 deletions functions/mainFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@


def getCollection(context):
bw_collection_name = context.preferences.addons[__package__].preferences.bonewidget_collection_name
#collection = context.scene.collection.children.get(bw_collection_name)
#check user preferences for the name of the collection
if not context.preferences.addons[__package__].preferences.use_rigify_defaults:
bw_collection_name = context.preferences.addons[__package__].preferences.bonewidget_collection_name
else:
bw_collection_name = "WGTS_" + context.active_object.name

collection = recurLayerCollection(context.scene.collection, bw_collection_name)
if collection: # if it already exists
return collection
Expand Down Expand Up @@ -92,11 +96,12 @@ def fromWidgetFindBone(widget):
def createWidget(bone, widget, relative, size, scale, slide, rotation, collection):
C = bpy.context
D = bpy.data
bw_widget_prefix = C.preferences.addons[__package__].preferences.widget_prefix

# if bone.custom_shape_transform:
# matrixBone = bone.custom_shape_transform
# else:
if not C.preferences.addons[__package__].preferences.use_rigify_defaults:
bw_widget_prefix = C.preferences.addons[__package__].preferences.widget_prefix
else:
bw_widget_prefix = "WGT-" + C.active_object.name + "_"

matrixBone = bone

if bone.custom_shape:
Expand Down Expand Up @@ -149,17 +154,23 @@ def createWidget(bone, widget, relative, size, scale, slide, rotation, collectio
def symmetrizeWidget(bone, collection):
C = bpy.context
D = bpy.data
bw_widget_prefix = C.preferences.addons[__package__].preferences.widget_prefix

if not C.preferences.addons[__package__].preferences.use_rigify_defaults:
bw_widget_prefix = C.preferences.addons[__package__].preferences.widget_prefix
rigify_object_name = ''
else:
bw_widget_prefix = "WGT-"
rigify_object_name = C.active_object.name + "_"

widget = bone.custom_shape
if findMirrorObject(bone) is not None:
if findMirrorObject(bone).custom_shape_transform:
mirrorBone = findMirrorObject(bone).custom_shape_transform
else:
mirrorBone = findMirrorObject(bone)

if findMirrorObject(bone):
mirrorBone = findMirrorObject(bone)

mirrorWidget = mirrorBone.custom_shape
if mirrorWidget:
print(mirrorBone)
print(mirrorWidget)
if mirrorWidget is not None:
if mirrorWidget != widget:
mirrorWidget.name = mirrorWidget.name + "_old"
mirrorWidget.data.name = mirrorWidget.data.name + "_old"
Expand All @@ -174,15 +185,20 @@ def symmetrizeWidget(bone, collection):
newObject = widget.copy()
newObject.data = newData
newData.update()
newObject.name = bw_widget_prefix + mirrorBone.name
newObject.name = bw_widget_prefix + rigify_object_name + findMirrorObject(bone).name
D.collections[collection.name].objects.link(newObject)

#if there is a override transform, use that bone matrix in the next step
if findMirrorObject(bone).custom_shape_transform:
mirrorBone = findMirrorObject(bone).custom_shape_transform

newObject.matrix_local = mirrorBone.bone.matrix_local
newObject.scale = [mirrorBone.bone.length, mirrorBone.bone.length, mirrorBone.bone.length]

layer = bpy.context.view_layer
layer.update()

mirrorBone.custom_shape = newObject
findMirrorObject(bone).custom_shape = newObject
mirrorBone.bone.show_wire = True

else:
Expand Down Expand Up @@ -210,7 +226,11 @@ def deleteUnusedWidgets():
C = bpy.context
D = bpy.data

bw_collection_name = C.preferences.addons[__package__].preferences.bonewidget_collection_name
if not C.preferences.addons[__package__].preferences.use_rigify_defaults:
bw_collection_name = C.preferences.addons[__package__].preferences.bonewidget_collection_name
else:
bw_collection_name = 'WGTS_' + C.active_object.name

collection = recurLayerCollection(C.scene.collection, bw_collection_name)
widgetList = []

Expand All @@ -227,7 +247,8 @@ def deleteUnusedWidgets():
# jump into object mode
bpy.ops.object.mode_set(mode='OBJECT')
# delete unwanted widgets
bpy.ops.object.delete({"selected_objects": unwantedList})
for ob in unwantedList:
bpy.data.objects.remove(bpy.data.objects[ob.name], do_unlink=True)
# jump back to current mode
bpy.ops.object.mode_set(mode=mode)

Expand Down Expand Up @@ -357,8 +378,12 @@ def resyncWidgetNames():
C = bpy.context
D = bpy.data

bw_collection_name = C.preferences.addons[__package__].preferences.bonewidget_collection_name
bw_widget_prefix = C.preferences.addons[__package__].preferences.widget_prefix
if not C.preferences.addons[__package__].preferences.use_rigify_defaults:
bw_collection_name = C.preferences.addons[__package__].preferences.bonewidget_collection_name
bw_widget_prefix = C.preferences.addons[__package__].preferences.widget_prefix
else:
bw_collection_name = 'WGTS_' + C.active_object.name
bw_widget_prefix = 'WGT-' + C.active_object.name + '_'

widgetsAndBones = {}

Expand All @@ -384,12 +409,22 @@ def clearBoneWidgets():


def addObjectAsWidget(context, collection):
sel = bpy.context.selected_objects
#bw_collection = context.preferences.addons[__package__].preferences.bonewidget_collection_name
selected_objects = bpy.context.selected_objects

if len(selected_objects) != 2:
print('Only a widget object and the pose bone(s)')
return{'FINISHED'}

allowed_object_types = ['MESH','CURVE']

widget_object = None

for ob in selected_objects:
if ob.type in allowed_object_types:
widget_object = ob

if sel[1].type == 'MESH':
if widget_object:
active_bone = context.active_pose_bone
widget_object = sel[1]

# deal with any existing shape
if active_bone.custom_shape:
Expand Down
67 changes: 5 additions & 62 deletions operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,16 +219,15 @@ def poll(cls, context):
return (context.object and context.object.type == 'ARMATURE' and context.object.mode == 'POSE')

def execute(self, context):
bw_collection_name = context.preferences.addons[__package__].preferences.bonewidget_collection_name
bw_collection = recurLayerCollection(bpy.context.view_layer.layer_collection, bw_collection_name)
if not context.preferences.addons[__package__].preferences.use_rigify_defaults:
bw_collection_name = context.preferences.addons[__package__].preferences.bonewidget_collection_name
else:
bw_collection_name = 'WGTS_' + context.active_object.name

#bw_collection = context.scene.collection.children.get(bw_collection_name)
bw_collection = recurLayerCollection(bpy.context.view_layer.layer_collection, bw_collection_name)
bw_collection.hide_viewport = not bw_collection.hide_viewport
#need to recursivly search for the view_layer
bw_collection.exclude = False
# collection = getViewLayerCollection(context)
# collection.hide_viewport = not collection.hide_viewport
# collection.exclude = False
return {'FINISHED'}


Expand Down Expand Up @@ -273,62 +272,6 @@ def execute(self, context):
resyncWidgetNames()
return {'FINISHED'}

'''
class BONEWIDGET_OT_selectObject(bpy.types.Operator):
"""Select object as widget for selected bone"""
bl_idname = "bonewidget.select_object"
bl_label = "Select Object as Widget"
@classmethod
def poll(cls, context):
return (context.object and context.object.type == 'ARMATURE' and context.object.mode == 'POSE')
def active_armature(self, context):
ob = context.object
ob = str(ob).split('"')
ob = ob[1]
return ob
def active_bone(self, context):
ob = context.active_bone
ob = str(ob).split('"')
ob = ob[1]
return ob
def execute(self, context):
active_armature = self.active_armature(context)
active_bone = self.active_bone(context)
writeTemp(active_armature, active_bone)
logOperation("info", 'Write armature name: "{}" and bone name: "{}" to file temp.txt'.format(active_armature, active_bone))
selectObject()
return {'FINISHED'}
class BONEWIDGET_OT_confirmWidget(bpy.types.Operator):
"""Set selected object as widget for selected bone"""
bl_idname = "bonewidget.confirm_widget"
bl_label = "Confirm selected Object as widget shape"
@classmethod
def poll(cls, context):
return (context.object and context.object.type == 'MESH' and context.object.mode == 'OBJECT')
def execute(self, context):
arm_bone = readTemp().split(",")
active_armature = arm_bone[0]
active_bone = arm_bone[1]
active_bone = bpy.data.objects[active_armature].pose.bones[active_bone]
active_armature = bpy.data.objects[active_armature]
print(active_armature, active_bone)
cW = confirmWidget(context, active_bone, active_armature)
logOperation("info", 'Duplicate Object "{}" and set duplicate as custom shape for Bone "{}" in Armature "{}".'.format(cW, active_bone, active_armature))
return {'FINISHED'}
'''

class BONEWIDGET_OT_addObjectAsWidget(bpy.types.Operator):
"""Add selected object as widget for active bone."""
Expand Down
Loading

0 comments on commit f70bf15

Please sign in to comment.