1
$\begingroup$

I'm currently creating a script to do the following:

  1. Generate a UV map via Smart UV Project.
  2. Rename the UV map "BaseMaterial"
  3. Add a new UV layer
  4. Rename the second UV layer to "Lightmap"
  5. Repeat for every object within the selection

The code currently works, but only on a select few objects out of the hundred or so I am trying to run the script on. I have no idea why it only works on some objects, and constantly changes which objects it works correctly on. When it fails, it gives me this error: KeyError: 'bpy_prop_collection[key]: key "UVMap" not found'

This is my first time trying to write a script for blender, on top of having no prior python experience. So excuse the code if it's a copy/pasted mess of different functions.

import bpy

# Get all objects in selection
selection = bpy.context.selected_objects


# Get the active object
active_object = bpy.context.active_object

# Deselect all objects
bpy.ops.object.select_all(action='DESELECT')

for obj in selection:
    # Select each object
    obj.select_set(True)
    # Make it active
    bpy.context.view_layer.objects.active = obj
    # Toggle into Edit Mode
    bpy.ops.object.mode_set(mode='EDIT')
    # Select the geometry
    bpy.ops.mesh.select_all(action='SELECT')
    # Call the smart project operator
    bpy.ops.uv.smart_project()
    #duplicate and name UV's
    for uvmap in  obj.data.uv_layers :
        uvmap.name = 'BaseMaterial'
        bpy.ops.mesh.uv_texture_add()
        bpy.data.meshes[(bpy.context.active_object.name)].uv_layers['UVMap'].name = 'Lightmap'

# Toggle out of Edit Mode
    bpy.ops.object.mode_set(mode='OBJECT')
    # Deselect the object
    obj.select_set(False)

# Restore the selection
for obj in selection:
    obj.select_set(True)

# Restore the active object
bpy.context.view_layer.objects.active = active_object
```
$\endgroup$
2
  • $\begingroup$ maybe you selected objects that don't support uv maps ? Try adding if obj.type != "MESH": continue right after for obj in selection: $\endgroup$
    – Gorgious
    May 31, 2022 at 5:44
  • $\begingroup$ Unfortunately this does nothing, as all the objects I have selected are simple meshes. What's even weirder is that when I manually select 3 or 4 objects, it sometimes works, but if I select all the objects, it tends to fail on the first object. I have no idea what is causing this behavior $\endgroup$
    – microvert
    May 31, 2022 at 17:25

3 Answers 3

1
$\begingroup$

Instead of calling bpy.ops.mesh.uv_texture_add(), you should create a new uv_layer for the object by following:

object.data.uv_layers.new(name = 'UVMap')

Can be implemented to your code as: remove for uvmap... loop, instead:

obj.data.uv_layers['UVMap'].name = 'BaseMaterial'
obj.data.uv_layers.new(name = 'Lightmap')
    
$\endgroup$
1
$\begingroup$

Managed to get it working with a little bit of re-writing.

import bpy
selection = bpy.context.selected_objects

active_object = bpy.context.active_object

bpy.ops.object.select_all(action='DESELECT')

for obj in selection:
    if obj.type != "MESH": continue
    obj.select_set(True)

    bpy.context.view_layer.objects.active = obj

    obj.data.use_auto_smooth = 1

    bpy.ops.object.mode_set(mode='EDIT')

    bpy.ops.mesh.select_all(action='SELECT')

    while(len(obj.data.uv_layers)):
        bpy.ops.mesh.uv_texture_remove()

    bpy.ops.uv.smart_project(angle_limit=66, island_margin=0.001, area_weight=0.0, correct_aspect=True, scale_to_bounds=False)

    bpy.ops.mesh.uv_texture_add()
    for index,uvmap in  enumerate(obj.data.uv_layers) :
        if index == 0:
            uvmap.name = 'BaseMaterial'
        else:
            uvmap.name = 'Lightmap'

    bpy.ops.object.mode_set(mode='OBJECT')
    obj.select_set(False)

for obj in selection:
    obj.select_set(True)

bpy.context.view_layer.objects.active = active_object
```
$\endgroup$
1
  • $\begingroup$ Can you explain what you did differently and why? $\endgroup$
    – Kirbinator
    Jun 2, 2022 at 17:25
0
$\begingroup$

Your code is working ok with no issues when I run it, the error might be elsewhere in the code, does the console show you where the KeyError 'UVMap' is? But apparently, you try to access the uv_layer that doesn't exist.

$\endgroup$
2
  • 1
    $\begingroup$ the key error occurs when the code tries to rename the second UV layer. Apparently, the code fails because the script fails to create a new uv layer for the object so UVMap doesn't exist. But i have no idea what causes this behavior $\endgroup$
    – microvert
    May 31, 2022 at 17:22
  • $\begingroup$ @microvert Probably It's because the object uv_layers you are trying to access is not active, meaning bpy.ops.mesh.uv_texture_add() is not running properly, I'll show how edited code should look like below $\endgroup$
    – kemplerart
    Jun 1, 2022 at 14:43

You must log in to answer this question.

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