Here’s a little AddOn you might find useful, it will help you quickly create multiple linked duplicates of the selected object. The AddOn adds a new menu item to the Object menu, “Duplicate Multiple Linked”. When you run the command, options in the Toolshelf allow you to interactively set them: number of copies, XYZ positional offset of the copies, and a checkbox to decide if you want the copies, including the original, parented under an empty.
The AddOn is coded to be used with one object selected, but it does also work on multiple objects - in the latter case, it helps to turn off the “Parent under Empty” checkbox, and you will need to select the copies with Shift-Alt-L every time you want to repeat the command. In the example render below, a grid of 11,554 objects was created in 4 steps that would have taken mere seconds were it not for the slowdown due to the large number (it took about 3 minutes on my 3.2Ghz box).
I’m releasing it as public domain, so feel free to appropriate it and if you feel generous, post an improved version. There are plenty of improvement that could be made. My favourite would the ability to input the name of a curve object, and have the duplication done along the curve, ie avoid DupliFrames. Another cool thing would be to set a translation factor for the whole chain of duplicates, to have them all progressively rotate or scale as they cascade into the distance. Alas, this simple version is all I have time for.
Enjoy!
bl_info = {
"name": "Duplicate Multiple Linked",
"description": "Copies the selected object into multiple linked duplicates, optionally parented under an empty.",
"author": "This script is public domain",
"version": (0,1),
"blender": (2, 5, 7),
"api": 36138,
"location": "View3D > Object",
"warning": "",
"wiki_url": "",
"tracker_url": "",
"category": "Object"}
import bpy
def duplicateObject(context, numCopies, transVec, doParent):
activeObj = context.active_object
dupCopies = []
dupCopies.append(activeObj)
while numCopies > 0:
bpy.ops.object.duplicate_move_linked(OBJECT_OT_duplicate={"linked":True, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":transVec, "release_confirm":False})
dupCopies.append(context.active_object)
numCopies -= 1
if doParent:
groupName = activeObj.name + "_Copies"
bpy.ops.object.add(type='EMPTY')
groupEmpty = context.active_object
groupEmpty.name = groupName
for i in dupCopies:
bpy.ops.object.select_name(name=i.name, extend=True)
bpy.ops.object.select_name(name=groupEmpty.name, extend=True)
bpy.ops.object.parent_set(type="OBJECT")
else:
for i in dupCopies:
bpy.ops.object.select_name(name=i.name, extend=True)
class multiDuplicate(bpy.types.Operator):
bl_idname = "object.multi_duplicate"
bl_label = "Duplicate Multiple Linked"
bl_options = {"REGISTER", "UNDO"}
my_int = bpy.props.IntProperty(name="Number of Copies:", default=1, description="Number of copies", min=1, max=200, subtype="NONE")
my_floatvec = bpy.props.FloatVectorProperty(name="XYZ Offset:", default=(0.0,0.0,0.0), min=-1000, max=1000, description="XYZ Offset")
my_bool = bpy.props.BoolProperty(name="Parent under Empty", default=1)
@classmethod
def poll(cls, context):
ob = context.object
if ob == None:
return False
elif ob.select:
return True
return False
def execute(self, context):
duplicateObject(context, self.my_int, self.my_floatvec, self.my_bool)
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
def menu_draw(self, context):
self.layout.operator_context = 'INVOKE_REGION_WIN'
self.layout.operator(multiDuplicate.bl_idname, "Duplicate Multiple Linked")
def register():
bpy.utils.register_module(__name__)
bpy.types.VIEW3D_MT_object.append(menu_draw)
def unregister():
bpy.types.VIEW3D_MT_object.remove(menu_draw)
bpy.utils.unregister_module(__name__)
if __name__ == '__main__':
register()