# How to batch export shapekeys as OBJ from the active object?

I am not a programmer and I don't know what I am doing.

I want to export many shapekeys as OBJ files from an active object. Doing this manually would take an insane amount of time. Unfortunately, I haven't found an existing script that is doing this.

What I want to do: (Blender button: I dont know how to do that)

for each 'shapekey' in the 'acive object':
if shapekey is 'hidden'
1. unhide shapekey
2. export 'active object' as "shapekey's name".obj
3. hide shapekey


Updated for Blender 2.8

# Export all 'hidden' shape_keys from all 'hidden' objects in the scene.
# Only ACTIVE 'LAYERS' will export objects.

import os
import bpy

basedir = bpy.path.abspath('//')

for obj in bpy.data.objects:
if obj.hide_get():
if obj.data.shape_keys:
bpy.context.view_layer.objects.active = obj
obj.hide_set(False)
obj.select_set(True)
for k in bpy.context.active_object.data.shape_keys.key_blocks:
if k.mute:
k.mute = False
print(k.name)
bpy.ops.export_scene.obj(
filepath=os.path.join(basedir, k.name + '.obj'),
use_selection=True,
global_scale=1,
axis_forward='-Z',
axis_up='Y',
use_normals=False,
use_materials=False,
keep_vertex_order=True)
k.mute = True
obj.select_set(False)
obj.hide_set(True)

• If I understand correctly you have edited the solution into the question. It is better to have the answer as an answer even if it's your own question you are answering. This is uniform format on Stack Exchange and it makes it easier for people to find so you should post it as an answer instead of editing the question. It is not really clear for other people who are looking for a solution to the same problem. This script might seem like a failed attempt included with the question if you leave it there. It would be better if it was posted as an answer. – Martynas Žiemys Jun 9 '20 at 13:27
• I see, I didn't know that. I'll keep that in mind next time I post something. Thanks. Is it possible to "Undo" this? – kopei Jun 10 '20 at 15:46

This script will iterate over the active object's shape keys, set each in turn to 1.0 (while the others are set to 0.0) and save this as an OBJ file.

import bpy
from os.path import join

o = bpy.context.object # Reference the active object

# Change this to the actual folder you want to save your OBJ files in
exportPath = "C:/tmp/obj"

# Reset all shape keys to 0 (skipping the Basis shape on index 0
for skblock in o.data.shape_keys.key_blocks[1:]:
skblock.value = 0

# Iterate over shape key blocks and save each as an OBJ file
for skblock in o.data.shape_keys.key_blocks[1:]:
skblock.value = 1.0  # Set shape key value to max

# Set OBJ file path and Export OBJ
objFileName = skblock.name + ".obj" # File name = shapekey name
objPath = join( exportPath, objFileName )
bpy.ops.export_scene.obj( filepath = objPath, use_selection = True )

skblock.value = 0 # Reset shape key value to 0

• Thanks for your answer. Setting the shapekey to 0 is not what I need because a lot of the shapekeys have values like 0.384 for example. Hide and Unhide works perfectly for me. I think my script crashes when I run it a second time because I need to put a sys.exit() at the end? – kopei Jul 28 '17 at 14:07
• You don't need to put a sys.exit(), that will exit Blender after the script is finished. Sorry, I didn't notice you reporting the script crashes. Could it be a permissions issue? Where are you trying to save your OBJ files? Do they exist already and are being overwritten? (If so, maybe they're locked by some other program / process?) – TLousky Jul 28 '17 at 14:09

Updated script for Blender 2.8

# Export all 'hidden' shape_keys from all 'hidden' objects in the scene.
# Only ACTIVE 'LAYERS' will export objects.

import os
import bpy

basedir = bpy.path.abspath('//')

for obj in bpy.data.objects:
if obj.hide_get():
if obj.data.shape_keys:
bpy.context.view_layer.objects.active = obj
obj.hide_set(False)
obj.select_set(True)
for k in bpy.context.active_object.data.shape_keys.key_blocks:
if k.mute:
k.mute = False
print(k.name)
bpy.ops.export_scene.obj(
filepath=os.path.join(basedir, k.name + '.obj'),
use_selection=True,
global_scale=1,
axis_forward='-Z',
axis_up='Y',
use_normals=False,
use_materials=False,
keep_vertex_order=True)
k.mute = True
obj.select_set(False)
obj.hide_set(True)