1

I am trying to automate some fairly tedious model prep steps before exporting a mesh to Unity. It creates 2 extra UV maps with special conditions and then slices and resizes all the mesh faces to very small sizes using the Individual Origins pivot for each face. Unfortunately, the line of code that actually runs the resizing instantly crashes Blender with no error that I can find. I have also tried iterating through the faces to resize them individually instead of all at once.

What am I doing wrong here? I am a novice at python and blender automations but I am bumbling my way through it. The problem is the very last line. Everything else works up until then.

import os

Get the directory of the current .blend file

current_directory = os.path.dirname(bpy.data.filepath) export_directory = os.path.join(current_directory, "export")

Create the export directory if it doesn't exist

os.makedirs(export_directory, exist_ok=True)

Store the current area type

previous_area_type = bpy.context.area.type

Activate the UV/Image Editor

bpy.context.area.ui_type = 'UV'

Loop through all objects in the scene

for obj in bpy.context.scene.objects: if obj.type == 'MESH': # Remember the active object original_object = obj

    # Step 1: Create a second UV map
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.uv_texture_add()

    # Step 2: Default UV unwrap for the second UV map
    bpy.ops.uv.unwrap()

    # Step 3: Reset UVs on the second UV map
    bpy.ops.mesh.select_all(action='SELECT')  # Select all faces/UVs
    bpy.ops.uv.select_all(action='SELECT')
    bpy.ops.uv.reset()
    bpy.context.object.data.uv_layers.active.name = "ResetMap"  # Rename the second UV map

    # Step 4: Create a third UV map
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.select_all(action='DESELECT')
    original_object.select_set(True)
    bpy.context.view_layer.objects.active = original_object

    # Create a new UV map for the active object
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.uv_texture_add()
    bpy.ops.object.mode_set(mode='OBJECT')

    # Rename the UV map to "RandomMap"
    original_object.data.uv_layers[-1].name = "RandomMap"

    # Step 5: Lightmap Pack project the UVs on the third UV map
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.uv.lightmap_pack(PREF_CONTEXT='SEL_FACES', PREF_PACK_IN_ONE=True, PREF_NEW_UVLAYER=False, PREF_BOX_DIV=12, PREF_MARGIN_DIV=0.1)

    # Step 6: Switch to UV Editing mode
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.uv.unwrap(method='ANGLE_BASED')  # Angle-based unwrap for the third UV map

   # Step 7: Scale UVs on the third UV map
    bpy.context.area.type = 'IMAGE_EDITOR'
    bpy.ops.uv.select_all(action='SELECT')
    bpy.context.space_data.pivot_point = 'INDIVIDUAL_ORIGINS'
    bpy.ops.transform.resize(value=(0.01, 0.01, 0.01), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', mirror=False, use_proportional_edit=True, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False, snap=False, snap_elements={'INCREMENT'}, use_snap_project=False, snap_target='CLOSEST', use_snap_self=True, use_snap_edit=True, use_snap_nonedit=True, use_snap_selectable=False)



    # Step 8: Split the mesh 'Faces by Edges'
    bpy.context.area.ui_type = 'VIEW_3D'
    bpy.ops.mesh.select_all(action='SELECT')
    bpy.ops.mesh.split()
    bpy.context.scene.tool_settings.transform_pivot_point = 'INDIVIDUAL_ORIGINS'
    bpy.ops.transform.resize(value=(0.001, 0.001, 0.001), orient_type='LOCAL')

Ty Underwood
  • 113
  • 3

1 Answers1

3

The culprit is not the last line but bpy.context.area.ui_type = 'VIEW_3D'. You can verify this by running this minimal script

import bpy

for obj in bpy.context.scene.objects: if obj.type == 'MESH': #bpy.context.area.ui_type = 'VIEW_3D' # <-- enable for crash bpy.ops.transform.resize(value=(0.001, 0.001, 0.001), orient_type='LOCAL')

You need to use the correct context and normally you use some temporary override. Here is how it's done the old way but since some Blender 3.x you get a warning in the system console (but its still working):

DeprecationWarning: Passing in context overrides is deprecated in favor of Context.temp_override(..)

Therefore, try this code for Step 8. Overriding the context avoids the crash and also makes sure that the individual origin option works.

# Step 8: Split the mesh 'Faces by Edges'
bpy.context.area.ui_type = 'VIEW_3D'

area = [area for area in bpy.context.screen.areas if area.type == "VIEW_3D"][0] region = [region for region in area.regions if region.type == 'WINDOW'][0]

with bpy.context.temp_override(area=area, region=region): bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_mode(type='EDGE') bpy.ops.mesh.select_all(action='SELECT')

bpy.ops.mesh.edge_split()

bpy.ops.mesh.select_mode(type='FACE')
bpy.context.scene.tool_settings.transform_pivot_point = 'INDIVIDUAL_ORIGINS'
bpy.ops.transform.resize(value=(0.001, 0.001, 0.001), orient_type='LOCAL')

taiyo
  • 3,384
  • 1
  • 3
  • 18