is it possible to set all the custom properties of a bone to 0?

Hello!, i´ve been looking the entire day for a solution for this :P, so gavsjdfjahsk, perhaps someone here can help me,

i have a lot of custom properties that are the controllers of shapekeys, but as i have the shapekeys driven, the “clear weights for all shape keys” button ain´t useful, so my question is is there a way to make it useful??? or maybe set another custom property to clear all the values??

can anybody help me please, i´m unable to find a solution for this on my own, please (:

Uncheck Deform from shape key bone property. Select the bone in Pose mode, Bone button, under there you will find Deform check box. When set not to deform, it will not weigh anything when you Parent with Auto Weight.

?.? thank you for your input :), but i´m afraid that wasn´t my question

perhaps i didn´t make myself clear, i was asking how to set these custom properties values to 0:


Something like this.

Select your armature, then run the script.



import bpy

context = bpy.context


armature = context.object

for bone in armature.pose.bones:
    for prop, value  in bone.items():
        #print(prop, value, type(value))
        if type(value) is float:
            print('pose.bones["%s"]["%s"] =  %.1f' % (bone.name, prop, value))
            bone[prop] = 0.0

you’ll need to check for other types like int etc.

Not as elegant as batFINGER’s, more of a brute force way:

import bpy

bone_dict = {
    "Hand_L": "rot",
    "Hand_R": "rot",
    "IK_Foot_L": "ik",
    "IK_Foot_R": "ik"}

pose_bones = bpy.context.active_object.pose.bones
   
for key in bone_dict:    
    pose_bones[key][bone_dict[key]] = 0.0

bone_dict is a python dictionary (type of variable) that associates the names of bones with their custom props. To get this to work in your case, you should change bone_dict so it reads like this:

bone_dict = {
    "<bone name>": "<custom property name>",
    "<bone name>": "<custom property name>",
    ....}

and so on, replacing <bone name> with the name of the bone and <custom property name> with the name of the custom property. Run the script when you want to reset the values with the armature selected.

With a little bit more code, you could create a nice button for the UI…

Randy

@Randy pay to have a list of properties per bone, in my prev post I put in the type checking but thought checking against a defined list of prop names could be the go.


import bpy

bone_dict = {
    "hips": ["rot","loc","boo"],
    "hand.R": ["ik"],
    "hand.L": ["ik"]}

pose_bones = bpy.context.active_object.pose.bones
   
for key in bone_dict:    
    bone = pose_bones[key]
    props = bone_dict[key]
    print(props)
    for prop in props:
        bone[prop] = 0.0

& after doing that it made me think that a dictionary for the props with their default values may be more useful.


import bpy

bone_dict = {
    "hips": {"rot":1, "bot":0},
    "hand.R": {"ik":0},
    "hand.L": {"ik":0}
    }

pose_bones = bpy.context.active_object.pose.bones
   
for key in bone_dict:    
    bone = pose_bones[key]
    props = bone_dict[key]
    print(props)
    for prop, value in props.items():
        bone[prop] = value

@ batFINGER: indeed, great idea about default values.

When I first started thinking about this, I started by scripting the UI first, then I realized I had no idea how to set custom props. Once I figured out that, I just posted that bit of code. Seems foolish to not share the entire thing.


import bpy

bone_dict = {
    "Hand_L": "rot",
    "Hand_R": "rot",
    "IK_Foot_L": "ik",
    "IK_Foot_R": "ik"}
    
    
