0
$\begingroup$

im trying to create a script that does basically what the array does. My code only moves the active object but does not duplicate and move the duplicate.

import bpy



 def createcircle(curve, number):
    for x in range(number):
        duplicateobject = curve.copy()
        duplicateobject = bpy.ops.transform.translate(value=(0, .1, 0))
    
    
 createcircle(bpy.context.active_object, 10)
$\endgroup$
1

2 Answers 2

3
$\begingroup$

try this:

import bpy
import math


def createcircle(object, number, radius, xOffset, yOffset, zOffset):
    origin = object.location
    
    for x in range(number):
        newObj = object.copy()
        bpy.context.scene.collection.objects.link(newObj)
        newObj.location = (origin.x + xOffset * x, origin.y + yOffset * x, origin.z + zOffset * x)
    
print("script started ---------")

radius = 6

createcircle(bpy.context.active_object, 10, radius, 2.1, 0, 0)

you created the cubes, but you created them in "nirvana". You have to link them to a scene to "see" them. But you can see them...if you go in your outliner and...check orphan data.

enter image description here

buuuuuut....i think, you were looking for this:

import bpy
import math


def createcircle(object, number_of_objects, radius):
    origin = object.location
    angle = 2 * math.pi / number_of_objects
    for x in range(number_of_objects):
        newObj = object.copy()
        bpy.context.scene.collection.objects.link(newObj)
        newObj.location = (math.sin(angle*x)*radius, math.cos(angle*x)*radius, 0)
    
print("script started ---------")

radius = 6

createcircle(bpy.context.active_object, 10, radius)

result:

[enter image description here2

and here is a video tutorial: https://youtu.be/k2lsdYBwocU

just in case you are interested ...

$\endgroup$
1
$\begingroup$

Use matirices to emulate modifier.

To make a circular array via the modifier entails using an object offset. Which for a circle, generally entails adding an empty at origin with the angle set, to be that of between current and next item in array, with empty as pivot point..

Adding translation to empty will spriral, scale will scale each a little more or less...

This is done by applying the empties matrix world to each array copy of our object, If a default object with no parent and only transform being 5 degrees around z axis its matrix world is the equivalent of the rotation matrix

R = Matrix.Rotation(radians(5), 4, 'Z')

when applied to an object's world (or global) matrix, it rotates it 5 more degrees around the $Z$ axis than it already was. ie it is not setting an absolute value, rather transforming from A to B. Let's for example sake start with zero global z rotation

ob.matrix_world = R @ ob.matrix_world

will rotate it from 0 to 5, and

ob.matrix_world = R @ R @ R @ ob.matrix_world

from 5 to 20. Instead we are doing this by applying to a copy which already has the rotation applied prior. The above would be the third copy.

A modifier creates mesh, whereas for this example will instead create a new object.

Test script, with an object selected as context, with transforms already set, add an empty, rotate it, and use it for our array modifer

import bpy
from bpy import context
from math import radians

def emulate_array(ob, count, empty):

    M = empty.matrix_world
    print(M.to_euler())

    for i in range(1, count):
        ob = ob.copy()
        ob.matrix_world = M @ ob.matrix_world
        context.collection.objects.link(ob)

ob = context.object
# add an empty to be array object
bpy.ops.object.empty_add(location=(0, 0, 0))
empty = context.object
count = 10
empty.rotation_euler.z = radians(360) / count
context.view_layer.update()
emulate_array(ob, count, empty)

Would however skip the adding empty step and create a matrix instead.

Examples.

https://blender.stackexchange.com/a/214497/15543

rotation via python does not the way i would it have expected

Add camera at random position through Python

$\endgroup$

You must log in to answer this question.

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