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?
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’
To answer my own question again The only solutions I found to this problem are:
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
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
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
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
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.
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
“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 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
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