Beginner Basics - how to get aces to objects and properly reference them

Hi i’m a total beginner in blender and python.

Im trying to write addon for automaticaly create array with object ofset to active object using empty.
Here’s my code:

def execute(self, context):
    

    scene = bpy.context.scene
    cursor = scene.cursor.location
    active_obj = bpy.context.view_layer.objects.active
    mode = active_obj.mode

   bpy.context.view_layer.objects.active = active_obj

    #Create Empty
    bpy.ops.object.empty_add(type='PLAIN_AXES', location=cursor)

    #PROBLEM  trying here get acces of first selected active object but it doest seem to work:
    bpy.context.view_layer.objects.active = active_obj
    bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')

   bpy.ops.object.modifier_add(type='ARRAY')
    bpy.ops.object.modifiers["Array"].use_object_offset = True 

This code doesnt seem to work. Please help. Thanks!

what about it doesn’t work? are you getting an error? unexpected behavior? going to need more than a block of code that says “doesn’t work”. at a glance, your indents are off- that would certainly throw an exception.

Besides the indents being off, the issue is with this line:

bpy.ops.object.modifiers["Array"].use_object_offset = True

You need to use the object not the operator to change properties.

active_obj.modifiers["Array"].use_relative_offset = False

Everything else seems to work. Since you’re probably going to want to set a few more properties of the modifier, you may want to use something like:

mod = active_obj.modifiers["Array"]
mod.use_relative_offset = False

Here’s the complete script. I turned off Relative Offset and set the Offset Object also.

import bpy

scene = bpy.context.scene
cursor = scene.cursor.location
active_obj = bpy.context.view_layer.objects.active
mode = active_obj.mode

bpy.context.view_layer.objects.active = active_obj

#Create Empty
bpy.ops.object.empty_add(type='PLAIN_AXES', location=cursor)
offset_object = bpy.context.view_layer.objects.active

#No problems here:
bpy.context.view_layer.objects.active = active_obj
#bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')

bpy.ops.object.modifier_add(type='ARRAY')
mod = active_obj.modifiers["Array"]
mod.use_relative_offset = False
mod.use_object_offset = True 
mod.offset_object = offset_object

Make sure you have an Info panel open and refer to the System Console for errors. My machine immediately pointed me to the problem area, of course I had to fix the indentation issues first.

I would also warn you against assuming the modifier will be named “Array” it’s also possible that your newly created empty won’t be called “Empty”. You may want to look into giving them unique names.

A better way would be to avoid using the operators and just create the empty manually. That way you have a reference to it, and don’t need to rely on the name of the object. Edit: also worth noting that if you do it this way you also have to add it to the scene collection manually as this isn’t handled by the object factory

for example:

# create the empty. if there's already an object named "array", the object
# factory will append a numeric identifier to it, ie) 'array.001'
empty_obj = bpy.data.objects.new("array", None)
bpy.context.collection.objects.link(empty_obj) # bpy.context.collection is the last collection you interacted with, most likely the scene collection.
1 Like

Yup. In general it is best to avoid operators in your addons. I’ve only recently discovered the power of this. It really takes a lot of digging to find the work arounds to using operators, though. I wish someone with a lot more time than me could write a cross reference. I’m starting to get the hang of it and finding more ways to avoid operators as I do more addons.

The “use no operators” approach to adding the array modifier would be:

mod = active_obj.modifiers.new(name="my_array", type='ARRAY')

So the full version with @testure’s suggestion and the above is:

import bpy

scene = bpy.context.scene
cursor = scene.cursor.location
active_obj = bpy.context.view_layer.objects.active
mode = active_obj.mode

bpy.context.view_layer.objects.active = active_obj

#Create Empty
offset_obj = bpy.data.objects.new("Offset_Object", None)
bpy.context.collection.objects.link(offset_obj)

#No problems here:
bpy.context.view_layer.objects.active = active_obj

#The line below wasn't used, so I commented it out
#bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')

#create a named array modifier
mod = active_obj.modifiers.new(name="my_array", type='ARRAY')

mod.use_relative_offset = False
mod.use_object_offset = True 
mod.offset_object = offset_obj

WOW Thank You guys for helping me out! Code now works perfectly. I will also try to write code as You sugested!