class reset_properties(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_label = "Reset Custom Properties"
    
    @classmethod
    def poll(self, context):
        try:
            obj = context.active_object
            mode = context.mode
            return (obj.name == "Joe_Rig" and mode == "POSE")
        except AttributeError:
            return 0
        
    def draw(self, context):
        layout = self.layout
        row = layout.row()
        row.operator("resetprops.op")
         
         
class reset_custom_props(bpy.types.Operator):
    bl_idname = "resetprops.op"
    bl_label = "Reset Custom Properties"
    bl_description = "Resets all bone's custom properties to 0"
    
    def execute(self, context):
        pose_bones = bpy.context.active_object.pose.bones
   
        for key in bone_dict:    
            pose_bones[key][bone_dict[key]] = 0.0        
    
        return {"FINISHED"}
    
    
def register():
    bpy.utils.register_class(reset_properties)
    bpy.utils.register_class(reset_custom_props)    
    

def unregister():
    bpy.utils.unregister_class(reset_properties)
    bpy.utils.unregister_class(reset_custom_props)    
    
register() 

Gives a nice UI like this:


Damn, allowed myself to get sidetracked again…:rolleyes:

Randy

wow! this is way beyond my understanding :P, thank you both, i´ll do my best to understand what your answers are, thank you again (:

YaY! thank you both!
i manage to get it to work (:

btw a little footnote that gave me headaches: to use this script one also must adress the object, so “Joe_Rig” must be changes to the name of the armature,

, and a little request, if you could, please, can you incorporate a command at the end
to update dependencies?, because after i hit the “Reset Custom properties” lovely
button i don´t see any change, i have to move another bone to see the effect of
the script

of course, only if that is something easy to do

thank you again (:

Greetings from Chile!

Greetings from Oz… chilly in chile? is here.

Put together this from both our concepts. The scene.update() call should fix your dependencies.
Added a menu to choose reset type:

ALL sets all float type properties on the bones of the rig to zero.
SELECTED sets all float type properties on the selected bones to zero.
DICT sets the values to the defaults you have set up in the bone dictionary

cheers.


import bpy
from bpy.props import EnumProperty
    
# set up a bone / prop dictionary with default values
bone_dict = {
    "hips": {"rot":1.00, "bot":0},
    "hand.R": {"ik":0},
    "hand.L": {"ik":0}
    }


class reset_properties(bpy.types.Panel):
    bl_space_type = 'VIEW_3D' # 'PROPERTIES'
    bl_region_type = 'UI' # 'WINDOW'
    #bl_context = "bone"
    bl_label = "Reset Custom Properties"
    
    @classmethod
    def poll(self, context):  
        object = context.object
        
        if object is not None:
            return object.type == 'ARMATURE' and object.mode == 'POSE'
        return False
        
    def draw(self, context):
        rig = context.object.data        
        layout = self.layout

        row = layout.row()
        row.prop(rig, "resetType", expand=True)
        row = layout.row()
        row.operator("resetprops.op")
        if rig.resetType == 'SELECTED':
            row.enabled = len(context.selected_pose_bones) &gt; 0    
             
         
class reset_custom_props(bpy.types.Operator):
    bl_idname = "resetprops.op"
    bl_label = "Reset Custom Properties"
    bl_description = "Resets all bone's custom properties to 0"
    
    def execute(self, context):
        
        scene = context.scene
        arm = context.object
        rig = arm.data
        
        if rig.resetType == 'ALL':
            for bone in arm.pose.bones:
                for prop, value  in bone.items():
                    #print(prop, value, type(value))
                    if type(value) is float:
                        bone[prop] = 0.0
                    elif type(value) is int:
                        bone[prop] = 0
        elif rig.resetType == 'SELECTED':
            for bone in context.selected_pose_bones:
                for prop, value  in bone.items():
                    #print(prop, value, type(value))
                    if type(value) is float:
                        bone[prop] = 0.0
                    elif type(value) is int:
                        bone[prop] = 0
        elif rig.resetType == 'DICT':
            for key in bone_dict:    
                bone = arm.pose.bones.get(key)
                if bone is None:
                    print("Bone %s not in %s" % (key, arm.name))
                    continue
                props = bone_dict[key]
                print(props)
                for prop, value in props.items():
                    bone[prop] = value  
                                                  
        scene.update()
        #frame_set seems to update the poses
        frame = scene.frame_current
        scene.frame_set(frame)
        return {"FINISHED"}
    
 
def initProps():
    bpy.types.Armature.resetType = EnumProperty(items=(
            ("ALL", "ALL", "Reset all bone props to zero"),
            ("SELECTED", "SELECTED", "Reset on Selected Bones"),
            ("DICT", "DICT", "Use bone Dict")
            ),
            name="Reset Bone Props",
            default="ALL",
            description="Reset Bone Properties",
            #update=setcontextspeakerENUM,
            options={'HIDDEN'}
            )


def register():
    initProps()
    try:
        
        f = bpy.types.reset_properties.draw
        bpy.types.BONE_PT_custom_props.remove(f)
    except:
        pass
    
    bpy.utils.register_class(reset_properties)
    f = bpy.types.reset_properties.draw
    bpy.types.BONE_PT_custom_props.prepend(f)
    
    bpy.utils.register_class(reset_custom_props)    
    

def unregister():
    bpy.utils.unregister_class(reset_properties)
    bpy.utils.unregister_class(reset_custom_props)    
    
register()

Prepended the panel to the custom props of the bone panel as well, where would you like it to be.

@Randy
Noticed in your code you quite often use bpy.context…
context is passed to the operator/panel etc, . Don’t think it makes any difference with how it works tho. I often put the line context = bpy.context at the start of my test scripts and then cut and paste later, to avoid doing this myself.

wow!, the concept is getting cooler and cooler :D!!

but i´m getting this error while trying to run the newest script:


am i doing something wrong?

Whoops,

fixed. Updated in previous post.

The awesomness!!! is working beautifully now, this is almost an addon by now :smiley: thank you both so much!!! i still have to move a bone to update the scene, but who cares? :slight_smile: this is way beyond what i was hoping for an answer, actually at first i thought that i was going to have to write an scripted expression for each custom property calling a new var, D: but no (:

Thank you!!!

Ok … looks like setting the frame updates the dependencies, from a very quick test using a prop in a driver expression.

Updated again in previous post.

((((((((: works perfectly now

btw i think you should post the code on the “Released scripts and themes” category, i think this thread is way too small for the wonderfull script (:

thank you again (:

well, i did this on gimp, just to explore the concept a bit further, (because i´m extremly happy with the script current status :), but, just to improve the gui, here is a suggestion:


(the dict has layers with names and a way to select the active layers to be reseted, just like the rigify layer names

and the edit property has a way to choose the dict layer to where that custom property will be in, and a slider to set the dict value to be reseted on)

Here is a script that moves each of your bones into a layer based on your naming convention… eg 0.jaw.foo foo will move that bone to layer 0. Not sure how helpful that is after another look at screen shot.


import bpy
import re

context = bpy.context

scene = context.scene
arm = context.object
rig = arm.data

for bone in arm.pose.bones:
    for prop, value  in bone.items():
        #print(prop, value, type(value))
        m = re.match(r"^(\d)",prop)
        if m is not None:
            print(m.group())
            print("Match %s" % prop)
            i = int(m.group())
            layers = [False] * 32
            rig.bones[bone.name].layers[i] = True

Here is the part of the rigify UI that concerns bone layers



import bpy
     
class RigLayers(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_label = "Rig Layers"
    bl_idname = "SOME RIG ID"

    @classmethod
    def poll(self, context):  
        object = context.object
        
        if object is not None:
            return object.type == 'ARMATURE' and object.mode == 'POSE'
        return False
    
    def draw(self, context):
        layout = self.layout
        col = layout.column()

        row = col.row()
        row.prop(context.active_object.data, 'layers', index=2, toggle=True, text='Head')

        row = col.row()
        row.prop(context.active_object.data, 'layers', index=0, toggle=True, text='JAW')

        row = col.row()
        row.prop(context.active_object.data, 'layers', index=4, toggle=True, text='Fingers')
        row.prop(context.active_object.data, 'layers', index=5, toggle=True, text='(Tweak)')

        row = col.row()
        row.prop(context.active_object.data, 'layers', index=6, toggle=True, text='Arm.L (FK)')
        row.prop(context.active_object.data, 'layers', index=8, toggle=True, text='Arm.R (FK)')

        row = col.row()
        row.prop(context.active_object.data, 'layers', index=7, toggle=True, text='Arm.L (IK)')
        row.prop(context.active_object.data, 'layers', index=9, toggle=True, text='Arm.R (IK)')

        row = col.row()
        row.prop(context.active_object.data, 'layers', index=10, toggle=True, text='Leg.L (FK)')
        row.prop(context.active_object.data, 'layers', index=12, toggle=True, text='Leg.R (FK)')

        row = col.row()
        row.prop(context.active_object.data, 'layers', index=11, toggle=True, text='Leg.L (IK)')
        row.prop(context.active_object.data, 'layers', index=13, toggle=True, text='Leg.R (IK)')

        row = col.row()
        row.separator()
        row = col.row()
        row.separator()

        row = col.row()
        row.prop(context.active_object.data, 'layers', index=28, toggle=True, text='Root')


def register():
    bpy.utils.register_class(RigLayers)

def unregister():
    bpy.utils.unregister_class(RigLayers)

register()

notice the prop i changed to “JAW” has index 0… you will need to change the others appropriately. You can do this manually by selecting the bones you want on different layers and selecting that bone layer/s

actually for me i´m actually done as the functionality i need with the “selected” button :slight_smile: (thanks to you :),

but as for what i was suggesting for deeper improvement, i used the rigify example just as a gui example (not to be linked), because i think the rigify layers gui it is better resolved than the 3d view layers (and can be named), so to be able to select a custom property layer to be reseted, with the Dict button, but knowing what you are reseting

also i think it could be something cool to have, to select a layer for the custom property from the edit panel and select the value on wich it will be reseted with a slider

of course you can do whatever you want, and leave the script as it is, because it is good enough i think :), but it was just a suggestion