Object array script

I’m doing script, who array object along curve.

And…I need to duplicate (linked) active object.
How I make active object via python?

My problem is 51 line.

class OBJECT_PT_follow(bpy.types.Panel):
    bl_label = "Follow Script"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
    curv=0;
    ob=0;
 
    def draw(self, context):
        layout = self.layout
 
        obj = context.object
 
        row = layout.row()
        row.label(text="Script Follow Curve", icon='WORLD_DATA')
 
        row = layout.row()
        row.label(text="Active object is: " + obj.name)
        row = layout.row()
        #*************************************************************************************************
        if obj.type=='CURVE':
            row.prop(obj, "name", "Curve Name", "CURVE_DATA")
            bpy.types.OBJECT_PT_follow.curv=obj
        else:
            row.prop(obj, "name", "Object Name", "OBJECT_DATA")
            bpy.types.OBJECT_PT_follow.ob=obj
        #*************************************************************************************************
        if bpy.types.OBJECT_PT_follow.curv!=0:
            row = layout.row()
            row.label(text="Selected Curve:  "+bpy.types.OBJECT_PT_follow.curv.name, icon='CURVE_DATA')
        #************************************************************************************************
        if bpy.types.OBJECT_PT_follow.ob!=0:
            row = layout.row()
            row.label(text="Selected Object:  "+bpy.types.OBJECT_PT_follow.ob.name, icon='OBJECT_DATA')


        row = layout.row()
        row.operator("efollow", text="go!")
       

class OBJECT_OT_execute_follow(bpy.types.Operator):
    bl_label = "efollow"
    bl_idname = "efollow"
    bl_description = "Move to curve"

    def invoke(self, context, event):
        print(bpy.types.OBJECT_PT_follow.curv)
        print(bpy.types.OBJECT_PT_follow.ob)
        
        print(bpy.types.OBJECT_PT_follow.ob.name)
        bpy.ops.object.select_name(name=bpy.types.OBJECT_PT_follow.ob.name)
        bpy.ops.object.duplicate_move()
        #bpy.ops.object.constraint_add(type='FOLLOW_PATH')
        #bpy.types.Object(ob).constraints["Follow Path"].use_curve_follow=1
        #bpy.types.Object(ob).constraints["Follow Path"].target=curv    
        return {'FINISHED'}

bpy.types.register(OBJECT_OT_execute_follow)
bpy.types.register(OBJECT_PT_follow)

okay, the thing that went wrong here, is that you tried to save values in a panel, which doesnt like to remember things. so instead we save values in the current scene

i changed you script to the following:


class OBJECT_PT_follow(bpy.types.Panel):
    bl_label = "Follow Script"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
    # initiate the variables once
    bpy.context.scene["curv"] = ""
    bpy.context.scene["ob"] = ""
 
    def draw(self, context):
        layout = self.layout
        # get current scene
        sce = bpy.context.scene
 
        # there can be more than one object selected, take the active one
        obj = context.active_object
 
        row = layout.row()
        row.label(text="Script Follow Curve", icon='WORLD_DATA')
 
        row = layout.row()
        row.label(text="Active object is: " + obj.name)
        row = layout.row()
        #*************************************************************************************************
        if obj.type=='CURVE':
            row.prop(obj, "name", "Curve Name", "CURVE_DATA")
            # save the objects name in the curve variable
            sce["curv"] = obj.name
        else:
            row.prop(obj, "name", "Object Name", "OBJECT_DATA")
            # save the objects name in the obj variable
            sce["ob"] = obj.name
        #*************************************************************************************************
        if sce["curv"]: # if the curve variable is not empty
            row = layout.row()
            row.label(text="Selected Curve:  " + sce["curv"], icon='CURVE_DATA')
        #************************************************************************************************
        if sce["ob"]: # if the obj variable is not empty
            row = layout.row()
            row.label(text="Selected Object:  " + sce["ob"], icon='OBJECT_DATA')


        row = layout.row()
        row.operator("efollow", text="go!")
       

