1
$\begingroup$

I am new to scripting in blender/python, and I am unsure what I did wrong here. The script works fine until I try to make it work just with the active object. Then it throws the following error

Python: Traceback (most recent call last):   File "C:\Users\Juantxopanza\AppData\Roaming\Blender Foundation\Blender\2.92\scripts\addons\snap_origin_addon.py", line 39, in execute
    curObject.origin_set(type='ORIGIN_CURSOR', center='MEDIAN') AttributeError: '_BPyOpsSubModOp' object has no attribute 'origin_set'

location: <unknown location>:-1

Here's the code:

bl_info = {
    "name": "Snap Origin to selected",
    "author": "",
    "version": (0, 0),
    "blender": (2, 90, 0),
    #"location": "View3D > Mesh > Snap > Snap Origin to selected",
    "description": "snaps the origin of the object to a selection",
    "category": "Mesh",
}

import bpy
from bpy.props import (BoolProperty)
class MESH_OT_snapOrigin(bpy.types.Operator):
    """It has to begin with a selected element in edit mode"""
    bl_idname = "mesh.snap_origin_to_selected"
    bl_label = "Snap Origin to selected"
    bl_options = {'REGISTER', 'UNDO'}
    
    only_active: bpy.props.BoolProperty(
        name="set only active",
        description="set only the origin of the active object",
        default=False,
    )
    

    @classmethod
    def poll(cls, context):
        return context.area.type == 'VIEW_3D'
    

    def execute(self, context):
        curObject = bpy.context.active_object
        get_3dCursor = (bpy.context.scene.cursor.location[0],bpy.context.scene.cursor.location[1],bpy.context.scene.cursor.location[2])
        print(bpy.context.active_object.name)
        #print(curObject.location[0])
        bpy.ops.view3d.snap_cursor_to_selected()
        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
        if self.only_active == True:
           curObject.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
        else:
           bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
        # bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
        bpy.context.scene.cursor.location[0] = get_3dCursor[0]
        bpy.context.scene.cursor.location[1] = get_3dCursor[1]
        bpy.context.scene.cursor.location[2] = get_3dCursor[2]
        return {'FINISHED'}

# Registration

def set_origin_button(self, context):
    self.layout.operator(
        MESH_OT_snapOrigin.bl_idname,
        text="snap origin to selected",
        icon='PIVOT_CURSOR')
        
        
def register():
    bpy.utils.register_class(MESH_OT_snapOrigin)
    bpy.types.VIEW3D_MT_edit_mesh.append(set_origin_button)

def unregister():
    bpy.utils.unregister_class(MESH_OT_snapOrigin)
    bpy.types.VIEW3D_MT_edit_mesh.remove(set_origin_button)
$\endgroup$
0

1 Answer 1

1
$\begingroup$

Override the context.

There is no origin_set belonging to an Object.

There are a couple of ways to do this, either deselect all other objects before calling the origin set operator, or override the context to make the selection only the single (or chosen) object(s)

Am using the python console, which is a great place to nut things out.

With "Cube" active, and the "Cone" and "IcoSphere" selected...

>>> C.object
bpy.data.objects['Cube']

>>> C.selected_objects
[bpy.data.objects['Cube'], bpy.data.objects['Icosphere'], bpy.data.objects['Cone']]

Make an override dictionary, telling blender the only object to re-origin-ate is the "Cube" by making it the only member of context.selected_editable_objects <- The selected objects that the operator uses. Why cannot I override the context for bpy.ops.object.origin_set()

>>> c = {}
>>> c['active_object'] = None
>>> c['selected_editable_objects'] = [C.object]
>>> c
{'active_object': None, 'selected_editable_objects': [bpy.data.objects['Cube']]}

Run the operator with that context dictionary c as the first argument.

>>> bpy.ops.object.origin_set(c, type='ORIGIN_CURSOR')
{'FINISHED'}

and only the origin of the active object is set.

The error in your question relates to the Object not having an origin_set property.

>>> C.object.origin_set
Traceback (most recent call last):
  File "<blender_console>", line 1, in <module>
AttributeError: 'Object' object has no attribute 'origin_set'

3.2 Update

Context overrides are deprecated in Blender 3.2 and are scheduled to be removed in Blender 3.3 The replacement is temp_override. The manual has examples of how to use the new function.

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.