0

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()

Juan Carlos
  • 179
  • 2
  • 9
  • Would a) make the property group members pointers to a collection instead of stings. https://blender.stackexchange.com/questions/199233/custom-search-data-to-uilayout-prop-search Can create a dynamic enum for the operator using this data https://blender.stackexchange.com/questions/122589/python-with-blender-using-enumproperty-the-dynamic-way – batFINGER May 18 '21 at 10:05
  • 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. – Juan Carlos May 18 '21 at 10:22

0 Answers0