0
$\begingroup$

OK, from the selected objects, I need to join one selected object with the active object and execute some other code. Then from the others select the next selected object and then execute the code again. I thought the following would work ,but it does all at the same.

import bpy

SEL_OBJS = bpy.context.selected_objects
ACT_OBJ = bpy.context.active_object    

#Join one at a time and execute more code
for OBJS in SEL_OBJS:
    bpy.ops.object.join()
    #More code here

Got my code working with the following.

import bpy

SEL_OBJS = bpy.context.selected_objects
ACT_OBJ = bpy.context.active_object

#List of all objects but the active object
SEL_NO_ACT = [o for o in SEL_OBJS if ACT_OBJ != o]

#Deselect list objects
for OBJS in SEL_NO_ACT: 
    OBJS.select_set(state=False)

#Loop list objects
while len(SEL_NO_ACT) >= 1:
    OBJS = SEL_NO_ACT.pop()
    OBJS.select_set(state=True)
    bpy.ops.object.join()
    #Run code for each object after joining 


$\endgroup$
3
  • $\begingroup$ The join operator joins all selected objects. The active object is also a selected object. This is pretty consistent behaviour for all operators in blender. $\endgroup$
    – batFINGER
    Jan 26, 2019 at 14:39
  • $\begingroup$ What I need is to enter edit mode and do intersect(knife) for each selected object. If all of them do it at the same time, it doesn't cut properly and leaves missing parts. I can manually do one at a time and it cuts fine. That's why I need a way to loop through the selected objects and execute the rest of the code for one selected object at a time. $\endgroup$
    – AFWS
    Jan 26, 2019 at 14:45
  • 1
    $\begingroup$ Simply explaining why what you thought would work, in question, doesn't. It's the equivalent of typing bpy.ops.object.join() into py console. Rather than a "what I need" comment above, edit question to clarify. $\endgroup$
    – batFINGER
    Jan 26, 2019 at 15:17

2 Answers 2

4
$\begingroup$

Essentially you need to create a list of objects based on the current selection that will not change if the selection changes.

import bpy
# store selection in list that in future will not change with selection
sel_objs = [obj for obj in bpy.context.selected_objects if obj.type == 'MESH']
bpy.ops.object.select_all(action='DESELECT')
if sel_objs:
    obj1 = sel_objs.pop()
    obj1.select = True
    bpy.context.scene.objects.active = obj1
while len(sel_objs) >= 1:
    obj2 = sel_objs.pop()
    obj2.select = True
    bpy.ops.object.join()
$\endgroup$
3
  • $\begingroup$ This was a big help.. I think the biggest thing I was missing was the "while len(sel_objs) >= 1:" I never used "while" before and that seemed to do the trick. $\endgroup$
    – AFWS
    Jan 26, 2019 at 21:21
  • $\begingroup$ @AFWS Do not hesistate to mark the answer as correct if it helped you :-) $\endgroup$ Jan 29, 2019 at 11:56
  • 1
    $\begingroup$ Was it the check next to the post? I just clicked it. Still trying to figure out how this site works. $\endgroup$
    – AFWS
    Jan 29, 2019 at 17:25
3
$\begingroup$

I found this worked quite well for me in 2.80. If you want to apply a function to each selected object, you can just do this:

def apply_to_selected_objects(fun, *args, **kwargs):
    sel_objs = [obj for obj in bpy.context.selected_objects if obj.type == 'MESH']
    bpy.ops.object.select_all(action='DESELECT')
    for obj in sel_objs:
        bpy.context.view_layer.objects.active = obj
        yield fun(obj, *args, **kwargs)
$\endgroup$

You must log in to answer this question.

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