4
$\begingroup$

I wrote a script that can detect similar objects based on the selected objects but can't put them in a collection named after selected objects.

It's not working.


import bpy 

selected_objects = bpy.context.selected_objects

for selected_object in selected_objects:
    name = selected_object.name
    collections = bpy.data.collections.new(name)
    bpy.context.scene.collection.children.link(collections)
    bpy.ops.object.select_pattern(pattern=f"*{name}*")
    objs = bpy.context.selected_objects
    coll = bpy.data.collections[name]

    for obj in objs:
        cols = obj.users_collection
        coll.objects.link(obj)
        for col in cols:
        col.objects.unlink(obj)

I want from:

enter image description here

To:

enter image description here

$\endgroup$
2
  • 1
    $\begingroup$ @RobinBetts: That's what he wrote ;) "I want to make a python script" -> i assume he wants to do this more than 100x and automated - so a python script makes sense. $\endgroup$
    – Chris
    May 8, 2021 at 6:39
  • $\begingroup$ @Chris Quite right. Deleted. $\endgroup$
    – Robin Betts
    May 8, 2021 at 6:43

3 Answers 3

6
$\begingroup$

I would do the same in python that I could do in the UI, which is to use Select Pattern, and then move these selected items to a Collection.

In python:

bpy.ops.object.select_all( action='DESELECT' ) # Deselect all objects
bpy.ops.object.select_pattern(pattern="Sphere*")

# if collection Sphere does not yet exist:
bpy.ops.object.move_to_collection( collection_index=0, is_new=True, new_collection_name='Sphere' ) # new collection
# else if collection Sphere does exist:
bpy.ops.object.move_to_collection( collection_index=2 ) # need collection index


$\endgroup$
3
  • $\begingroup$ Somewhat related, joining instead of adding to collection. blender.stackexchange.com/a/166446/15543 $\endgroup$
    – batFINGER
    May 7, 2021 at 19:49
  • 1
    $\begingroup$ i wish the select pattern would be there in the open file menu.... :( $\endgroup$
    – Chris
    May 8, 2021 at 6:42
  • $\begingroup$ @Chris, if you mean Append or Link or File Open.... someone recently pointed out to me, it exists in a rather crude way in Append or Link. To the right of the File View, Directory Path, is a search text box labeled in the helptext as search filter. I think it's inferior but usable. screencap for Append, filename, Objects at dropbox.com/s/pimmjg9yy7fda5p/blenderNameFilter.png $\endgroup$
    – james_t
    May 8, 2021 at 18:28
3
$\begingroup$

Here is another script where Collection names are used, with link and unlink:

bpy.ops.object.select_all( action='DESELECT' ) # Deselect all objects
bpy.ops.object.select_pattern(pattern="Sphere*")
objs = bpy.context.selected_objects

sphColl = bpy.data.collections['Spheres']

for obj in objs:
    print(obj)
    cols = obj.users_collection # ptr to current collection
    sphColl.objects.link(obj) # link into 'Spheres' collection
    print(cols)
    for col in cols:
        col.objects.unlink( obj ) # unline from original collection
$\endgroup$
3
$\begingroup$

Object to collection by name.

Similarly to https://blender.stackexchange.com/a/166446/15543 can do this with API methods.

  • Sort all objects in scene by name (could change this to selected objects if desired)

  • Get the name up to the ".", eg for "Cube.022" this is "Cube", and all objects that start with this name

  • Move to collection of same name. Make a new collection and link to scene collection if need be. This will ensure can run this again and again and again without moving "Cube" to collection named "Cube.001" then "Cube.002" etc

  • Repeat until all objects moved.

  • Optionally remove any collections left with zero objects.

Test script.

import bpy

context = bpy.context
scene = context.scene
obs = scene.objects[:]
obs.sort(key=lambda o: o.name)

def move(name, obs):
    # unlink from old collections
    for o in obs:
        for c in o.users_collection:
            c.objects.unlink(o)
    # make a new collection and link to it
    coll = bpy.data.collections.get(name)
    if not coll:
        coll = bpy.data.collections.new(name)
        scene.collection.children.link(coll)
    for o in obs:
        coll.objects.link(o)
    

while obs:
    name = obs[0].name.split(".")[0] 
    x = [o for o in obs if o.name.startswith(name)]
    move(name, x)
    obs = obs[len(x):]
    
# remove any now empty collections

empty_colls = [c for c in bpy.data.collections if not len(c.all_objects)]

while empty_colls:
    bpy.data.collections.remove(empty_colls.pop())
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .