0
$\begingroup$

This is my first time trying to code anything so I apologize in advance. I'm creating an addon that transfers bone names. Currently I've created 2 buttons that retrieve all the bone names in an armature (one for source, one for target), and also tells me how many bones are in said armature. I intend to create dictionaries with the same amount as the armature with the largest amount of bones. In order to do this, the buttons I mentioned earlier also have a value that stores the length of the bone list.

source_number = len(source_armature_bone_list)

target_number = len(target_armature_bone_list)

Within another operator button, I wish to generate x amount of dictionaries. This isn't the important part I request help with. The issue is that I want to use my source_num and target_num values (sorry I don't remember the terminology) in another section (from one operator to another). It's important to note, depending on the bone count of the source/target, the longer the list will be (meaning it will have a higher len in some cases). I wish to use these "constantly changing values" with PropertyGroups so that once i obtain the bone list length, I can continue to use them elsewhere (in other operators) I tried to register PropertyGroups to do so, but it's not working and I'm sure i'm doing something wrong.

Here is what my custom properties looks like (not sure if StringProperty is what I want to use)

class CustomProperties(bpy.types.PropertyGroup):
    source_num : bpy.props.StringProperty()
    target_num : bpy.props.StringProperty()

Here is what my registered items look like

classes = [CustomProperties, Devola_PT_Panel, TEST_OT_Button, OPEN_OT_SourceArmature, OPEN_OT_TargetArmature, CREATE_OT_Dictionary]

def register():
    for cls in classes:
        bpy.utils.register_class(cls)
        
        bpy.types.Scene.custom_properties = bpy.props.PointerProperty(type= CustomProperties)

def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
        del bpy.types.Scene.custom_properties

And here is what my other operators look like that try to change what source_number and target_number are (example for target_number is the same as source_number). Testing to see if the bone list prints in the first place works just fine within this operator. It's just I can't seem to save the value to the PropertyGroup like this.

class OPEN_OT_TargetArmature(bpy.types.Operator):
    """Generate a bone list based on the target armature"""
    bl_label = "Generate List"
    bl_idname = "open.targetarmature"
    
    def execute(self, context):
        
        scene = context.scene
        customproperties = scene.custom_properties
        target_number = customproperties.target_num
    
    
        currentobject = bpy.context.selected_objects
        for selectedobject in currentobject:
            if selectedobject.type != "ARMATURE":
                continue
                
            target_armature_bone_list = []
            
            
            for bone in selectedobject.data.bones:
                if bone not in target_armature_bone_list:
                    target_armature_bone_list.append(bone)
            
            target_number = len(target_armature_bone_list)

            print("\nNumber of bones in target armature:" , target_number)
            print("\nBones in target armature "+ selectedobject.name + ":")
            for bone in target_armature_bone_list:
                print(bone.name)
                    
        return {'FINISHED'}

Using this operator to create the dictionary.

class CREATE_OT_Dictionary(bpy.types.Operator):
    bl_label = "Create Bone Dictionary"
    bl_idname = "create.bonedictionary"
    
    def execute(self, context):
        
        scene = context.scene
        customproperties = scene.custom_properties
        
        source_number = customproperties.source_num
        target_number = customproperties.target_num
        
        if source_number > target_number:
            dictionary_length = source_number
        else:
            dictionary_length = target_number
        print(dictionary_length)

Could anyone point out what I did wrong/I'm missing. When trying to at least print the custom property group(s), nothing shows up in the system console. I made a little test button like so, but once again nothing. Testing something like print("hello") works.

class TEST_OT_Button(bpy.types.Operator):
    bl_label = "test"
    bl_idname = "test.button"
    
    def execute(self, context):    
        
        scene = context.scene
        customproperties = scene.custom_properties        
        source_number = customproperties.source_num
        
        print(source_number)
        
                
        return {'FINISHED'}
$\endgroup$

1 Answer 1

1
$\begingroup$

From what I gathered it's more a python question than really a blender question, but you'll need to grasp a few concepts that are specific to the Blender Python API.

If you're going to retrieve a len, you'll get an int object, so you can use bpy.props.IntProperty() instead of StringProperty. This will save you from having to cast from and to str and int every time you do calculations with it.

You do assign the len to an object, but not to the custom property. When you use target_number = customproperties.target_num, you create a new object of type int that loses all relationship to the PropertyGroup. If you want to assign the actual property that's tied to the scene object, you need to assign it directly (at the end of your method) : customproperties.target_num = target_number.

For readability it's advised to use Snake Case in python. At least adding an underscode between different words of a variable helps.

Use Python builtin functions (like max). This :

    scene = context.scene
    customproperties = scene.custom_properties
    
    source_number = customproperties.source_num
    target_number = customproperties.target_num
    
    if source_number > target_number:
        dictionary_length = source_number
    else:
        dictionary_length = target_number

Can be reduced to this :

    custom_properties = context.scene.custom_properties
    dictionary_length = max(custom_properties.source_num, custom_properties.target_num)
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .