0
$\begingroup$

I have a script that is runing fine but I think there is a way to make it more efficient and is by using a list of items, the problem I have is that I'm not sure if I can use the list to perform some operations depending on the items order or names from the list. In this case I would like to know if I could use the same operator for each item independently or I just have to make a operator for each item (which I think is not efficient at all to write it), since each operator points to a different string.

As you can see in the code, between the lines 122 and 236 there are 3 operators almost exactly the same but changing the string pointer and the class name, imagine now if I have like 20 items do I have to make 20 operators? So I think that having a list I could just add a new item without the need of creating another operator. Hope all this makes sense. Bear with me, I'm a noob on this coding thingy :)

import bpy

#my_list_that_want_to_use = [
#    {
#        'name': 'WINDOWS'
#    },
#    {
#        'name': 'DOORS'
#    },
#    {
#        'name': 'WALLS'
#    },
#]

class MyProperties(bpy.types.PropertyGroup):
    my_string_windows : bpy.props.StringProperty(name = "Windows", default ="WINDOWS")
    my_string_doors : bpy.props.StringProperty(name = "Doors", default ="DOORS")
    my_string_walls : bpy.props.StringProperty(name = "Walls", default ="WALLS")


class SelectByNameOperator_windows(bpy.types.Operator):
    """Select objects by name"""
    bl_idname = "object.selected_by_name_operator_windows"
    bl_label = "Select by Name"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        bpy.ops.object.select_all(action='DESELECT')
        bpy.data.objects['Light'].select_set(True)
        bpy.context.view_layer.objects.active = bpy.context.selected_objects[0]

        return {'FINISHED'} 

class SelectByNameOperator_doors(bpy.types.Operator):
    """Select objects by name"""
    bl_idname = "object.selected_by_name_operator_doors"
    bl_label = "Select by Name"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        bpy.ops.object.select_all(action='DESELECT')
        bpy.data.objects['Camera'].select_set(True)
        bpy.context.view_layer.objects.active = bpy.context.selected_objects[0]

        return {'FINISHED'} 

class SelectByNameOperator_walls(bpy.types.Operator):
    """Select objects by name"""
    bl_idname = "object.selected_by_name_operator_walls"
    bl_label = "Select by Name"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        bpy.ops.object.select_all(action='DESELECT')
        bpy.data.objects['Cube'].select_set(True)
        bpy.context.view_layer.objects.active = bpy.context.selected_objects[0]

        return {'FINISHED'} 

class ADDONNAME_OT_my_op_windows(bpy.types.Operator):
    bl_label = "Sort"
    bl_idname = "addonname.myop_operator_windows"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        scene = context.scene
        mytool = scene.my_tool
        
        collectionFound = False

        for myCol in bpy.data.collections:
            #print(myCol.name)
            if myCol.name == mytool.my_string_windows:
                collectionFound = True
                #print ("Collection found in scene")
                break
            
        # Creates a new collection                
        if collectionFound == False:
            myCol = bpy.data.collections.new(mytool.my_string_windows)
            bpy.context.scene.collection.children.link(myCol) 

        # Set the new collection as active
        def recurLayerCollection(layerColl, collName):
            found = None
            if (layerColl.name == collName):
                return layerColl
            for layer in layerColl.children:
                found = recurLayerCollection(layer, collName)
                if found:
                    return found

        layer_collection = bpy.context.view_layer.layer_collection
        layerColl = recurLayerCollection(layer_collection, mytool.my_string_windows)
        bpy.context.view_layer.active_layer_collection = layerColl



        # MOVE SELECTED OBJECTS TO ANOTHER COLLECTION ONLY
        objs = bpy.context.selected_objects # List of object references

        coll_target = bpy.context.scene.collection.children.get(mytool.my_string_windows)     # Set target collection to a known collection 
        coll_target = bpy.context.collection                                           # Set target collection based on the collection in context (selected) 

        if coll_target and objs:                                                       # If target found and object list not empty

            for ob in objs:                                                            # Loop through all objects
                for coll in ob.users_collection:                                       # Loop through all collections the obj is linked to
                    coll.objects.unlink(ob)                                            # Unlink the object

                coll_target.objects.link(ob)                                           # Link each object to the target collection

        bpy.ops.object.select_all(action="DESELECT")


        return {'FINISHED'}


class ADDONNAME_OT_my_op_doors(bpy.types.Operator):
    bl_label = "Sort"
    bl_idname = "addonname.myop_operator_doors"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        scene = context.scene
        mytool = scene.my_tool
        
        collectionFound = False

        for myCol in bpy.data.collections:
            #print(myCol.name)
            if myCol.name == mytool.my_string_doors:
                collectionFound = True
                #print ("Collection found in scene")
                break
            
        # Creates a new collection                
        if collectionFound == False:
            myCol = bpy.data.collections.new(mytool.my_string_doors)
            bpy.context.scene.collection.children.link(myCol) 

        # Set the new collection as active
        def recurLayerCollection(layerColl, collName):
            found = None
            if (layerColl.name == collName):
                return layerColl
            for layer in layerColl.children:
                found = recurLayerCollection(layer, collName)
                if found:
                    return found

        layer_collection = bpy.context.view_layer.layer_collection
        layerColl = recurLayerCollection(layer_collection, mytool.my_string_doors)
        bpy.context.view_layer.active_layer_collection = layerColl



        # MOVE SELECTED OBJECTS TO ANOTHER COLLECTION ONLY
        objs = bpy.context.selected_objects # List of object references

        coll_target = bpy.context.scene.collection.children.get(mytool.my_string_doors)     # Set target collection to a known collection 
        coll_target = bpy.context.collection                                           # Set target collection based on the collection in context (selected) 

        if coll_target and objs:                                                       # If target found and object list not empty

            for ob in objs:                                                            # Loop through all objects
                for coll in ob.users_collection:                                       # Loop through all collections the obj is linked to
                    coll.objects.unlink(ob)                                            # Unlink the object

                coll_target.objects.link(ob)                                           # Link each object to the target collection

        bpy.ops.object.select_all(action="DESELECT")


        return {'FINISHED'}

class ADDONNAME_OT_my_op_walls(bpy.types.Operator):
    bl_label = "Sort"
    bl_idname = "addonname.myop_operator_walls"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        scene = context.scene
        mytool = scene.my_tool
        
        collectionFound = False

        for myCol in bpy.data.collections:
            #print(myCol.name)
            if myCol.name == mytool.my_string_walls:
                collectionFound = True
                #print ("Collection found in scene")
                break
            
        # Creates a new collection                
        if collectionFound == False:
            myCol = bpy.data.collections.new(mytool.my_string_walls)
            bpy.context.scene.collection.children.link(myCol) 

        # Set the new collection as active
        def recurLayerCollection(layerColl, collName):
            found = None
            if (layerColl.name == collName):
                return layerColl
            for layer in layerColl.children:
                found = recurLayerCollection(layer, collName)
                if found:
                    return found

        layer_collection = bpy.context.view_layer.layer_collection
        layerColl = recurLayerCollection(layer_collection, mytool.my_string_walls)
        bpy.context.view_layer.active_layer_collection = layerColl



        # MOVE SELECTED OBJECTS TO ANOTHER COLLECTION ONLY
        objs = bpy.context.selected_objects # List of object references

        coll_target = bpy.context.scene.collection.children.get(mytool.my_string_walls)     # Set target collection to a known collection 
        coll_target = bpy.context.collection                                           # Set target collection based on the collection in context (selected) 

        if coll_target and objs:                                                       # If target found and object list not empty

            for ob in objs:                                                            # Loop through all objects
                for coll in ob.users_collection:                                       # Loop through all collections the obj is linked to
                    coll.objects.unlink(ob)                                            # Unlink the object

                coll_target.objects.link(ob)                                           # Link each object to the target collection

        bpy.ops.object.select_all(action="DESELECT")


        return {'FINISHED'}

#################### UI #######################
class ADDONNAME_PT_main_panel(bpy.types.Panel):
    bl_label = "Main Panel"
    bl_idname = "ADDONNAME_PT_main_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "New Tab"

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        mytool = scene.my_tool
        
        
        split = layout.split(factor=0.75)
        col_1 = split.column()
        col_2 = split.column()
        col_3 = split.column()
        
        col_1.prop(mytool, "my_string_windows")
        col_2.operator('object.selected_by_name_operator_windows', text='Select')
        col_3.operator("addonname.myop_operator")
        

        split = layout.split(factor=0.75)
        col_1 = split.column()
        col_2 = split.column()
        col_3 = split.column()
        col_1.prop(mytool, "my_string_doors")
        col_2.operator('object.selected_by_name_operator_doors', text='Select')
        col_3.operator("addonname.myop_operator_doors")

        split = layout.split(factor=0.75)
        col_1 = split.column()
        col_2 = split.column()
        col_3 = split.column()
        col_1.prop(mytool, "my_string_walls")
        col_2.operator('object.selected_by_name_operator_walls', text='Select')
        col_3.operator("addonname.myop_operator_walls")




classes = [MyProperties, 
            ADDONNAME_PT_main_panel, 
            ADDONNAME_OT_my_op_windows, 
            ADDONNAME_OT_my_op_doors,
            ADDONNAME_OT_my_op_walls,
            SelectByNameOperator_windows,
            SelectByNameOperator_doors,
            SelectByNameOperator_walls,
]

def register():
    for cls in classes:
        bpy.utils.register_class(cls)
        
        bpy.types.Scene.my_tool = bpy.props.PointerProperty(type= MyProperties)
 
def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
        del bpy.types.Scene.my_tool

if __name__ == "__main__":
    register()
$\endgroup$
2
  • $\begingroup$ Would a) make the property group members pointers to a collection instead of stings. blender.stackexchange.com/questions/199233/… Can create a dynamic enum for the operator using this data blender.stackexchange.com/questions/122589/… $\endgroup$
    – batFINGER
    Commented May 18, 2021 at 10:05
  • $\begingroup$ Hmmm, maybe I'm not following but those suggestions are for selecting from a list existing items, but this case is different since the collections are created by the user with custom names. $\endgroup$ Commented May 18, 2021 at 10:22

0

You must log in to answer this question.

Browse other questions tagged .