0
$\begingroup$

I'm trying to write a script that will automate applying shapeKeys and subSerfs into LOD's ready for export into a game engine. It's going well so far but I'm stuck on setting the value of the shape key for a copied mesh ready to be applied.

Here is what I have so far.

import bpy
obj = bpy.context.object
objName = obj.name
i = 0

shapekeysList = [] #building an array of all available sahpeKeys

for sp in obj.data.shape_keys.key_blocks: #loop through available shape keys
    shapekeysList.append(sp) #add shapeKey name to array 
    currentShapeKey = shapekeysList[i].name #grab current shapeKey

    obj_dup = obj.copy() #duplicate selected mesh

    newName = objName+"_"+shapekeysList[i].name #generate a name for the copy

    obj_dup.data.shape_keys.key_blocks[shapekeysList[i].name].value = 1 #<--PROBLEM HERE

    obj_dup.name = newName #rename copy to match the shapeKey it'll be set to

    bpy.data.scenes[0].objects.link(obj_dup) #add copy to scene (I think)
    i += 1 #tick up for next round

So the problem is instead of just updating the currentShapeKey for just the current object it seems to loop through all objects both the copies and the original (but not wholly separate meshes).

I've also tried changing the value after it's been renamed, added to the scene and is outside the copy loop but it keeps telling me that the object doesn't have that kind of data.

This feels like such a simple problem so sorry if this is just wasting time and thanks in advance for any help you can offer.

Also tried adding this as a work around but no cigar

for sk in shapekeysList:
        obj_dup.data.shape_keys.key_blocks[shapekeysList[skCount].name].value = 0

        print ("   Current: " + shapekeysList[skCount].name)
        print ("   Target: " + shapekeysList[i].name)
        if (shapekeysList[skCount].na
me != shapekeysList[i].name):
            print("   DELETE "+shapekeysList[i].name)
            #obj_dup.data.shape_keys.key_blocks[shapekeysList[i].name].shape_key_remove()
            iIndex = obj_dup.data.shape_keys.key_blocks.keys().index(shapekeysList[i].name)
            obj_dup.active_shape_key_index = iIndex
            #bpy.ops.object.shape_key_remove()
        else:
            print("   KEEP "+shapekeysList[skCount].name)
        skCount += 1

EDIT: Okay I think I've almost got it. The script copys the mesh with shape keys that don't seem to effect each other when testing but when I try to clean out the unused shapeKeys it still seems to want to target the original mesh killing the loop after the first round leaving me with an empty original and a full copy (opposite of what I need).

import bpy

obj = bpy.context.object
objName = obj.name
spIndex = obj.active_shape_key_index
i = 0

print ("-----------------------------") #Just breaking up the consol logs

shapekeysList = [] #building an array of all available sahpeKeys
fullShapekeysList = []
x=0
for fsp in obj.data.shape_keys.key_blocks: #loop through available shape keys
    fullShapekeysList.append(fsp) #add shapeKey name to array
    print('fullShapekeysList gets: '+fsp.name)
    x += 1

for sp in obj.data.shape_keys.key_blocks: #loop through available shape keys
    shapekeysList.append(sp) #add shapeKey name to array 
    currentShapeKey = shapekeysList[i].name #grab current shapeKey
    print ("Shapekey: "+currentShapeKey) #Checking to make sure key and name below match

    obj_dup = obj.copy() #duplicate selected mesh
    obj_dup.data = obj.data.copy() #duplicate selected mesh

    newName = objName+"_"+shapekeysList[i].name #generate a name for the copy
    print ("newName: " + newName) #Just check the name will come out right

    obj_dup.data.shape_keys.key_blocks[shapekeysList[i].name].value = 1 #Set target to one

    #Convert copy to mesh
    skCount = 0
    for sk in fullShapekeysList:

        print ("   Current: " + fullShapekeysList[skCount].name)
        print ("   Target: " + fullShapekeysList[i].name)
        if (fullShapekeysList[skCount].name == fullShapekeysList[i].name):
            print("   KEEP "+fullShapekeysList[skCount].name)
        else:
            print("   DELETE "+fullShapekeysList[skCount].name)

            iIndex = obj_dup.data.shape_keys.key_blocks.keys().index(fullShapekeysList[skCount].name)
            obj_dup.active_shape_key_index = iIndex
            bpy.ops.object.shape_key_remove()
        skCount += 1

    obj_dup.name = newName #rename copy to match the shapeKey it'll be set to

    bpy.data.scenes[0].objects.link(obj_dup) #add copy to scene (I think)
    i += 1 #tick up for next round
```
$\endgroup$
  • $\begingroup$ Shape keys work like materials: there is a general list of shape keys, so your object doesn't have a shape key, but it has a link that points to that shape key. Both your objects have the same materials and the same shape keys, so to modify just one of them you need to copy the shape key as well. $\endgroup$ – Tareyes Aug 4 '19 at 16:36
  • $\begingroup$ @Tareyes Thanks, that's more help info on the problem then I've managed to dig up on the forums/docs in two day but it still doesn't really help. How exactly do I "copy the shape keys". Not asking for a handout, believe me I've tried figuring it out on my own but there seem to be painfully little info on this online. I also tried a work around where I looped through removing unneeded shapekeys from the copys but results were.. nonsensical.. (edited into op) $\endgroup$ – Robert Porter Aug 5 '19 at 11:55
  • $\begingroup$ Or maybe I'm just missing the requisite magic search keywords.. $\endgroup$ – Robert Porter Aug 5 '19 at 12:02
  • $\begingroup$ I'm sorry, this week I'm on holiday, so I can't really help, but if you are willing to wait until then I'll try to write something down. In the mean time, try to use other methods to copy that object that copy the data blocks as well. Another useful thing is also to do manually in the UI what your script should do, looking in the INFO panel for the commands that Blender used $\endgroup$ – Tareyes Aug 6 '19 at 15:51
  • $\begingroup$ @Tareyes It's cool, pretty sure I've got it figured out now. I'll update the post when the script is done so hopefully this comes up if anyone is searching for a similar problem in future. $\endgroup$ – Robert Porter Aug 8 '19 at 4:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.