Can this Code be made Better - Join objects?

Hi,
In my addon, I have a button that I use to do the join function.
The code below works fine. However, it seems long and clunky.
Is there a better way to do this. I spent a couple of hours to get to this point.

Here is what the button is supposed to do in the @poll section of code…

It only enables the button if all the selected objects are the same, i.e all MESH or all CURVES.
If it detects that there are two different types it will not enable the button.

CODE THAT WORKS:

class SELJOIN_OT_Operator(bpy.types.Operator):
    bl_idname = "viewed3d.select_join"
    bl_label = "Join Selected Objects"
    bl_description = "Join Selected Objects"

    @classmethod
    def poll(cls, context):

        obj = context.active_object
        objs = context.selected_objects

        if len(objs) == 0: return False

            #selection_names = []
            strType = "none"
            boolFirst = False
            boolTF = False

            for objs in bpy.context.selected_objects:

              #gets the firs obj intance

                if boolFirst == False:
                    boolFirst = True
                    if obj.mode == "OBJECT":
                        if objs.type == "MESH":
                            strType = "MESH"
                        elif objs.type == "CURVE":
                            strType = "CURVE"
                        elif objs.type == "GPENCIL":
                            strType = "GPENCIL"
                        elif objs.type == "SURFACE":
                            strType = "SURFACE"
                        elif objs.type == "ARMATURE":
                            strType = "ARMATURE"
                        else:
                            print("no valid object selected")
                else:
                    
                   #checks if there is a match or not

                    if obj.mode == "OBJECT":
                        if objs.type == strType:
                            boolTF = True
                        else:
                            boolTF = False
                            break
            
            #if T/F, then return T/F

            if boolTF == True:
                return True
            else:
                return False

        return False

    def execute(self, context):
        bpy.ops.object.join()
        return {'FINISHED'}

Can this be done more effciently?
Thanks in advanced.

One or two points to make, your line if len(objs) == 0: return False is not good practice, it should be two lines for ease of comprehension by others, search “pep8” guidance and Blender Add-on guidance. Variable names should be snake case, not camel case. Yes it is a bit clunky, perhaps this might be better:

class SELJOIN_OT_Operator(bpy.types.Operator):
    bl_idname = "viewed3d.select_join"
    bl_label = "Join Selected Objects"
    bl_description = "Join Selected Objects"

    @classmethod
    def poll(cls, context):
        if len(context.view_layer.objects.selected) == 0:
            return False
        for obj in context.view_layer.objects.selected:
            if obj.type not in ["MESH", "CURVE", "GPENCIL", "SURFACE", "ARMATURE"]:
                return False
            if obj.type != context.active_object.type
                return False
        return True

I haven’t tested it, but you should try something along these lines. You should be testing against the active object, not the first one in the list of selected objects I think?

Cheers, Clock.

That partly works.
The only issue is that the button is enabled when just selecting on one legitimate object.
Can’t join a single object… has to be two or more.
Other than that… this is so much cleaner.

Now,I just need to add some code to check for more than 2 objects selected.

Thanks

Got it…

CODE THAT WORKS NOW…

@classmethod
    def poll(cls, context):
        if len(context.view_layer.objects.selected) < 2:
            return False
       for obj in context.view_layer.objects.selected:
            if obj.type not in ["MESH", "CURVE", "GPENCIL", "SURFACE", "ARMATURE"]:
                return False
            if obj.type != context.active_object.type:
                return False
        return True

Thanks for you help man!!

You’re welcome, however you don’t need these two lines in your code, they do nothing:

        obj = context.active_object
        objs = context.selected_objects

Cheers, Clock.

EDIT:

Watch your indents, I think one line is not lined up properly, but that may be how you pasted here. Which Code Editor do you use, I use Atom, it’s free and brilliant! Don’t use something like Text Editor, it cannot distinguish some quotes and is not easy to read, this is Atom:

Yeah, forgot to remove those lines
just pasted from VSCode (had to edit afterwards
Thanks

1 Like