Where to store an ordered list related to an object?


import bpy
<i>#needs follow-path-constraint on active object
#use obj.constraints.new("FOLLOW_PATH")
#to create constraint via script</i>

group=bpy.data.groups.get("Duplicates")
if(group is None):
    group=bpy.data.groups.new("Duplicates")

handled={}
    
def hndl(context):
    for str in handled.keys():
        curve=bpy.data.objects.get(str)
        stack,obj=handled[str]
        if(
            curve is not None and
            curve.is_updated and 
            curve["count"]&gt;=0 and 
            type(curve["count"]) is int
        ):
            dn=curve["count"]-len(stack)
            if(dn&lt;0):
                for i in range(-dn):
                    dupli=stack.pop()
                    group.objects.unlink(dupli)
                    bpy.context.scene.objects.unlink(dupli)
                    bpy.data.objects.remove(dupli)
            elif(dn&gt;0):
                for i in range(dn):
                    dupli=obj.copy() #also copies constraints!
                    stack.append(dupli)
                    group.objects.link(dupli) 
                    bpy.context.scene.objects.link(dupli)     
            for i,dupli in enumerate(stack):
                dupli.constraints[0].offset=curve["offset"]*i+obj.constraints[0].offset
        elif(curve is None):
            del handled[str]
    if(len(handled)==0):
       bpy.app.handlers.scene_update_post.remove(hndl)

def main(context):
    obj=bpy.context.object
    curve=obj.constraints[0].target
    curve["offset"]=4.0
    curve["count"]=10
    handled[curve.name]=([],obj)
    if(bpy.app.handlers.scene_update_post.count(hndl)==0):
        bpy.app.handlers.scene_update_post.append(hndl)
    curve.update_tag()

class FollowPathArray(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.fpath_array"
    bl_label = "FollowPathArray"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}


def register():
    bpy.utils.register_class(FollowPathArray)


def unregister():
    bpy.utils.unregister_class(FollowPathArray)


if __name__ == "__main__":
    register()

For each curve i am storing a list of duplis in a dictionary named “handled” in the module. Is there another way to realize this which is more suitable?

Is it possible to attach a list to an object?

bpy.types.Object.handled = bpy.props.CollectionProperty(…) is probably the most suitable

but you could also use id props, e.g. ob[‘handled’] = (4,1,3) # seems to remain order


bl_info = {
    "name": "FollowPathArray",
    "author": "pink vertex",
    "version": (1, 0),
    "blender": (2, 68, 0),
    "location": "Search Menu &gt; FollowPathArray",
    "description": "creates duplicates of an object with a follow-path-constraint",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "Object"}

import bpy

def main(context,count,offset,spacing):
    obj=bpy.context.object
    ctr=get_constraint(obj)
    curve=ctr.target
    group=bpy.data.groups.get("fpath.duplicates." + obj.name)
    if(group is None):
        group=bpy.data.groups.new("fpath.duplicates." + obj.name)
    for i in range(count):
        dupli=obj.copy() #also copies constraints!
        group.objects.link(dupli)
        bpy.context.scene.objects.link(dupli)
        if(spacing):
            dupli.constraints[ctr.name].offset=(curve.data.path_duration/count)*i+ctr.offset
        else:
            dupli.constraints[ctr.name].offset=offset*i+ctr.offset

def check(context):
    result=False
    obj=context.active_object
    if(obj is not None and len(obj.constraints)&gt;=1):
        if(get_constraint(obj) is not None):
            result=True
    return result

def get_constraint(obj):
    for ctr in obj.constraints:
        if(ctr.type=="FOLLOW_PATH" and ctr.target is not None):
            return ctr
    #nothing found
    return None
       
from bpy.props import BoolProperty, FloatProperty, IntProperty

class FollowPathArray(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.fpath_array"
    bl_label = "FollowPathArray"
    bl_options = {'REGISTER', 'UNDO'}
    
    offset = FloatProperty(
             name="offset",
             description="offset",
             default=0.0
             )
   
    count = IntProperty(
             name="count",
             description="number of duplicates",
             default=0,
             min=0,
             max=100
             )

    spacing=BoolProperty(name="evenly spaced")
             
    @classmethod
    def poll(cls, context):
        return check(context)

    def execute(self, context):
        main(context,self.count,self.offset,self.spacing)
        return {'FINISHED'}


def register():
    bpy.utils.register_class(FollowPathArray)


def unregister():
    bpy.utils.unregister_class(FollowPathArray)


if __name__ == "__main__":
    register()

I changed the script and removed the handler because i didn’t need it and installed it as an addon.

However occasionally when called editing the operators properties in the operator toolbar has no effect and the operator won’t be updated.

Only bpy.data.window_managers[“WinMan”].(null) = 42 is printed in the info area. How do i fix this?