0
$\begingroup$

Greetings to our awesome community.

I'm having one doubt in my python script that copy all the shapekeys from source mesh to destination mesh.

The below script is working perfectly when running inside blender python console after selecting the source mesh first and then the destination mesh,

import bpy
def copy_all_shape_keys():
    if len(bpy.context.selected_objects) == 2:
        source = bpy.context.selected_objects[1]
        dest = bpy.context.active_object
        for v in bpy.context.selected_objects:
            if v is not dest:
                source = v
                break
        
        print("Source: ", source.name)
        print("Destination: ", dest.name)
        
        if source.data.shape_keys is None:
            print("Source object has no shape keys!") 
        else:
            for idx in range(1, len(source.data.shape_keys.key_blocks)):
                source.active_shape_key_index = idx
                print("Copying Shape Key - ", source.active_shape_key.name)
                bpy.ops.object.shape_key_transfer()
copy_all_shape_keys()

But I want to run it from outside blender using python interpreter having bpy module. So,modified the above script like below,

import bpy

def init_scene():
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete(use_global=False)
    
def import_obj(filepath):
    bpy.ops.import_scene.obj(filepath=filepath,split_mode="OFF")
    bpy.ops.object.shade_smooth()
    # For some mysterious raison, this is necessary otherwise I cannot toggle shade smooth / shade flat

def import_skeleton(filepath):
    bpy.ops.import_scene.fbx(filepath=filepath)


def copy_all_shape_keys(shapekey_model_path,target_model_path,output_path):
    init_scene()
    import_skeleton(shapekey_model_path)
    source1 = bpy.context.selected_objects[0]
    source1.select_set(True)

    import_obj(target_model_path)
    dest1=bpy.context.selected_objects[0]
    source1.select_set(True)
    dest1.select_set(True)
    bpy.context.view_layer.objects.active = dest1
    print('test1:',bpy.context.selected_objects)
    if len(bpy.context.selected_objects) == 2:
        source = bpy.context.selected_objects[1]
        dest = bpy.context.active_object
        for v in bpy.context.selected_objects:
            if v is not dest:
                source = v
                break
        
        print("Source: ", source.name)
        print("Destination: ", dest.name)
        
        if source.data.shape_keys is None:
            print("Source object has no shape keys!") 
        else:
            for idx in range(1, len(source.data.shape_keys.key_blocks)):
                source.active_shape_key_index = idx
                print("Copying Shape Key - ", source.active_shape_key.name)
                bpy.ops.object.shape_key_transfer()
    print('test2:',bpy.context.selected_objects)
    print('dest shape keys:',len(dest.data.shape_keys.key_blocks))
    bpy.ops.object.select_all(action='DESELECT')
    dest.select_set(True)
    bpy.ops.export_scene.fbx(filepath=output_path, use_selection=True,use_mesh_modifiers=True,add_leaf_bones=False,bake_anim_use_nla_strips=False, bake_anim_use_all_actions=False)

shapekey_model_path='/home/my_work/blendshapes/head_blendshapes.fbx'
target_model_path='/home/my_work/meshes/head.obj'
output_path='/home/my_work/meshes/head_testshapekey.fbx'


print("Start")
copy_all_shape_keys(shapekey_model_path,target_model_path,output_path)
print("End") 

This script is also copying all the shapekeys from the source mesh to the target mesh, but deformation is not correct.

For output reference, Right one is the result I'm getting through my independent script. And, Left is the correct result, I'm getting when running the script in Blender python console,

enter image description here

Any suggestion where I'm going wrong?

$\endgroup$

1 Answer 1

0
$\begingroup$

Just tried some modifications and it's working fine.

  1. Just removed the split_mode="OFF" in import_obj().

  2. Loading source and dest mesh outside the function and passing it to

    copy_all_shape_keys()

  3. Also, removed the unnecessary source and dest assignment inside if statement i.e. if len(bpy.context.selected_objects) == 2

Here, attaching the updated script.

import bpy

def init_scene():
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete(use_global=False)
    
def import_obj(filepath):
    bpy.ops.import_scene.obj(filepath=filepath)
    bpy.ops.object.shade_smooth()
    # For some mysterious raison, this is necessary otherwise I cannot toggle shade smooth / shade flat

def import_skeleton(filepath):
    bpy.ops.import_scene.fbx(filepath=filepath)

def copy_all_shape_keys(source,dest,output_path):
    source.select_set(True)
    dest.select_set(True)
    bpy.context.view_layer.objects.active = dest
    print('test1:',bpy.context.selected_objects)
    if len(bpy.context.selected_objects) == 2:
        for v in bpy.context.selected_objects:
            if v is not dest:
                source = v
                break
        
        print("Source: ", source.name)
        print("Destination: ", dest.name)
        
        if source.data.shape_keys is None:
            print("Source object has no shape keys!") 
        else:
            for idx in range(1, len(source.data.shape_keys.key_blocks)):
                source.active_shape_key_index = idx
                print("Copying Shape Key - ", source.active_shape_key.name)
                bpy.ops.object.shape_key_transfer()
    print('test2:',bpy.context.selected_objects)
    print('dest shape keys:',len(dest.data.shape_keys.key_blocks))
    bpy.ops.object.select_all(action='DESELECT')
    dest.select_set(True)
    bpy.ops.export_scene.fbx(filepath=output_path, use_selection=True,use_mesh_modifiers=True,add_leaf_bones=False,bake_anim_use_nla_strips=False, bake_anim_use_all_actions=False)

shapekey_model_path='/home/my_work/blendshapes/head_blendshapes.fbx'
target_model_path='/home/ujjawal/my_work/meshes/head.obj'
output_path='/home/ujjawal/my_work/meshes/head_testshapekey.fbx'

init_scene()
import_skeleton(shapekey_model_path)
source= bpy.context.selected_objects[0]

import_obj(target_model_path)
dest=bpy.context.selected_objects[0]
print("Start")
#copy_all_shape_keys()
copy_all_shape_keys(source,dest,output_path)
print("End")
$\endgroup$

You must log in to answer this question.

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