class OBJECT_OT_execute_follow(bpy.types.Operator):
    bl_label = "efollow"
    bl_idname = "efollow"
    bl_description = "Move to curve"

    def invoke(self, context, event):
        sce = bpy.context.scene
        if sce["ob"]:
            # get object with name stored in the ob variable
            obj = bpy.data.objects[sce["ob"]]
            # print it for confirmation
            print(obj.name)
        else:
            # none was selected so far, cancel operator
            print("no object selected")
            return {'CANCELLED'}
        if sce["curv"]:
            curve = bpy.data.objects[sce["curv"]]
            print(curve.name)
        else:
            print("no curve selected")
            return {'CANCELLED'}
        # and now you have two variables (obj and curve) that are the object and curve
        # and you can do what you want :P
        #bpy.ops.object.select_name(name=bpy.types.OBJECT_PT_follow.ob.name)
        #bpy.ops.object.duplicate_move()
        #bpy.ops.object.constraint_add(type='FOLLOW_PATH')
        #bpy.types.Object(ob).constraints["Follow Path"].use_curve_follow=1
        #bpy.types.Object(ob).constraints["Follow Path"].target=curv    
        return {'FINISHED'}

bpy.types.register(OBJECT_OT_execute_follow)
bpy.types.register(OBJECT_PT_follow)

hope that helped

Why not just use the built in array modifier along a curve?

Is there a reason for re-inventing the wheel or just an exercise in coding?

dreampainter
Your script works is exactly the same, but… thx.

Atom

Array modifier copies mesh data (and deform her), not object. Me need to copy objects without deformations, and with its own local coordinates for each copies.

Me need to known how copy selected object (not active). Very need.

in blender active object is the last selected object!
try this


class OBJECT_OT_execute_follow(bpy.types.Operator):
    bl_label = "efollow"
    bl_idname = "efollow"
    bl_description = "Move to curve"

    def invoke(self, context, event):
        #first deselect all
        bpy.ops.object.select_all(action='DESELECT')
        #after select desired object
        bpy.data.objects[bpy.types.OBJECT_PT_follow.ob.name].selected = True
        active = context.active_object
        
        #add constraint to base object
        const_col = active.constraints
        const = const_col.new(type='FOLLOW_PATH')
        const.name="followCurve"
        const.use_curve_follow=1
        #can also be negative!!! depend on direction of curve
        const.offset = 3
        #depend on direction of curve
        const.forward = 'FORWARD_Y'
        const.target=bpy.types.OBJECT_PT_follow.curv
        
        #dupli with shared mesh the object base (the active)
        obj_new = bpy.ops.object.duplicate(linked=True)
        return {'FINISHED'}

bpy.types.register(OBJECT_OT_execute_follow)
bpy.types.register(OBJECT_PT_follow)

ops! error
You must use
active=context.scene.objects[bpy.types.OBJECT_PT_follow.ob.name]

orinoco56
Big THX man! it works.

And another question:

How to get access of parameter offset constraint “Follow path”? (69 line)

And…

How I may control count of duplicate object (like “Array” modifier)?


class OBJECT_PT_follow(bpy.types.Panel):
    bl_label = "Follow Script"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
    curv=0;
    ob=0;
 
    def draw(self, context):
        layout = self.layout
 
        obj = context.object
 
        row = layout.row()
        row.label(text="Script Follow Curve", icon='WORLD_DATA')
 
        row = layout.row()
        row.label(text="Active object is: " + obj.name)
        row = layout.row()
        #*************************************************************************************************
        if obj.type=='CURVE':
            row.prop(obj, "name", "Curve Name", "CURVE_DATA")
            bpy.types.OBJECT_PT_follow.curv=obj
        else:
            row.prop(obj, "name", "Object Name", "OBJECT_DATA")
            bpy.types.OBJECT_PT_follow.ob=obj
        #*************************************************************************************************
        if bpy.types.OBJECT_PT_follow.curv!=0:
            row = layout.row()
            row.label(text="Selected Curve:  "+bpy.types.OBJECT_PT_follow.curv.name, icon='CURVE_DATA')
        #************************************************************************************************
        if bpy.types.OBJECT_PT_follow.ob!=0:
            row = layout.row()
            row.label(text="Selected Object:  "+bpy.types.OBJECT_PT_follow.ob.name, icon='OBJECT_DATA')


        row = layout.row()
        row.operator("efollow", text="go!")
       

