# Find out if Mesh Operator (bpy.ops.mesh…) was cancelled or not via python

I am using bpy.ops.mesh.extrude_region_move to extrude a selected region along their averaged normal. I don't set the value-component of TRANSFORM_OT_translate, so the operator is modal. The return-value of the operator is not {'CANCELLED'} or {'FINISHED'} it's {'RUNNING_MODAL'}. The user can accept the extrusion with enter or cancel it via esc (normal behaviour of that operator).

My blender-addon needs to know if the user has accepted a extrusion or if it was cancelled (The addon stores the face-ids of a selected region. If the user now extrudes the face ids are recreated. Therefore I need to update the stored face-ids. But I need to know 'when').

Any ideas how I can find out if the extrude_region_move was cancelled/not cancelled?

Thanks!

• If you are calling that operator from within your code you can examine the return value, rv = bpy.ops.extrude_region_move(...), which will be {'CANCELLED'} if it is cancelled, or {'FINISHED'} if completed. – batFINGER Sep 3 '15 at 14:21
• The return_value is {'RUNNING_MODAL'} so I can't use it. – Hamburml Sep 3 '15 at 14:24
• Don't know if there's a general solution to this, but you can find out with a little hack. Check the dimensions of the object before and after the operation. If there's any difference, the extrusion included a translation (at least if the faces were extruded outwards). You can also use the bmesh calc_volume function to check if there's a difference in volume, which would work even if the faces WERE extruded inwards. – TLousky Sep 3 '15 at 14:52
• It is not allways sure: if the user did accept the extrusion, but didn't move the new geometry, the result is the same as if he would have cancelled it. Do you need to differentiate these two cases? – Mörkö Sep 3 '15 at 16:04
• @user277143 No, I don't need to differentiate between those two cases. But batFinger's Solution is working great! – Hamburml Sep 3 '15 at 17:27

This looks at the TRANSFORM_OT_translate.value Vector as shown in the 'INFO' reports. If the operator was cancelled it returns (0, 0, 0) else has a length.

import bpy

wm = bpy.context.window_manager

print("TESTing Extrude Op")
for op in wm.operators:
if op.bl_idname == 'MESH_OT_extrude_region_move':  #name == 'Extrude Region and Move'
print(op.name, "Found")
v = op.macros['TRANSFORM_OT_translate'].properties.value
if v.length:
print("operator used")
else:
print("operator canceled")

• That is lovely! Thanks! I will post an additional answer of how I did it. – Hamburml Sep 3 '15 at 17:28

@batFinger's Solution was correct. I only want to present my solution because I also used a Timer to check every half second if the Operator is in the wm.operators list.

def execute(self, context):

bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN',
TRANSFORM_OT_translate={
"constraint_orientation": 'NORMAL',
"constraint_axis": (False, False, True)})

wm = bpy.context.window_manager
ob = bpy.context.active_object
lastLen = len(wm.operators)

def checkExtrudeOperator():
#print("Things are being done")
wm = bpy.context.window_manager
indexoflastoperator = len(wm.operators)
if indexoflastoperator > 0 and indexoflastoperator > lastLen:
lastoperator = wm.operators.items()[indexoflastoperator -1]
op = lastoperator[1] # get the TRANSFORM_OT_translate
if op.bl_idname == 'MESH_OT_extrude_region_move':
v = op.macros['TRANSFORM_OT_translate'].properties.value
if v.length:
#we need to get new face ids
bm = bmesh.from_edit_mesh(ob.data)
region = bpy.context.scene.plator_custom[bpy.context.scene.plator_custom_index]
region.face_ids = ""
for face in bm.faces:
if face.select:
region.face_ids = region.face_ids + ";" + str(face.index)
print("operator used")
return
else:

print("operator canceled")
return
# we don't need to get new face ids