Access active operator during its execution

Hello guys,

I am trying to implement a custom node based addon in python and I am unable to identify the active operator during the execution.
Use case scenario:
I have a custom node which implements the free() method. During the execution of the free() method I want to know which action was performend on this node. I my case it can be “delete node” or “delete with reconnect”
I tried bpy.context.active_operator and also bpy.ops.info.report_copy() to get the last executed operator. The problem here is the fact that active_operator is availabe only after the execution of the operator. Also, there is no way to determine the last keyboard event from outside modal operators
So, is there any way to determine which operator is being executed during its execution?

Thanks!

1 Like

More preciseley, what I want to know here, is the name of the operator during execution. In this case, the name is ‘NODE_OT_delete_reconnect’ or ‘NODE_OT_delete’

Looks like the bpy.context.active_operator is always the previosily executed operator. Is this misnaming or a bug?

Same problem with

bpy.data.window_managers["WinMan"].operators[-1]

To answer my own question again :slight_smile: The only solutions I found to this problem are:

  1. Use a dummy modal operator to catch keyboard event CTRL+X and store this into an accessible prop. This will work only if nobody chages the default shortcut for delete_reconnect

  2. Capture context(node links and sockets) from free() callback and execute it later on a timer when bpy.context.active_operator is up to date… This might work in any situation …unless the delete_reconnect is being batched into another script like node wrangler for example :slight_smile:

  3. Implement a custom delete node operator and try to override the default keyboard shortcut for delete_reconnect in nodes view. I don’t like this approach. It’s to messy and it can interfeere with other stuff

So, bpy.context.active_operator not being real time and accesible information from a callback, smels like a bug to me. Maybe I should open a bug report about this :thinking:

If fits the Bug Report criteria for Blender then it would be a good idea to report it.

I also need this ability, though I’m not sure it’s a bug. What we need is an app.handler callback for pre/post operator events

that could work as well

@jacqueslucke do you have any insight on this probem? Thanks!

I’m not aware of any solution to the problem you describe. The best solution is probably to avoid this problem. Why is it important for you to know which operator deleted the node?

If my understanding is correct, for custom nodes there is no automatic reconnect behavior implemented in blender, but you can call the node.delete_reconnect operator anyway and this behaves like the regular node.delete. Now, I took my inspiration from here https://github.com/LuxCoreRender/BlendLuxCore/blob/master/nodes/base.py#L108 and I implemented an automatic reconnect procedure. The only problem I have is that I cannot diferentiate between delete and delete_reconnect in real time… during the callback execution

I see. Unfortunately, I cannot help you here…

np. thanks anyway. I will dig a little bit more, maybe something comes up…

Callbacks in blender are not always context aware. there is no way of knowing which event/operator triggered the callback in the first place

You no 1 solution should work. Create a modal operator that always returns “pass_through” and acts as listener for all events. You will be able to capture the initiation but not the termination of the operator if the operator is also modal and consumes its termination event. Passing through events means also your modal operator won’t block in other modal operators. Changing the shortcut is irrelevant. Shortcuts are dynamically assigned as such you can detect the shortcut by looking up the current shortcut assigned to the operator of your interest. It’s anyway good practice to avoid hard wired code , especially in a dynamic language like Python.

If the operator watched is non modal which should be the case here then termination should be the same as initiation so you should not have any issues here. Non modal operators usually suppose to be instant actions.

You are right about this, but there’s a small problem: this won’t work if the operator is being called by menu :slight_smile:

… or by script

It could but the level of difficulty increases dramatically because now you won’t only have to track only the shortcuts but also mousemove and left click events. It’s possible but not easy to do.

You also keep track of the property that shows the connection if you wanna cover the script call possibility

I am not so sure why you want to differentiate between delete and reconnect. But if you keep track of the connections that’s possible too.

The info area in Blender also keeps track of operator execution but I am not familiar with it python wise.

This solution won’t really work if the is being called by other script like nodewrangler.
I found something which might work, but it requires more research until I am sure about it
First slution:
Theoretically, you can override operator entirely by creating a new one with the same id, but in this case you cannot use the original operator anymore, or at least I was not able to find a way to preserve the old one

Second one:
Do a method swizzling on the call function of the BPyOpsSubModOp class. This is working with python operators, but won’t work for native C operators :slight_smile:

“I am not so sure why you want to differentiate between delete and reconnect. But if you keep track of the connections that’s possible too.”

I need to differentiate beween delete and delete with reconnect because they are behaving the same way for custom python nodes :slight_smile: and I was trying to replicate the same behavior in python. Of course, this is minor issue, but the fact that you can’t access operator state in real time it is a much larger issue

I edited my reply for working with a script.

You can override even a C operator. You replace the reference to its initialization method with your own method while keeping the reference to the original method , renamed.

Python basically treats method and function names , or even class names, as variables.

Note in order to do that you will have to play with import functionality of python. Using sys.modules

There is only one python inside blender which all add ons and scripts share thus they can also share modules by reference according to namespace

This is advanced python coding but not that hard to do