class OBJECT_OT_execute_follow(bpy.types.Operator):
    bl_label = "efollow"
    bl_idname = "efollow"
    bl_description = "Move to curve"

    def invoke(self, context, event):
        #first deselect all
        bpy.ops.object.select_all(action='DESELECT')
        #after select desired object
        bpy.data.objects[bpy.types.OBJECT_PT_follow.ob.name].selected = True
        active=context.scene.objects[bpy.types.OBJECT_PT_follow.ob.name] 
        
        #add constraint to base object
        const_col = active.constraints
        const = const_col.new(type='FOLLOW_PATH')
        const.name="followCurve"
        const.use_curve_follow=1
        #can also be negative!!! depend on direction of curve
        const.offset = 3
        #depend on direction of curve
        const.forward = 'FORWARD_Y'
        const.target=bpy.types.OBJECT_PT_follow.curv

        active.location=bpy.types.OBJECT_PT_follow.curv.location
        #dupli with shared mesh the object base (the active)
        obj_new = bpy.ops.object.duplicate(linked=True)
        active=bpy.context.active_object
        active.location=bpy.types.OBJECT_PT_follow.curv.location
        bpy.types.Object(active.name).constraints["Follow Path"].offset=16;
        return {'FINISHED'}

bpy.types.register(OBJECT_OT_execute_follow)
bpy.types.register(OBJECT_PT_follow)

I have see a little problem in my script
“const” is a reserved word of python so it’s better and much clear to use “constraint”
“constraint” is the object where you set all your parameters
contraint.offset = 16
To control the number use a for statement
PROBLEMS:
bpy.ops.object.duplicate(linked=True) function is not made to return an object
So how to select the new duplicated object and acess the constraint parameter?
One possibility is that, I think…


class OBJECT_OT_execute_follow(bpy.types.Operator):
    bl_label = "efollow"
    bl_idname = "efollow"
    bl_description = "Move to curve"

    def invoke(self, context, event):
        #first deselect all
        bpy.ops.object.select_all(action='DESELECT')
        #after select desired object
        bpy.data.objects[bpy.types.OBJECT_PT_follow.ob.name].selected = True
        active=context.scene.objects[bpy.types.OBJECT_PT_follow.ob.name] 
        
        #add constraint to base object. 
        const_col = active.constraints
        #Set here all the parameters for constraint
        constraint = const_col.new(type='FOLLOW_PATH')
        constraint.name="followCurve"
        constraint.use_curve_follow=1
        #can also be negative!!! depend on direction of curve
        constraint.offset = 0
        #depend on direction of curve
        constraint.forward = 'FORWARD_Y'
        constraint.target=bpy.types.OBJECT_PT_follow.curv

        #Here you can use a for statement
        for obj in range(10):
            bpy.ops.object.duplicate(linked=True)
            active = bpy.context.selected_editable_objects 
            #constraint object! Here you set parameter for the duplicate
            constraint =  active[0].constraints[0] 
            constraint.offset = -16 *(obj+2)
            
        #NOT HERE! Above on the "constraint" variable  lines(21...28) for object base or lines(77...78) for duplicates
        #bpy.types.Object(active.name).constraints["Follow Path"].offset=16;
        return {'FINISHED'}

man… it’s bad… offset parametr changes only by integer value, who = 0,2 blender units. Fixed position also did not usable. :frowning:

Hmmm…

Thanx for you asistense.