I have the following code:

bl_info = {
    "name": "Align select verts to abs pos",
    "category": "Mesh",

import bpy
import bmesh

class MeshAlignVerts(bpy.types.Operator):
    bl_idname = "mesh.align_verts"
    bl_label = "Align verts pos"
    bl_options = {'REGISTER', 'UNDO'}

    x_pos = bpy.props.FloatProperty(name="X",description="X axis",default=0.0)
    y_pos = bpy.props.FloatProperty(name="Y",description="Y axis",default=0.0)
    z_pos = bpy.props.FloatProperty(name="Z",description="Z axis",default=0.0)

    chosen_axis = bpy.props.EnumProperty(items=(('X','X','Align along X axis'),('Y','Y','Align along Y axis'),('Z','Z','Align along Z axis')),name="Choose Axis")

    def execute(self,context):
        print (self.chosen_axis)
        print ("Executed script")
        return {'FINISHED'}

    # update individual verts
    def update_indiv_vert_pos(self,context):
        sel_verts = []
        for v in mesh.verts:
            if v.select:
    # TODO: Add logic to move points along custom defined transform orientation
      #   bpy.context.space_data.transform_orientation = 'GLOBAL'
        for v in sel_verts:
            if self.chosen_axis == 'X':
                v.co.x = self.x_pos
            if self.chosen_axis == 'Y':
                v.co.y = self.y_pos
            if self.chosen_axis == 'Z':
                v.co.z = self.z_pos

def register():

def unregister():

if __name__ == "__main__":

I want to either add a button which when pressed will call the function in execute. Or at least wait for the user to specify values for the Float properties and then choose an axis which then calls the function in execute()

How can I achieve this ?

This question looks similar to Addon: run execute() only when button is clicked

I have read that but am not able to get any sufficiently useful info from the responses there can someone please guide me on what to do ?

Also what are the other possible alternatives to delaying execution of the execute function for this script ?


1 Answer 1


Normally you can let Blender's layout system draw the properties, but when you want to have an action button on an Operator UI, you have to specify the whole interface. You might even consider writing a bit of Panel code instead of trying to do it all in the Operator.

But if you do want to stick with the Operator only you could augment your current Operator code with.

  • an unlocked property (boolean),
  • an explicit draw() function,
  • replace your current execute() function with something that checks if the unlocked property was set to True yet.


unlocked = bpy.props.BoolProperty()

def draw(self, context):
    scn = context.scene
    l = self.layout
    col = l.column()

    col.prop(self, 'x_pos')
    col.prop(self, 'y_pos')
    col.prop(self, 'z_pos')
    col.prop(self, 'chosen_axis')
    col.operator('mesh.align_verts', text='Mesh Align').unlocked = True

def execute(self,context):
    print (self.chosen_axis)
    if self.unlocked:
        print ("Executed script")
    return {'FINISHED'}

enter image description here

I would not not use an Operator as a replacement for a proper UI panel.

  • $\begingroup$ Should "col.operator('mesh.align_verts', text='Mesh Align').unlocked = True" be set to False if I do not want the execute function to be run the first time when the operator is called from the menu. So that only the second time when the button is actually clicked action is taken ? $\endgroup$
    – Aiena
    Nov 27, 2015 at 10:42
  • $\begingroup$ Was unsure if the line 'col.operator('mesh.align_verts', text='Mesh Align').unlocked = True' would immediately call the execute function having the 'unlocked' property set to True rather than on button press. $\endgroup$
    – Aiena
    Nov 27, 2015 at 10:52
  • $\begingroup$ Yep. That line has no effect on the value of unlocked until you press the button. $\endgroup$
    – zeffii
    Nov 27, 2015 at 10:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .