Alternative Blender Python snippets

I’m collecting all these neat bits of code as I figure them out, so I thought I’d make them available to everyone. The collection grows by the week and might contain insight to any newcomer to python programming in relation to blender. It’s not a personal blog, it’s only for code snippets. Hope this is the right place to mention this.

Nice idea, thanks!

Great idea
2 questions though:

Wouldn’t it be even better if there was like a category index, or at least a tag cloud to sift through the snippets?

Also code highlighting is nice I must say… but is there a bbcode tag or something to post a snippet in the comments?

Thanks for your effort!

I wanted to comment on your entry padding a number with zeroes, but your blog doesn’t let me if I don’t have any of those accounts from the drop down, so I’m commenting here.

For zero padding there’s a builtin string formatting:
“%03d” % 2 returns “022”
“%04d” % 22 returns “0022”

Docs: http://docs.python.org/py3k/library/string.html#format-specification-mini-language

That’s beautiful sanne! I will adjust the entry thank you. The option for non registered users to comment has now been enabled.

1 Yep, Done! If there is enough interest i will look around for alternative hosting, maybe even stick this on the wiki.

2 yes it would, but i’m not aware that the blog interface allows that. I use syntaxhighlighter it uses <pre name=“code” class=“Python”></pre>

  1. Nice, that was fast
  2. Yep, that what I thought, I tried but the comment system escapes/filters html tags

An alternative to Sanne method:


i = 4
print(str(i).zfill(3))
&gt;&gt;&gt; '004'

Thanks for that equally nifty alternative nfloyd!

This goes to show that a python script can be written in 20 lines or 300 lines if the standard library is utilized. I think in future I will leave my old ‘archaic code’ in place and offer improved solutions below, so people can see what the differences can be.

I didn’t know zfill, what a handy method! Thank you, nfloyd. Python is so versatile!

Thanks for changing the comment requirements on your blog, zeffii.

yeah the zfill is useful if you don’t know until runtime what the pad number will be.

Sanne I’m quite happy every time I learn about more convenient approaches. “Living higher up the food chain” I think it’s important to keep a repository of these tricks.

Yes, me too. It’s still a good exercise to code it yourself, though. :slight_smile:

I certainly agree with that.

But sometimes, there’s no need to reinvent the wheel. Usually, if what I’m looking to accomplish seem pretty straightforward, I’ll check in the python standard library.

If I come up empty handed, I assume someone else had had the same need as me, and search for an answer. stackoverflow.com is in my opinion a great ressource.

Actually, one week ago, I didn’t knew about zfill (found out in stackoverflow). I used it in the following function. (Feel free to add it to your snippets)


def generate_name(list, default_name="unnamed", z_padding=3):
    '''
    generate a 'unique' name, assuming a list of items with a name property
    '''
    names = []
    for item in list:
        item_name = item.name
        if item_name.startswith(default_name):
            names.append(item_name)
    names.sort()
    try:
        last_name = names[-1]
        suffix = last_name.rpartition('.')[2]
        if suffix.isnumeric():
            suffix = str(int(suffix) + 1).zfill(z_padding)
        else:
            if suffix == default_name:
                suffix = "1".zfill(z_padding)
        generated_name = ".".join([default_name, suffix])
    except: # len(names) == 0
        generated_name = default_name
    
    return generated_name

could you describe a use case for that? here’s a some boilerplate i used to test what it does : nfloydv2.py
but blender automatically does that right?

yeah stackoverflow and activestate are great for quick answers, would be cool to have that kind of cookbook functionality for blender bpy api.

Sure, when you add a new object to the scene for example, blender automatically create a unique name. But I use this function for custom data :


import bpy

class Item(bpy.types.PropertyGroup):
    name = bpy.props.StringProperty()

class Data(bpy.types.PropertyGroup):
    item_list = bpy.props.CollectionProperty(type=Item)

bpy.types.Scene.custom_data = bpy.props.PointerProperty(type=Data)

def new_item(list):
    new_item = list.add()
    new_item.name = generate_name(list)
    return new_item

def generate_name(list, default_name="unnamed", z_padding=3):
    '''
    generate a 'unique' name, assuming a list of items with a name property
    '''
    names = []
    for item in list:
        item_name = item.name
        if item_name.startswith(default_name):
            names.append(item_name)
    names.sort()
    try:
        last_name = names[-1]
        suffix = last_name.rpartition('.')[2]
        if suffix.isnumeric():
            suffix = str(int(suffix) + 1).zfill(z_padding)
        else:
            if suffix == default_name:
                suffix = "1".zfill(z_padding)
        generated_name = ".".join([default_name, suffix])
    except: # len(names) == 0
        generated_name = default_name
    
    return generated_name


scn = bpy.context.scene
list = scn.custom_data.item_list
item = new_item(list)
print(item.name)

does this cover your special cases?


def generate_name(mlist, name="unnamed", z_padding=3):
    <b>'''
    generate a 'unique' name, assuming a list of items with a name property

    name :      defaults to 'unnamed' when not passed.
    z_padding : indicates the string length to pad.
    '''</b>
    names = []        
    for i in mlist:
        match = re.search(name, i.name)
        if match == None: continue
        if (match.group() == name):
            names.append(i.name)
            # print(i.name)

    if(len(names))== 0: return name
    if(len(names))== 1: return name+"."+("1".zfill(z_padding))
            
    names = sorted(names)
    match = re.search('\d+',names[-1])

    nextnum = int(match.group())+1
    return name + "." + (str(nextnum)).zfill(z_padding)

print(generate_name(my_list, z_padding=3))

I can’t try it right now, but it seems to me to be a functional equivalent, using regex instead of string methods.

But I think that in your implementation there’s a catch in case the default name contains itself a numeric part ie: foo_01_bar, foobar_01. That’s why I used the .rpartition method. The regex should search for the numeric part after the ‘.’ , or search from the end of the string ( ‘\d+$’ )

maybe you would like author privileges on the blog nfloyd?

Why not? I not sure I would be as prolific as you, but I could certainly come up with some recipes learned along the way.

I just had a look at the stack exchange network. In fact there’s a proposition in the staging area for a new site for 3D Graphics, Modeling & Applications :

http://area51.stackexchange.com/proposals/5022/3d-graphics-modeling-applications

For now, it still requires more users to commit to it. I didn’t saw it, but apparently there was a mention about it on blenderartists.

I must say that it would be a great platform to collect the knowledge that is kind of buried after a while in these forums

it would be cool to see that stackexchange proposal move into beta some day! …thought i signed up to it a year ago, but it seems i didnt! ashamed