I am looking at giving more than one arguments to a button operator. I know how to pass one. I create a property and assign a new value to it in the draw function of the panel. This is very useful because, one single operator can serve as many buttons. But what if I’d like to pass two arguments?
Here is a simplified example showing the situation.
import bpy
class SimpleOperator(bpy.types.Operator):
''''''
bl_idname = "object.simple_operator"
bl_label = ""
property_1 = bpy.props.StringProperty() # defining the property
property_2 = bpy.props.StringProperty() # defining another property
def execute(self, context):
print("property_1 :" + self.property_1)
print("property_2 :" + self.property_2)
return {'FINISHED'}
class OBJECT_PT_hello(bpy.types.Panel):
bl_label = "Hello World Panel"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
def draw(self, context):
layout = self.layout
col = layout.column()
a = "Argument a"
b = "Argument b"
col.operator("object.simple_operator", text="property_1 passing a").property_1 = a
col.operator("object.simple_operator", text="property_1 passing b").property_1 = b # same operator with different argument
col.operator("object.simple_operator", text="property_2 passing a").property_2 = a # how to pass both argument together?
This example code will put three buttons in an “Hello World Panel” in the properties window on the object tab. Pushing on these buttons will print value of (a) or (b). Pushing on the third will pass (a) to another property. Now, how would I do if I want to pass both arguments at the same time and print both arguments. They must stay different arguments (c = a + b and passing c as argument would not work).
I think that a possibility would be to make a CollectionProperty and passing a list instead, but I didn’t figure how to do it. I think that it would work.
So here is my question :
Is it possible to assign new values to more than one property on a button operator? (and if yes how)
If not, How do I set a CollectionProperty to pass a list to my button operator (in this example)
Ok I’ll clarify something. In the above script, in the line :
col.operator("object.simple_operator", text="property_1 passing a").property_1 = a
I pass the argument (a) to (property_1) when (simple_operator) is executed. Is it possible to pass an argument to (property_1) and another one to (property_2) at the same time?
If not, how do I make a collection property to pass a list in which I would put (a, b)?
The problem Axon D mentions is something I’ve also experienced and I’d be interested in seeing a solution.
Stringing arguments together is a workaround that has limitations. It’s ok for strings, but doesn’t work for lists, dictionaries, etc.
Storing arguments as (scene/window manager) properties unnecessarily clutters blender and is the workaround I usually use. But it’s still a workaround.
You could try in those cases a string like this: “N, P1, P2, P3” where N is the number of arguments, in this case 3, and P1, P2, P3 are pointers to such global variables (lists, dictionaires…).
But I think this is a way of complicate the life yourself. If BlenderFoundation don’t want operators to have arguments just create a different operator for each case you need and read global variables or properties stored in the Scene as RickyBlender says. I asked Ton why operators have not arguments and he said that it was very debated. Probably more easy to code and not really life or death issue so they did the easy way.
so this is the way of passing a “pointer” in python using a string and eval() then to be able to use that “pointer”.
I agree pointer is a bad name for that, call it “passing a variable name and posterior reading with eval method” instead. I am just lazy in naming things.
Thanks for the replies. Now I have some solutions.
I think I’ll go with something similar to what Bao2 talked. This seems an interesting approach I didn’t think of. but I will avoid to use an eval() function. I read on this forum that eval() should be used as less as possible for security reasons. Malicious code can be hidden with that.
I think I’ll encode my arguments and decode them with the separator approach and adapt with if statements. This should do the trick for my situation. But I really hope that arguments are implemented into operators. This would really make things easier.
Bye the way, is there a possibility to make lists properties? Is CollectionProperty a kind of list property? I never used them. I am not sure what they are used for.
when you execute col.operator() function you get returned a pointer to operator button and then you modified one attribute in the same line…
for example: