2
$\begingroup$

After hours of arguing with my code (Trying to eliminate some uv_layers), I'm trying this script directly in the console:

for uv in C.object.data.uv_layers:
    C.object.data.uv_layers.remove(uv)

This is producing unexpected results, including partial, but not complete, deletion of all uv_layers (Uv Map) I would have expected all maps to be deleted. In addition in some cases I get strange errors, with uv_layers names that are not even present in the C.object.data.uv_layers list.

I would like to be sure that we are talking about a bug, in this case I would eliminate the question right away. If not, I'd like to know if I'm doing something wrong.

A simple test is to add a dozen or more uv_layers, manually, and run this code The result: enter image description here

$\endgroup$

2 Answers 2

7
$\begingroup$

Try a while loop.

Rather than looping thru a list you are removing from, it is often a better to make a copy of that list and pop and remove until list exhausted.

Using pop() is taking from the end of the list.

>>> me = C.object.data
>>> me
bpy.data.meshes['Suzanne']


>>> uvlayers = me.uv_layers[:]
>>> while uvlayers:
...     me.uv_layers.remove(uvlayers.pop())
$\endgroup$
4
  • 3
    $\begingroup$ so I guess this is another example in which it is a bad idea to mutate a list that is currently iterated over. More like a generic Python topic than a Blender specific one, right? $\endgroup$
    – aliasguru
    Aug 22, 2020 at 15:07
  • $\begingroup$ Ok, this seems to work fine, but how can I avoid deleting a certain uv_layers? assuming that a me.uv_layers['My uv map'] must remain on the list? $\endgroup$
    – Noob Cat
    Aug 22, 2020 at 15:12
  • $\begingroup$ @aliasguru Pretty much. When iterating as in question code I often get eg RuntimeError: Error: Texture layer 'UVMap.003' not found Appears blender is resetting the active index and possibly reordering the list in doing so. I use "while pop" by default. @N $\endgroup$
    – batFINGER
    Aug 22, 2020 at 15:16
  • 1
    $\begingroup$ @NoobCat remove any not to be removed from list copy. uv_layers. $\endgroup$
    – batFINGER
    Aug 22, 2020 at 15:17
3
$\begingroup$

Other solution (for completeness) is to walk the list from last element to first one with a for loop. It is more error-prone than copying the full list as suggested by the other answer. Moreover since there will be at most 8 UV Maps the potential speed gain is null.

import bpy

layers = bpy.context.object.data.uv_layers

for uv_layer in reversed(layers):
    layers.remove(uv_layer)
$\endgroup$
1
  • $\begingroup$ Right, I hadn't thought about it, I was aware of it, but it escaped me. Sounds like a good observation. $\endgroup$
    – Noob Cat
    Aug 24, 2020 at 13:27

You must log in to answer this question.

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