0
$\begingroup$

Is it possible to have a class method work as same as with a function, where you can put in different parameter for one instance function? Like in my case, where I need to have 8 selection options, each with different naming conventions. This works fine with a function, but I need to execute the operation with a pie menu, so I believe an operator is the only way to go?
I was hoping to have one operator for each option, but have a different variable for each in the pie menu command?

lst = ["YO!", "WAZZAP!?", "HOW'YOU'DOIN!?"]

class Print1(bpy.types.Operator):
    bl_idname = "object.print1"
    bl_label = "Print 1"

    def execute(self, context):
        self.printz()
        return{"FINISHED"}

    @classmethod
    def printz(cls, text=lst[0]):

        print(text, "What is going on in the kitchen?")


class Print2(bpy.types.Operator):
    bl_idname = "object.print2"
    bl_label = "Print 2"

    def execute(self, context):
        Print1.printz(lst[1])
        return{"FINISHED"}

In this case, I have one "master" operator that feeds others, but I think there must be a simpler way than have a copy of 7 operators in code, that do almost the same thing? Can it be done as same as with basic functions?

$\endgroup$
  • $\begingroup$ Given example above, one operator with an index int property. def printz(self): print(lst[self.index]) Pass the different index in your pie menu pie.operator("object.print").index = 0 $\endgroup$ – batFINGER May 19 '18 at 3:15
0
$\begingroup$

Having multiple operators just to call one function with different arguments is not the way I like that, I prefer what @batFINGER suggested in a comment - a single operator that behaves based on passed parameter:

class Print(bpy.types.Operator):
    bl_idname = "object.print"
    bl_label = "Print"

    # this is the parameter
    id = bpy.props.IntProperty(default=0)
    # it can even be of type StringProperty() and you can pass the message you want

    def execute(self, context):
        output = ["response 1",
                  "response 2",
                  "reposnse 3"]
        print(output[self.id])
        return {"FINISHED"}

When you call the operator, you pass the parameter:

 bpy.ops.object.print(id=2)
 # or inside UI
 layout.operator('object.print').id = 2
 # prints 'response 3' when pressed

 # or like this with multiple params
 bpy.ops.object.print(param_1=False, param_2="Foo")
 op = layout.operator('object.print')
 op.param_1 = False
 op.param_2 = "Foo"

Ultimately it depends on what you are doing and whether you have other intentions with the classes. But for simple things like outputting different text this is the way to keep code simple.

Another thing I'd like to mention is to make it explicitly read what it does, ie:

# I have no idea what this prints and have to look it up in code
bpy.ops.object.print(id=2)

# with comment this is better, but falls apart when you change it in operator
# (unless you change all the comments also..)
bpy.ops.object.print(id=2)    # "response 3"

# best (using string param)
bpy.ops.object.print(msg="response 3")
$\endgroup$
0
$\begingroup$

I don't know what exactly you were going for with the class method, but using a function in this case should be equivalent. There is no need for a "master" operator.

from bpy.types import Operator


def printz(index=0):  # "cls" wasn't being used anyway
    text = ["A", "B", "C"][index]
    print(text)


class Print1(Operator):
    bl_idname = "object.print1"
    bl_label = "Print 1"

    def execute(self, context):
        printz()  # index defaults to 0

        return {"FINISHED"}


class Print2(Operator):
    bl_idname = "object.print2"
    bl_label = "Print 2"

    def execute(self, context):
        printz(1)

        return {"FINISHED"}
$\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.