othman alazzam
othman alazzam

Reputation: 29

Loop doesn't work, 3-lines python code

this question is about blender, python scripting

I'm completely new in this, so please excuse me for any stupid/newbie question/comment.

I made it simple (3 lines code) to make it easy addressing the problem.

what I need is a code that adds a new uv map for each object within loop function.

But this code instead is adding multiple new UV maps to only one object.

import bpy
for x in bpy.context.selected_objects:
    bpy.ops.mesh.uv_texture_add()

what's wrong I'm doing here??

Thanks

Upvotes: 1

Views: 1625

Answers (3)

Jake Dube
Jake Dube

Reputation: 2990

Similar to what Sambler said, I always use:

for active in bpy.context.selected_objects:
    bpy.context.scene.objects.active = active
    ...

These two lines I use more than any other when programming for Blender (except import bpy of course).

I think I first learned this here if you'd like a good intro on how this works:

https://cgcookiemarkets.com/2014/12/11/writing-first-blender-script/

In the article he uses:

# Create a list of all the selected objects
selected = bpy.context.selected_objects

# Iterate through all selected objects
for obj in selected:
    bpy.context.scene.objects.active = obj
    ...

His comments explain it pretty well, but I will take it a step further. As you know, Blender lacks built-in multi-object editing, so you have selected objects and one active object. The active object is what you can and will edit if you try to set its values from python or Blender's gui itself. So although we are writing it slightly differently each time, the effect is the same. We loop over all selected objects with the for active in bpy.context.selected_objects, then we set the active object to be the next one in the loop that iterates over all the objects that are selected with bpy.context.scene.objects.active = active. As a result, whatever we do in the loop gets done once for every object in the selection and any operation we do on the object in question gets done on all of the objects. What would happen if we only used the first line and put our code in the for loop?

for active in bpy.context.selected_objects:
    ...

Whatever we do in the loop gets done once for every object in the selection but any operation we do on the object in question gets done on only the active object, but as many times as there are selected objects. This is why we need to set the active object from within the loop.

Upvotes: 2

sambler
sambler

Reputation: 7079

The uv_texture_add operator is one that only works on the current active object. You can change the active object by setting scene.objects.active

import bpy
for x in bpy.context.selected_objects:
    bpy.context.scene.objects.active = x
    bpy.ops.mesh.uv_texture_add()

Upvotes: 0

varesa
varesa

Reputation: 2419

note: I am not really familiar with blender

It seems that bpy.ops operations depend on the state of bpy.context. The context can also be overridden per-operation.

I assume that uv_texture_add() only works on a single object at a time?

Try something like this:

import bpy

for x in bpy.context.selected_objects:
    override = { "selected_objects": x }
    bpy.ops.mesh.uv_texture_add(override)

That should run the operations as if only one object was selected at a time.

Source:
https://www.blender.org/api/blender_python_api_2_63_17/bpy.ops.html#overriding-context

Upvotes: 0

Related Questions