5
$\begingroup$

I'm still very new to Blender, but I'm trying to get a custom menu up and running. I followed the video tutorial on Blender Cookie and works great.

I'm trying to create a button that will move and object to the origin.

My code is as followed.

    row = layout.row()
    row.operator("transform.resize", text="Scale")
    row = layout.row()
    row.operator("context.active_object.location=(0,0,0)", text="Orgin")
    row = layout.row()
    row.operator("transform.translate(value=(0,0,0))", text="Orgin")

The "Scale" button works so I know something somewhat works. The other two buttons do not show up. I was trying to see what move commands work.

I tried the commands independently in the console and they work... just not in button form.

$\endgroup$
1
  • $\begingroup$ Try moving the translate command to the top, and see how many buttons appear, and whether the command works. Also try making three scale buttons. In the console, type help(layout.row); and help(row.operator). I strongly suspect you need to specify a function name, not a statement (such as a function call or an assignment). But also make sure you're using layout.row correctly. $\endgroup$
    – user234461
    Commented Oct 2, 2013 at 14:46

3 Answers 3

4
$\begingroup$

Function row.operator() only accepts operators, the full name of which are prefixed with bpy.ops., as in bpy.ops.transform.resize for the 1st row. The 2nd row fails because it's not an operator.

The mechanism for passing arguments to an operator is by using the OperatorProperties object returned by operator(). So, the 3rd row could be rewritten like this:

row = layout.row()
prop = row.operator("transform.translate", text="Orgin")
prop.value = (1, 0, 0)

Note that your original value argument of (0, 0, 0) wouldn't move the object anywhere, as if it fails to execute. The value I use above will move it 1 unit across X axis.

$\endgroup$
4
  • 1
    $\begingroup$ but that wouldn't move it to the origin; the only way to really do it like this would be to set prop.value to some tricky lambda that overrides __getitem__ to check bpy.context.active_object.location[0] * -1 or similar. $\endgroup$
    – wchargin
    Commented Oct 22, 2013 at 3:14
  • $\begingroup$ Whoops, didn't realize that bit about moving to origin. In that case, object.location_clear() might be more appropriate. $\endgroup$
    – Adhi
    Commented Oct 22, 2013 at 3:23
  • $\begingroup$ ah, indeed! Didn't know that existed. $\endgroup$
    – wchargin
    Commented Oct 22, 2013 at 3:24
  • $\begingroup$ You can also use row.operator('transform.translate', text='Origin').value=(1, 0, 0) instead of putting the value assignment on two lines $\endgroup$
    – Greg Zaal
    Commented Dec 10, 2013 at 18:56
4
$\begingroup$

That's because context.active_object.location=(0,0,0) is not an operator. It's a statement.

You could define your own operator:

import bpy
def main(context):
    # This is what happens when your operator is invoked.
    context.active_object.location = (0, 0, 0)

class SnapToCenterOperator(bpy.types.Operator):
    """Snaps an object to the center."""
    bl_idname = "view3d.snap_to_center_operator"
    bl_label = "Snap Object to Center"

    @classmethod
    def poll(cls, context):
        # This is called to determine whether the operator can be invoked
        return context.active_object is not None

    def execute(self, context):
        # This invokes the operator and returns a state
        main(context)
        return {'FINISHED'}

def register():
    # If it's an addon, this is called when the addon is enabled
    bpy.utils.register_class(SnapToCenterOperator)
def unregister():
    # If it's an addon, this is called when the addon is disabled
    bpy.utils.unregister_class(SnapToCenterOperator)

if __name__ == "__main__":
    # We use this to register it in case we're running it manually
    # (which we are; click the "Run Script" button)
    register()

and then use

row.operator("view3d.snap_to_center", text="Origin")

to achieve the desired result.


NOTE: This is just an example on how to create your own operator. In this case you'll actually just want to use bpy.ops.object.location_clear, as such:

row.operator("object.location_clear", text="Origin")
$\endgroup$
1
  • $\begingroup$ Downvoter, please explain? $\endgroup$
    – wchargin
    Commented Dec 11, 2013 at 1:30
1
$\begingroup$

Sometimes it is convenient to use the bpy.ops.wm.context_* operators to change context properties, as you don't need to create your own operator to wrap single-liners.

# Operator call
bpy.ops.wm.context_set_value(data_path="object.location", value="(1,2,3)")

# Add to layout
props = row.operator("wm.context_set_value", text="Orgin")
props.data_path = "object.location"
props.value = "(0,0,0)"

# data_path can be any member of bpy.context
# If it's not available, the operator will PASS_THROUGH
$\endgroup$

You must log in to answer this question.