Python - Grouping objects

I ran into a problem with a script I am working on. I pulled out the bits that have to do with my problem. The problem in this script is the same.

What I am trying to do:
*Establish a group (seems to require an object- cannot create group without anything in it)
*Somehow keep track of that group by a variable within the script
*As I add objects, I need to add them to the existing group

Here’s the code:
http://www.pasteall.org/21610/python

Thanks!

To get you started:

Do this experiment with nothing selected. A scene with 3 objects : Cube1, Cube2, Cube3


>>> bpy.ops.group.create(name="myGroup")
{'FINISHED'} # will not appear in outliner yet.

>>> bpy.ops.object.select_name(name="Cube1") 
{'FINISHED'}

&gt;&gt;&gt; bpy.ops.object.group_link(<b>group="myGroup"</b>)
{'FINISHED'}

The result of the above code should be that the object becomes part of “myGroup”

Now manually un-group it again, and un-select everything. If you want all of them added you could do:


# stick this into the console too
objects_to_add = "Cube1","Cube2","Cube3"
for name in objects_to_add:
    bpy.ops.object.select_name(name=name)
    bpy.ops.object.group_link(group="myGroup")


Ok, so I tried your examples and it didn’t work exactly like it should.

First example
*When creating a group with nothing selected, the empty group doesn’t show up in the scene outliner, but I found it exists as a datablock.
*linking the objects, didn’t link to myGroup, it made a new group.

Second example
*works only if group exists already

Thanks for the tips. They help- API help isn’t very descriptive :slight_smile:
Ill let you know if this works in my script.

i really don’t want to bump this thread, but it is necessary to clarify a few things. using group_link() (without an argument) can result in some unexpected results, but that’s what experiments are for, right?

with nothing selected, and 3 cubes (Cube1, Cube2 and Cube3) in the scene


bpy.ops.group.create(name="myGroup") # will not appear in outliner until objects are linked.
objects_to_add = "Cube1","Cube2","Cube3"
for name in objects_to_add:
    bpy.ops.object.select_name(name=name)
    bpy.ops.object.group_link(group="myGroup")

maybe you can mark solved, because there is no question this works!

The following is a snippet from a script I wrote as an alternative to using operators. It checks for the existence of a named group and creates it if needed. It then adds the active object to this named group if it is not already a group member.


import bpy

obj = bpy.context.object
group_name = "myGroup"

if group_name in bpy.data.groups:
    group = bpy.data.groups[group_name]
else:
    group = bpy.data.groups.new(group_name)

if not obj.name in group.objects:
    group.objects.link(obj)

Hope this helps. :slight_smile:

Yes, thanks a bunch :slight_smile:

@Funkyworm Thanks, This gives me ideas about how to deal with when there’s already a group with the same name and you don’t want to get it named “myGroup.001” etc.


import bpy

Number = 000 #not sure exactly how to store it this way with leading zeros
group_name = "myGroup" +"." + number 

Exists = 1
while Exists == 1: 
    if group_name in bpy.data.groups: #test if exists
        Number += 1
        group_name = "myGroup" +"." + Number #try again with higher number appended    
    else
        Exists = 0
        group_name = "myGroup" +"." + Number #Create it, no matches


Haven’t tried this yet though
Just Idea :slight_smile:
@zeffii Thanks for the help Too!

An alternative is to allow Blender to work voodoo on the new group name then read it back…


import bpy

group_name = 'Group'
group = bpy.data.groups.new(group_name)
actual_group_name = group.name

print(group_name, actual_group_name)

Run the above code a few times and you will see a number of new groups created called Group, Group.001, Group.002, etc. The group names increment, but the script always has access to the actual_group_name of the last-created group.

The script creates a group asking for a name to be given to it, but if this name is already taken then Blender will increment the number and give the new group a name+number. If a reference to the group is stored when the script creates the group, it is possible to read back the actual name after the group has been created and see what name Blender has actually given to the group (as I do in the code above… this code looks small but runs quite well).

hmm ill have to try that. I thought I was doing something like that earlier but couldn’t get access to its name that way. Is the group a pointer-like variable (my terminology is fuzzy) that points to the actual Group in blender, or is it a copy that only can be edited locally in the script.

Everything in Python is an object. The variable <group> in my script above is a reference to the actual data object. Editing the data object will alter the raw data in Blender. Most objects are accessed by reference this way. Operators are a safer way of doing things in macros, but for scripts the data api is great. :slight_smile:

Blender’s new Python api is powerful. :smiley:

A useful code structure is…


import bpy

'''
for &lt;object&gt; in &lt;data_structure&gt;:
    doStuff()
'''

for group in bpy.data.groups:
    print(group.name)