0
$\begingroup$

I want to pass some created objects by an operator to another operator for modifications. I tested with CollectionProperty, but can't pass the collection from the first operator to the second one: TypeError: Converting py args to operator properties: OBJECT_OT_called_op.selItems expected a each sequence member to be a dict for an RNA collection, not SceneSettingItem

What is the problem here ? (Maybe, there is a better method to pass a list of objects).

import bpy

# Assign a collection
class SceneSettingItem(bpy.types.PropertyGroup):
    name = bpy.props.StringProperty(name="Test Prop", default="Unknown")



class CallerOperator(bpy.types.Operator):
    """caller"""
    bl_idname = "object.caller_operator"
    bl_label = "Simple caller Operator"

    def execute(self, context):
        #Assume we have some selected objects :
        selected = bpy.context.selected_objects

        # Create Collection :
        bpy.types.Scene.my_settings = bpy.props.CollectionProperty(type=SceneSettingItem)
        # clear collection:
        bpy.context.scene.my_settings.clear()
        # add in collection:
        for obj in selected:
            my_item = bpy.context.scene.my_settings.add()
            my_item.name = obj.name

        # pass collection: 
        bpy.ops.object.called_op(selItems = bpy.context.scene.my_settings)
        return {'FINISHED'}


class CalledOp(bpy.types.Operator):
    """called"""
    bl_idname = "object.called_op"
    bl_label = "Called Operator"
    selItems : bpy.props.CollectionProperty(type=SceneSettingItem)

    def execute(self, context):
        #read collection
        print ("collection = ",self.selItems)
        for obj in self.selItems:
            print(obj.name)

        return {'FINISHED'}


def register():
    bpy.utils.register_class(CallerOperator)
    bpy.utils.register_class(SceneSettingItem)
    bpy.utils.register_class(CalledOp)

def unregister():
    bpy.utils.unregister_class(CallerOperator)
    bpy.utils.unregister_class(SceneSettingItem)
    bpy.utils.unregister_class(CalledOp)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.caller_operator()
$\endgroup$
  • 1
    $\begingroup$ Suggest using the operator / context paradigm. For example by selecting the objects that are created with one operator, they are available to next as context.selected_objects (Note that there is a context argument in operator methods so there is no need to use bpy.context ad infinitum) If you set the scene property in one operator it is available to the next thru context without passing as argument at all. Also See blender.stackexchange.com/questions/48513/… $\endgroup$ – batFINGER Oct 25 '19 at 0:44
  • $\begingroup$ Thanks batFINGER, context argument was the solution; working code in answer. $\endgroup$ – Tolgan Oct 25 '19 at 20:42
1
$\begingroup$

Thanks to batFINGER's comment, here is the working code: no need to pass arguments here, when calling operator : if it's stored in Scene, we can access to collection through context:

import bpy


# Assign a collection
class SceneSettingItem(bpy.types.PropertyGroup):
    name = bpy.props.StringProperty(name="Test Prop", default="Unknown")


class CallerOperator(bpy.types.Operator):
    """calls"""
    bl_idname = "object.caller_operator"
    bl_label = "Simple caller Operator"

    def execute(self, context):
        # Assume we have selected objects :
        selected = context.selected_objects

        # Create Collection :
        bpy.types.Scene.my_settings = bpy.props.CollectionProperty(type=SceneSettingItem)
        # clear collection:
        context.scene.my_settings.clear()
        # add in collection:
        for obj in selected:
            my_item = context.scene.my_settings.add()
            my_item.name = obj.name

        # call operator: 
        bpy.ops.object.called_op()
        return {'FINISHED'}


class CalledOp(bpy.types.Operator):
    """called"""
    bl_idname = "object.called_op"
    bl_label = "Called Operator"
    #selItems : bpy.props.CollectionProperty(type=SceneSettingItem)

    def execute(self, context):
        #read collection
        print ("collection = ",context.scene.my_settings)

        for obj in context.scene.my_settings:
            print(obj.name)

        return {'FINISHED'}


def register():
    bpy.utils.register_class(CallerOperator)
    bpy.utils.register_class(SceneSettingItem)
    bpy.utils.register_class(CalledOp)

def unregister():
    bpy.utils.unregister_class(CallerOperator)
    bpy.utils.unregister_class(SceneSettingItem)
    bpy.utils.unregister_class(CalledOp)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.caller_operator()
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.