Context mode of an operator

When I want to enable operator on only specific modes, I can use bl_context = “posemode” in the panel class or check it with if context.mode == “POSE”. But in both cases, the operator is still available with space bar as an element of the search list and can make errors if it is used in a wrong context.

Is it possible the make the operator itself appear only in some mode? or what else could I do?

Thanks :slight_smile:

bl_context in a panel class is only cosmetic, it will hide the panel under certain circumstances.

The proper way is to add a poll() classmethod to the operator in question and let it ensure all context conditions are met (return False otherwise).

You should not check context.mode btw, but rather context.object.mode, so something like

class YourOperator(...):
    # ...

    @classmethod
    def poll(cls, context):
        return (context.object is not None and
                  context.object.mode == 'POSE')

    def execute(self, context): #...

Poll-failing operators are not listed in spacebar menu, buttons in panels will be grayed out.

Thanks, that’s perfect.

What’s @classmethod? I didn’t understand well what is does and it’s still working without.

It’s a function decorator with special meaning, it makes the following function definition a class method, as opposed to a regular method.

A regular method needs to be called on an instance of a class, and the first argument will be a reference to that instance (usually called “self”):

class A:
    i = 1
    def foo(self, val):
        self.i += val
        print(self.i)

a = A()
a.foo(4) # prints 5

b = A()
b.foo(7) # prints 8

If you turn a function in a class (=method) into a class method, there’s no need for an instance of the class. Instead, the class method is called on the class directly, and the first argument will be a reference to the class (usually named “cls”).

class A:
    i = 1
    @classmethod
    def foo(cls, val):
        cls.i += val
        print(cls.i)

# Note: you shouldn't call a classmethod via a class instance actually
a = A()
a.foo(4) # prints 5

b = A()
b.foo(7) # prints 12

# Proper call to class method:
A.foo(8) # prints 20

It’s possible to call a class method on a class instance, but note that no matter on what you call it, there will only be one class and thus one variable i (not independent for every object).

There’s actually a 3rd type, static methods. They are no different from class methods, except there’s no reference passed at all (neither self nor the class):

class A:
    i = 1
    @staticmethod
    def foo(val):
        # since we don't have a reference to the class,
        # we need to explicitly state that we refer to class A's variable i
        A.i += val
        print(A.i)

# Note: you shouldn't call a staticmethod via a class instance actually
a = A()
a.foo(4) # prints 5

b = A()
b.foo(7) # prints 12

# Proper call to static method:
A.foo(8) # prints 20

Also see: http://stackoverflow.com/a/11788267/2044940

1 Like

Thank you for the explanation!